From 89c181ded11b6d51c34ca27c5df5905c976207c7 Mon Sep 17 00:00:00 2001 From: vladislavbelov Date: Wed, 15 Dec 2021 06:43:41 +0000 Subject: [PATCH] Encapsulates information about GL inside device. Commented By: Stan Differential Revision: https://code.wildfiregames.com/D4375 This was SVN commit r26072. --- build/premake/premake5.lua | 2 + source/lib/ogl.cpp | 1 - source/lib/ogl.h | 4 +- source/lib/sysdep/gfx.cpp | 92 ---------- source/lib/sysdep/gfx.h | 46 ----- source/lib/sysdep/os/osx/osx.cpp | 3 +- source/lib/sysdep/os/win/wgfx.cpp | 3 +- source/ps/GameSetup/GameSetup.cpp | 8 +- source/ps/GameSetup/HWDetect.cpp | 6 +- source/ps/GameSetup/HWDetect.h | 4 +- source/ps/Util.cpp | 40 +---- source/ps/VideoMode.cpp | 34 ++-- source/ps/VideoMode.h | 21 ++- source/renderer/Renderer.cpp | 2 + source/renderer/backend/gl/Device.cpp | 166 ++++++++++++++++++ source/renderer/backend/gl/Device.h | 68 +++++++ .../Handlers/GraphicsSetupHandlers.cpp | 2 +- 17 files changed, 294 insertions(+), 208 deletions(-) delete mode 100644 source/lib/sysdep/gfx.cpp delete mode 100644 source/lib/sysdep/gfx.h create mode 100644 source/renderer/backend/gl/Device.cpp create mode 100644 source/renderer/backend/gl/Device.h diff --git a/build/premake/premake5.lua b/build/premake/premake5.lua index 70ada68f8e..9cf5248263 100644 --- a/build/premake/premake5.lua +++ b/build/premake/premake5.lua @@ -772,6 +772,8 @@ function setup_all_libs () "graphics", "graphics/scripting", "renderer", + "renderer/backend", + "renderer/backend/gl", "renderer/scripting", "third_party/mikktspace", "third_party/ogre3d_preprocessor" diff --git a/source/lib/ogl.cpp b/source/lib/ogl.cpp index 575a189383..144885ffdc 100644 --- a/source/lib/ogl.cpp +++ b/source/lib/ogl.cpp @@ -33,7 +33,6 @@ #include "lib/external_libraries/libsdl.h" #include "lib/debug.h" -#include "lib/sysdep/gfx.h" #include "lib/res/h_mgr.h" #if MSC_VERSION diff --git a/source/lib/ogl.h b/source/lib/ogl.h index f0a8a846c4..27c68de7da 100644 --- a/source/lib/ogl.h +++ b/source/lib/ogl.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -32,7 +32,7 @@ /** * initialization: import extension function pointers and do feature detect. - * call before using any other function, and after each video mode change. + * call before using any other function. * fails if OpenGL not ready for use. **/ extern void ogl_Init(); diff --git a/source/lib/sysdep/gfx.cpp b/source/lib/sysdep/gfx.cpp deleted file mode 100644 index 1aa7f68827..0000000000 --- a/source/lib/sysdep/gfx.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright (C) 2020 Wildfire Games. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* - * graphics card detection. - */ - -#include "precompiled.h" -#include "lib/sysdep/gfx.h" - -#include "lib/external_libraries/libsdl.h" -#include "lib/ogl.h" - -#if OS_WIN -# include "lib/sysdep/os/win/wgfx.h" -#endif - -#include - -namespace gfx { - -std::wstring CardName() -{ - // GL_VENDOR+GL_RENDERER are good enough here, so we don't use WMI to detect the cards. - // On top of that WMI can cause crashes with Nvidia Optimus and some netbooks - // see http://trac.wildfiregames.com/ticket/1952 - // http://trac.wildfiregames.com/ticket/1575 - wchar_t cardName[128]; - const char* vendor = (const char*)glGetString(GL_VENDOR); - const char* renderer = (const char*)glGetString(GL_RENDERER); - // (happens if called before ogl_Init or between glBegin and glEnd.) - if(!vendor || !renderer) - return L""; - swprintf_s(cardName, ARRAY_SIZE(cardName), L"%hs %hs", vendor, renderer); - - // remove crap from vendor names. (don't dare touch the model name - - // it's too risky, there are too many different strings) -#define SHORTEN(what, charsToKeep)\ - if(!wcsncmp(cardName, what, ARRAY_SIZE(what)-1))\ - memmove(cardName+charsToKeep, cardName+ARRAY_SIZE(what)-1, (wcslen(cardName)-(ARRAY_SIZE(what)-1)+1)*sizeof(wchar_t)); - SHORTEN(L"ATI Technologies Inc.", 3); - SHORTEN(L"NVIDIA Corporation", 6); - SHORTEN(L"S3 Graphics", 2); // returned by EnumDisplayDevices - SHORTEN(L"S3 Graphics, Incorporated", 2); // returned by GL_VENDOR -#undef SHORTEN - - return cardName; -} - - -std::wstring DriverInfo() -{ - std::wstring driverInfo; -#if OS_WIN - driverInfo = wgfx_DriverInfo(); - if(driverInfo.empty()) -#endif - { - const char* version = (const char*)glGetString(GL_VERSION); - if(version) - { - // add "OpenGL" to differentiate this from the real driver version - // (returned by platform-specific detect routines). - driverInfo = std::wstring(L"OpenGL ") + std::wstring(version, version+strlen(version)); - } - } - - if(driverInfo.empty()) - return L"(unknown)"; - return driverInfo; -} - -} // namespace gfx diff --git a/source/lib/sysdep/gfx.h b/source/lib/sysdep/gfx.h deleted file mode 100644 index 7440dd2da9..0000000000 --- a/source/lib/sysdep/gfx.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Copyright (C) 2020 Wildfire Games. - * - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of this software and associated documentation files (the - * "Software"), to deal in the Software without restriction, including - * without limitation the rights to use, copy, modify, merge, publish, - * distribute, sublicense, and/or sell copies of the Software, and to - * permit persons to whom the Software is furnished to do so, subject to - * the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY - * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, - * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -/* - * graphics card detection. - */ - -#ifndef INCLUDED_GFX -#define INCLUDED_GFX - -namespace gfx { - -/** - * @return description of graphics card, -* or L"" if unknown. - **/ -LIB_API std::wstring CardName(); - -/** - * @return string describing the graphics driver and its version, - * or L"" if unknown. - **/ -LIB_API std::wstring DriverInfo(); - -} // namespace gfx - -#endif // #ifndef INCLUDED_GFX diff --git a/source/lib/sysdep/os/osx/osx.cpp b/source/lib/sysdep/os/osx/osx.cpp index cfe03faac3..97359dd997 100644 --- a/source/lib/sysdep/os/osx/osx.cpp +++ b/source/lib/sysdep/os/osx/osx.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -24,7 +24,6 @@ #include "lib/lib.h" #include "lib/sysdep/sysdep.h" -#include "lib/sysdep/gfx.h" #include "lib/utf8.h" #include "osx_bundle.h" diff --git a/source/lib/sysdep/os/win/wgfx.cpp b/source/lib/sysdep/os/win/wgfx.cpp index af436a6569..f415afa1b0 100644 --- a/source/lib/sysdep/os/win/wgfx.cpp +++ b/source/lib/sysdep/os/win/wgfx.cpp @@ -1,4 +1,4 @@ -/* Copyright (C) 2020 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * * Permission is hereby granted, free of charge, to any person obtaining * a copy of this software and associated documentation files (the @@ -27,7 +27,6 @@ #include "precompiled.h" #include "lib/sysdep/os/win/wgfx.h" -#include "lib/sysdep/gfx.h" #include "lib/sysdep/os/win/wdll_ver.h" #include "lib/sysdep/os/win/wutil.h" diff --git a/source/ps/GameSetup/GameSetup.cpp b/source/ps/GameSetup/GameSetup.cpp index 330cb61a67..ff1cadc2c3 100644 --- a/source/ps/GameSetup/GameSetup.cpp +++ b/source/ps/GameSetup/GameSetup.cpp @@ -931,15 +931,9 @@ void InitGraphics(const CmdLineArgs& args, int flags, const std::vector& i g_GUI = new CGUIManager(); - // (must come after SetVideoMode, since it calls ogl_Init) CStr8 renderPath = "default"; CFG_GET_VAL("renderpath", renderPath); - if ((ogl_HaveExtensions(0, "GL_ARB_vertex_program", "GL_ARB_fragment_program", nullptr) // ARB - && ogl_HaveExtensions(0, "GL_ARB_vertex_shader", "GL_ARB_fragment_shader", nullptr)) // GLSL - || !ogl_HaveExtension("GL_ARB_vertex_buffer_object") // VBO - || ogl_HaveExtensions(0, "GL_ARB_multitexture", "GL_EXT_draw_range_elements", nullptr) - || (!ogl_HaveExtension("GL_EXT_framebuffer_object") && !ogl_HaveExtension("GL_ARB_framebuffer_object")) - || RenderPathEnum::FromString(renderPath) == FIXED) + if (RenderPathEnum::FromString(renderPath) == FIXED) { // It doesn't make sense to continue working here, because we're not // able to display anything. diff --git a/source/ps/GameSetup/HWDetect.cpp b/source/ps/GameSetup/HWDetect.cpp index 47b109b4ed..93f248987e 100644 --- a/source/ps/GameSetup/HWDetect.cpp +++ b/source/ps/GameSetup/HWDetect.cpp @@ -25,7 +25,6 @@ #include "lib/res/graphics/ogl_tex.h" #include "lib/posix/posix_utsname.h" #include "lib/sysdep/cpu.h" -#include "lib/sysdep/gfx.h" #include "lib/sysdep/numa.h" #include "lib/sysdep/os_cpu.h" #if ARCH_X86_X64 @@ -43,6 +42,7 @@ #include "ps/scripting/JSInterface_Debug.h" #include "ps/UserReport.h" #include "ps/VideoMode.h" +#include "renderer/backend/gl/Device.h" #include "scriptinterface/FunctionWrapper.h" #include "scriptinterface/JSON.h" #include "scriptinterface/Object.h" @@ -160,8 +160,8 @@ void RunHardwareDetection() Script::SetProperty(rq, settings, "build_gcc", (int)GCC_VERSION); Script::SetProperty(rq, settings, "build_clang", (int)CLANG_VERSION); - Script::SetProperty(rq, settings, "gfx_card", gfx::CardName()); - Script::SetProperty(rq, settings, "gfx_drv_ver", gfx::DriverInfo()); + Script::SetProperty(rq, settings, "gfx_card", g_VideoMode.GetBackendDevice()->GetName()); + Script::SetProperty(rq, settings, "gfx_drv_ver", g_VideoMode.GetBackendDevice()->GetDriverInformation()); #if CONFIG2_AUDIO if (g_SoundManager) { diff --git a/source/ps/GameSetup/HWDetect.h b/source/ps/GameSetup/HWDetect.h index 7b0069bd4d..7346a470cf 100644 --- a/source/ps/GameSetup/HWDetect.h +++ b/source/ps/GameSetup/HWDetect.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2010 Wildfire Games. +/* Copyright (C) 2021 Wildfire Games. * This file is part of 0 A.D. * * 0 A.D. is free software: you can redistribute it and/or modify @@ -21,7 +21,7 @@ /** * Runs hardware-detection script to adjust default config settings * and/or emit warnings depending on the user's system configuration. - * This must only be called after ogl_Init. + * This must only be called after backend device creation. */ void RunHardwareDetection(); diff --git a/source/ps/Util.cpp b/source/ps/Util.cpp index dbf64a4290..f2fc2ebb34 100644 --- a/source/ps/Util.cpp +++ b/source/ps/Util.cpp @@ -28,7 +28,6 @@ #if ARCH_X86_X64 #include "lib/sysdep/arch/x86_x64/topology.h" #endif -#include "lib/sysdep/gfx.h" #include "lib/sysdep/cpu.h" #include "lib/sysdep/os_cpu.h" #include "lib/sysdep/smbios.h" @@ -44,6 +43,7 @@ #include "ps/GameSetup/GameSetup.h" #include "ps/Pyrogenesis.h" #include "ps/VideoMode.h" +#include "renderer/backend/gl/Device.h" #include "renderer/Renderer.h" #if CONFIG2_AUDIO @@ -53,29 +53,6 @@ #include #include -static std::string SplitExts(const char *exts) -{ - std::string str = exts; - std::string ret = ""; - size_t idx = str.find_first_of(" "); - while(idx != std::string::npos) - { - if(idx >= str.length() - 1) - { - ret += str; - break; - } - - ret += str.substr(0, idx); - ret += "\n"; - str = str.substr(idx + 1); - idx = str.find_first_of(" "); - } - - return ret; -} - - void WriteSystemInfo() { TIMER(L"write_sys_info"); @@ -126,10 +103,8 @@ void WriteSystemInfo() fprintf(f, "Memory : %u MiB; %u MiB free\n", (unsigned)os_cpu_MemorySize(), (unsigned)os_cpu_MemoryAvailable()); // graphics - const std::wstring cardName = gfx::CardName(); - const std::wstring driverInfo = gfx::DriverInfo(); - fprintf(f, "Graphics Card : %ls\n", cardName.c_str()); - fprintf(f, "OpenGL Drivers : %s; %ls\n", glGetString(GL_VERSION), driverInfo.c_str()); + fprintf(f, "Video Card : %s\n", g_VideoMode.GetBackendDevice()->GetName().c_str()); + fprintf(f, "Video Driver : %s\n", g_VideoMode.GetBackendDevice()->GetDriverInformation().c_str()); fprintf(f, "Video Mode : %dx%d:%d\n", g_VideoMode.GetXRes(), g_VideoMode.GetYRes(), g_VideoMode.GetBPP()); #if CONFIG2_AUDIO @@ -147,9 +122,12 @@ void WriteSystemInfo() #endif // OpenGL extensions (write them last, since it's a lot of text) - const char* exts = ogl_ExtensionString(); - if (!exts) exts = "{unknown}"; - fprintf(f, "\nOpenGL Extensions: \n%s\n", SplitExts(exts).c_str()); + fprintf(f, "\nBackend Extensions:\n"); + if (g_VideoMode.GetBackendDevice()->GetExtensions().empty()) + fprintf(f, "{unknown}\n"); + else + for (const std::string& extension : g_VideoMode.GetBackendDevice()->GetExtensions()) + fprintf(f, "%s\n", extension.c_str()); // System Management BIOS (even more text than OpenGL extensions) std::string smbios = SMBIOS::StringizeStructures(SMBIOS::GetStructures()); diff --git a/source/ps/VideoMode.cpp b/source/ps/VideoMode.cpp index c8c30fdca8..6283eb4242 100644 --- a/source/ps/VideoMode.cpp +++ b/source/ps/VideoMode.cpp @@ -24,7 +24,6 @@ #include "lib/config2.h" #include "lib/external_libraries/libsdl.h" #include "lib/ogl.h" -#include "lib/sysdep/gfx.h" #include "lib/tex/tex.h" #include "ps/CConsole.h" #include "ps/CLogger.h" @@ -34,6 +33,7 @@ #include "ps/Game.h" #include "ps/GameSetup/Config.h" #include "ps/Pyrogenesis.h" +#include "renderer/backend/gl/Device.h" #include "renderer/Renderer.h" namespace @@ -286,11 +286,15 @@ bool CVideoMode::SetVideoMode(int w, int h, int bpp, bool fullscreen) return false; } - m_Context = SDL_GL_CreateContext(m_Window); - if (!m_Context) +#if OS_WIN + // We need to set the window for an error dialog. + wutil_SetAppWindow(m_Window); +#endif + + if (!CreateBackendDevice(true)) { - LOGERROR("SetVideoMode failed in SDL_GL_CreateContext: %dx%d:%d %d (\"%s\")", - w, h, bpp, fullscreen ? 1 : 0, SDL_GetError()); + LOGERROR("SetVideoMode failed in backend device creation: %dx%d:%d %d", + w, h, bpp, fullscreen ? 1 : 0); return false; } } @@ -330,11 +334,6 @@ bool CVideoMode::SetVideoMode(int w, int h, int bpp, bool fullscreen) else SDL_SetWindowGrab(m_Window, SDL_FALSE); -#if OS_WIN - // We need to set the window for an error dialog. - wutil_SetAppWindow(m_Window); -#endif - m_IsFullscreen = fullscreen; g_xres = m_CurrentW; @@ -468,9 +467,6 @@ bool CVideoMode::InitSDL() atexit(SDL_Quit); // End work around. - ogl_Init(); // required after each mode change - // (TODO: does that mean we need to call this when toggling fullscreen later?) - m_IsInitialised = true; if (!m_ConfigFullscreen) @@ -505,11 +501,7 @@ void CVideoMode::Shutdown() m_IsFullscreen = false; m_IsInitialised = false; - if (m_Context) - { - SDL_GL_DeleteContext(m_Context); - m_Context = nullptr; - } + m_BackendDevice.reset(); if (m_Window) { SDL_DestroyWindow(m_Window); @@ -517,6 +509,12 @@ void CVideoMode::Shutdown() } } +bool CVideoMode::CreateBackendDevice(const bool createSDLContext) +{ + m_BackendDevice = Renderer::Backend::GL::CDevice::Create(createSDLContext ? m_Window : nullptr); + return !!m_BackendDevice; +} + bool CVideoMode::ResizeWindow(int w, int h) { ENSURE(m_IsInitialised); diff --git a/source/ps/VideoMode.h b/source/ps/VideoMode.h index c2883f2e5a..d80cc9e4a8 100644 --- a/source/ps/VideoMode.h +++ b/source/ps/VideoMode.h @@ -25,6 +25,17 @@ typedef struct SDL_Window SDL_Window; typedef void* SDL_GLContext; +namespace Renderer +{ +namespace Backend +{ +namespace GL +{ +class CDevice; +} +} +} + class CVideoMode { public: @@ -53,6 +64,12 @@ public: */ void Shutdown(); + /** + * Creates a backend device. Also we use wxWidgets in Atlas so we don't need + * to create one for that case. + */ + bool CreateBackendDevice(const bool createSDLContext); + /** * Resize the SDL window and associated graphics stuff to the new size. */ @@ -112,6 +129,8 @@ public: Backend GetBackend() const { return m_Backend; } + Renderer::Backend::GL::CDevice* GetBackendDevice() { return m_BackendDevice.get(); } + private: void ReadConfig(); int GetBestBPP(); @@ -125,7 +144,6 @@ private: bool m_IsInitialised = false; SDL_Window* m_Window = nullptr; - SDL_GLContext m_Context = nullptr; // Initial desktop settings. // Frequency is in Hz, and BPP means bits per pixels (not bytes per pixels). @@ -167,6 +185,7 @@ private: std::unique_ptr m_Cursor; Backend m_Backend = Backend::GL; + std::unique_ptr m_BackendDevice; }; extern CVideoMode g_VideoMode; diff --git a/source/renderer/Renderer.cpp b/source/renderer/Renderer.cpp index ffef38aa3c..5985fd7139 100644 --- a/source/renderer/Renderer.cpp +++ b/source/renderer/Renderer.cpp @@ -1388,8 +1388,10 @@ void CRenderer::OnSwapBuffers() { bool checkGLErrorAfterSwap = false; CFG_GET_VAL("gl.checkerrorafterswap", checkGLErrorAfterSwap); +#if defined(NDEBUG) if (!checkGLErrorAfterSwap) return; +#endif PROFILE3("error check"); // We have to check GL errors after SwapBuffer to avoid possible // synchronizations during rendering. diff --git a/source/renderer/backend/gl/Device.cpp b/source/renderer/backend/gl/Device.cpp new file mode 100644 index 0000000000..e3781fc209 --- /dev/null +++ b/source/renderer/backend/gl/Device.cpp @@ -0,0 +1,166 @@ +/* Copyright (C) 2021 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#include "precompiled.h" + +#include "Device.h" + +#include "lib/external_libraries/libsdl.h" +#include "lib/ogl.h" +#include "ps/CLogger.h" + +#if OS_WIN +#include "lib/sysdep/os/win/wgfx.h" +#endif + +#include +#include +#include + +namespace Renderer +{ + +namespace Backend +{ + +namespace GL +{ + +namespace +{ + +std::string GetNameImpl() +{ + // GL_VENDOR+GL_RENDERER are good enough here, so we don't use WMI to detect the cards. + // On top of that WMI can cause crashes with Nvidia Optimus and some netbooks + // see http://trac.wildfiregames.com/ticket/1952 + // http://trac.wildfiregames.com/ticket/1575 + char cardName[128]; + const char* vendor = reinterpret_cast(glGetString(GL_VENDOR)); + const char* renderer = reinterpret_cast(glGetString(GL_RENDERER)); + // Happens if called before GL initialization. + if (!vendor || !renderer) + return {}; + sprintf_s(cardName, std::size(cardName), "%s %s", vendor, renderer); + + // Remove crap from vendor names. (don't dare touch the model name - + // it's too risky, there are too many different strings). +#define SHORTEN(what, charsToKeep) \ + if (!strncmp(cardName, what, std::size(what) - 1)) \ + memmove(cardName + charsToKeep, cardName + std::size(what) - 1, (strlen(cardName) - (std::size(what) - 1) + 1) * sizeof(char)); + SHORTEN("ATI Technologies Inc.", 3); + SHORTEN("NVIDIA Corporation", 6); + SHORTEN("S3 Graphics", 2); // returned by EnumDisplayDevices + SHORTEN("S3 Graphics, Incorporated", 2); // returned by GL_VENDOR +#undef SHORTEN + + return cardName; +} + +std::string GetVersionImpl() +{ + return reinterpret_cast(glGetString(GL_VERSION)); +} + +std::string GetDriverInformationImpl() +{ + const std::string version = GetVersionImpl(); + + std::string driverInfo; +#if OS_WIN + driverInfo = CStrW(wgfx_DriverInfo()).ToUTF8(); + if (driverInfo.empty()) +#endif + { + if (!version.empty()) + { + // Add "OpenGL" to differentiate this from the real driver version + // (returned by platform-specific detect routines). + driverInfo = std::string("OpenGL ") + version; + } + } + + if (driverInfo.empty()) + return version; + return version + " " + driverInfo; +} + +std::vector GetExtensionsImpl() +{ + std::vector extensions; + const std::string exts = ogl_ExtensionString(); + boost::split(extensions, exts, boost::algorithm::is_space(), boost::token_compress_on); + std::sort(extensions.begin(), extensions.end()); + return extensions; +} + +} // anonymous namespace + +// static +std::unique_ptr CDevice::Create(SDL_Window* window) +{ + std::unique_ptr device(new CDevice()); + + if (window) + { + device->m_Context = SDL_GL_CreateContext(window); + if (!device->m_Context) + { + LOGERROR("SDL_GL_CreateContext failed: '%s'", SDL_GetError()); + return nullptr; + } + } + + ogl_Init(); + + if ((ogl_HaveExtensions(0, "GL_ARB_vertex_program", "GL_ARB_fragment_program", nullptr) // ARB + && ogl_HaveExtensions(0, "GL_ARB_vertex_shader", "GL_ARB_fragment_shader", nullptr)) // GLSL + || !ogl_HaveExtension("GL_ARB_vertex_buffer_object") // VBO + || ogl_HaveExtensions(0, "GL_ARB_multitexture", "GL_EXT_draw_range_elements", nullptr) + || (!ogl_HaveExtension("GL_EXT_framebuffer_object") && !ogl_HaveExtension("GL_ARB_framebuffer_object"))) + { + // It doesn't make sense to continue working here, because we're not + // able to display anything. + DEBUG_DISPLAY_FATAL_ERROR( + L"Your graphics card doesn't appear to be fully compatible with OpenGL shaders." + L" The game does not support pre-shader graphics cards." + L" You are advised to try installing newer drivers and/or upgrade your graphics card." + L" For more information, please see http://www.wildfiregames.com/forum/index.php?showtopic=16734" + ); + } + + device->m_Name = GetNameImpl(); + device->m_Version = GetVersionImpl(); + device->m_DriverInformation = GetDriverInformationImpl(); + device->m_Extensions = GetExtensionsImpl(); + + return device; +} + +CDevice::CDevice() = default; + +CDevice::~CDevice() +{ + if (m_Context) + SDL_GL_DeleteContext(m_Context); +} + +} // namespace GL + +} // namespace Backend + +} // namespace Renderer diff --git a/source/renderer/backend/gl/Device.h b/source/renderer/backend/gl/Device.h new file mode 100644 index 0000000000..6d3635e278 --- /dev/null +++ b/source/renderer/backend/gl/Device.h @@ -0,0 +1,68 @@ +/* Copyright (C) 2021 Wildfire Games. + * This file is part of 0 A.D. + * + * 0 A.D. is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * 0 A.D. is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with 0 A.D. If not, see . + */ + +#ifndef INCLUDED_RENDERER_BACKEND_GL_DEVICE +#define INCLUDED_RENDERER_BACKEND_GL_DEVICE + +#include "lib/external_libraries/libsdl.h" + +#include +#include +#include + +namespace Renderer +{ + +namespace Backend +{ + +namespace GL +{ + +class CDevice +{ +public: + ~CDevice(); + + /** + * Creates the GL device and the GL context for the window if it presents. + */ + static std::unique_ptr Create(SDL_Window* window); + + const std::string& GetName() const { return m_Name; } + const std::string& GetVersion() const { return m_Version; } + const std::string& GetDriverInformation() const { return m_DriverInformation; } + const std::vector& GetExtensions() const { return m_Extensions; } + +private: + CDevice(); + + SDL_GLContext m_Context = nullptr; + + std::string m_Name; + std::string m_Version; + std::string m_DriverInformation; + std::vector m_Extensions; +}; + +} // namespace GL + +} // namespace Backend + +} // namespace Renderer + +#endif // INCLUDED_RENDERER_BACKEND_GL_DEVICE diff --git a/source/tools/atlas/GameInterface/Handlers/GraphicsSetupHandlers.cpp b/source/tools/atlas/GameInterface/Handlers/GraphicsSetupHandlers.cpp index cebdd6c203..85ceb8088a 100644 --- a/source/tools/atlas/GameInterface/Handlers/GraphicsSetupHandlers.cpp +++ b/source/tools/atlas/GameInterface/Handlers/GraphicsSetupHandlers.cpp @@ -111,7 +111,7 @@ MESSAGEHANDLER(InitGraphics) { UNUSED2(msg); - ogl_Init(); + g_VideoMode.CreateBackendDevice(false); InitGraphics(g_AtlasGameLoop->args, g_InitFlags, {});