LCOV - code coverage report
Current view: top level - source/renderer/backend/gl - Device.cpp (source / functions) Hit Total Coverage
Test: 0 A.D. test coverage report Lines: 1 442 0.2 %
Date: 2023-01-19 00:18:29 Functions: 2 28 7.1 %

          Line data    Source code
       1             : /* Copyright (C) 2023 Wildfire Games.
       2             :  * This file is part of 0 A.D.
       3             :  *
       4             :  * 0 A.D. is free software: you can redistribute it and/or modify
       5             :  * it under the terms of the GNU General Public License as published by
       6             :  * the Free Software Foundation, either version 2 of the License, or
       7             :  * (at your option) any later version.
       8             :  *
       9             :  * 0 A.D. is distributed in the hope that it will be useful,
      10             :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      11             :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      12             :  * GNU General Public License for more details.
      13             :  *
      14             :  * You should have received a copy of the GNU General Public License
      15             :  * along with 0 A.D.  If not, see <http://www.gnu.org/licenses/>.
      16             :  */
      17             : 
      18             : #include "precompiled.h"
      19             : 
      20             : #include "Device.h"
      21             : 
      22             : #include "lib/external_libraries/libsdl.h"
      23             : #include "lib/hash.h"
      24             : #include "lib/ogl.h"
      25             : #include "ps/CLogger.h"
      26             : #include "ps/ConfigDB.h"
      27             : #include "ps/Profile.h"
      28             : #include "renderer/backend/gl/DeviceCommandContext.h"
      29             : #include "renderer/backend/gl/PipelineState.h"
      30             : #include "renderer/backend/gl/Texture.h"
      31             : #include "scriptinterface/JSON.h"
      32             : #include "scriptinterface/Object.h"
      33             : #include "scriptinterface/ScriptInterface.h"
      34             : #include "scriptinterface/ScriptRequest.h"
      35             : 
      36             : #if OS_WIN
      37             : #include "lib/sysdep/os/win/wgfx.h"
      38             : 
      39             : // We can't include wutil directly because GL headers conflict with Windows
      40             : // until we use a proper GL loader.
      41             : extern void* wutil_GetAppHDC();
      42             : #endif
      43             : 
      44             : #include <algorithm>
      45             : #include <boost/algorithm/string/classification.hpp>
      46             : #include <boost/algorithm/string/split.hpp>
      47             : 
      48             : #if !CONFIG2_GLES && (defined(SDL_VIDEO_DRIVER_X11) || defined(SDL_VIDEO_DRIVER_WAYLAND))
      49             : 
      50             : #if defined(SDL_VIDEO_DRIVER_X11)
      51             : #include <glad/glx.h>
      52             : #endif
      53             : #if defined(SDL_VIDEO_DRIVER_WAYLAND)
      54             : #include <glad/egl.h>
      55             : #endif
      56             : #include <SDL_syswm.h>
      57             : 
      58             : #endif // !CONFIG2_GLES && (defined(SDL_VIDEO_DRIVER_X11) || defined(SDL_VIDEO_DRIVER_WAYLAND))
      59             : 
      60             : namespace Renderer
      61             : {
      62             : 
      63             : namespace Backend
      64             : {
      65             : 
      66             : namespace GL
      67             : {
      68             : 
      69             : namespace
      70             : {
      71             : 
      72           0 : std::string GetNameImpl()
      73             : {
      74             :     // GL_VENDOR+GL_RENDERER are good enough here, so we don't use WMI to detect the cards.
      75             :     // On top of that WMI can cause crashes with Nvidia Optimus and some netbooks
      76             :     // see http://trac.wildfiregames.com/ticket/1952
      77             :     //     http://trac.wildfiregames.com/ticket/1575
      78             :     char cardName[128];
      79           0 :     const char* vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR));
      80           0 :     const char* renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER));
      81             :     // Happens if called before GL initialization.
      82           0 :     if (!vendor || !renderer)
      83           0 :         return {};
      84           0 :     sprintf_s(cardName, std::size(cardName), "%s %s", vendor, renderer);
      85             : 
      86             :     // Remove crap from vendor names. (don't dare touch the model name -
      87             :     // it's too risky, there are too many different strings).
      88             : #define SHORTEN(what, charsToKeep) \
      89             :     if (!strncmp(cardName, what, std::size(what) - 1)) \
      90             :         memmove(cardName + charsToKeep, cardName + std::size(what) - 1, (strlen(cardName) - (std::size(what) - 1) + 1) * sizeof(char));
      91           0 :     SHORTEN("ATI Technologies Inc.", 3);
      92           0 :     SHORTEN("NVIDIA Corporation", 6);
      93           0 :     SHORTEN("S3 Graphics", 2);                    // returned by EnumDisplayDevices
      94           0 :     SHORTEN("S3 Graphics, Incorporated", 2);  // returned by GL_VENDOR
      95             : #undef SHORTEN
      96             : 
      97           0 :     return cardName;
      98             : }
      99             : 
     100           0 : std::string GetVersionImpl()
     101             : {
     102           0 :     return reinterpret_cast<const char*>(glGetString(GL_VERSION));
     103             : }
     104             : 
     105           0 : std::string GetDriverInformationImpl()
     106             : {
     107           0 :     const std::string version = GetVersionImpl();
     108             : 
     109           0 :     std::string driverInfo;
     110             : #if OS_WIN
     111             :     driverInfo = CStrW(wgfx_DriverInfo()).ToUTF8();
     112             :     if (driverInfo.empty())
     113             : #endif
     114             :     {
     115           0 :         if (!version.empty())
     116             :         {
     117             :             // Add "OpenGL" to differentiate this from the real driver version
     118             :             // (returned by platform-specific detect routines).
     119           0 :             driverInfo = std::string("OpenGL ") + version;
     120             :         }
     121             :     }
     122             : 
     123           0 :     if (driverInfo.empty())
     124           0 :         return version;
     125           0 :     return version + " " + driverInfo;
     126             : }
     127             : 
     128           0 : std::vector<std::string> GetExtensionsImpl()
     129             : {
     130           0 :     std::vector<std::string> extensions;
     131           0 :     const std::string exts = ogl_ExtensionString();
     132           0 :     boost::split(extensions, exts, boost::algorithm::is_space(), boost::token_compress_on);
     133           0 :     std::sort(extensions.begin(), extensions.end());
     134           0 :     return extensions;
     135             : }
     136             : 
     137           0 : void GLAD_API_PTR OnDebugMessage(
     138             :     GLenum source, GLenum type, GLuint id, GLenum severity,
     139             :     GLsizei UNUSED(length), const GLchar* message, const void* UNUSED(user_param))
     140             : {
     141           0 :     std::string debugSource = "unknown";
     142           0 :     std::string debugType = "unknown";
     143           0 :     std::string debugSeverity = "unknown";
     144             : 
     145           0 :     switch (source)
     146             :     {
     147           0 :     case GL_DEBUG_SOURCE_API:
     148           0 :         debugSource = "the API";
     149           0 :         break;
     150           0 :     case GL_DEBUG_SOURCE_WINDOW_SYSTEM:
     151           0 :         debugSource = "the window system";
     152           0 :         break;
     153           0 :     case GL_DEBUG_SOURCE_SHADER_COMPILER:
     154           0 :         debugSource = "the shader compiler";
     155           0 :         break;
     156           0 :     case GL_DEBUG_SOURCE_THIRD_PARTY:
     157           0 :         debugSource = "a third party";
     158           0 :         break;
     159           0 :     case GL_DEBUG_SOURCE_APPLICATION:
     160           0 :         debugSource = "the application";
     161           0 :         break;
     162           0 :     case GL_DEBUG_SOURCE_OTHER:
     163           0 :         debugSource = "somewhere";
     164           0 :         break;
     165             :     }
     166             : 
     167           0 :     switch (type)
     168             :     {
     169           0 :     case GL_DEBUG_TYPE_ERROR:
     170           0 :         debugType = "error";
     171           0 :         break;
     172           0 :     case GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR:
     173           0 :         debugType = "deprecated behaviour";
     174           0 :         break;
     175           0 :     case GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR:
     176           0 :         debugType = "undefined behaviour";
     177           0 :         break;
     178           0 :     case GL_DEBUG_TYPE_PORTABILITY:
     179           0 :         debugType = "portability";
     180           0 :         break;
     181           0 :     case GL_DEBUG_TYPE_PERFORMANCE:
     182           0 :         debugType = "performance";
     183           0 :         break;
     184           0 :     case GL_DEBUG_TYPE_OTHER:
     185           0 :         debugType = "other";
     186           0 :         break;
     187           0 :     case GL_DEBUG_TYPE_MARKER:
     188           0 :         debugType = "marker";
     189           0 :         break;
     190           0 :     case GL_DEBUG_TYPE_PUSH_GROUP:
     191           0 :         debugType = "push group";
     192           0 :         break;
     193           0 :     case GL_DEBUG_TYPE_POP_GROUP:
     194           0 :         debugType = "pop group";
     195           0 :         break;
     196             :     }
     197             : 
     198           0 :     switch (severity)
     199             :     {
     200           0 :     case GL_DEBUG_SEVERITY_HIGH:
     201           0 :         debugSeverity = "high";
     202           0 :         break;
     203           0 :     case GL_DEBUG_SEVERITY_MEDIUM:
     204           0 :         debugSeverity = "medium";
     205           0 :         break;
     206           0 :     case GL_DEBUG_SEVERITY_LOW:
     207           0 :         debugSeverity = "low";
     208           0 :         break;
     209           0 :     case GL_DEBUG_SEVERITY_NOTIFICATION:
     210           0 :         debugSeverity = "notification";
     211           0 :         break;
     212             :     }
     213             : 
     214           0 :     if (severity == GL_DEBUG_SEVERITY_NOTIFICATION)
     215             :     {
     216           0 :         debug_printf(
     217             :             "OpenGL | %s: %s source: %s id %u: %s\n", debugSeverity.c_str(), debugType.c_str(), debugSource.c_str(), id, message);
     218             :     }
     219             :     else
     220             :     {
     221           0 :         LOGWARNING(
     222             :             "OpenGL | %s: %s source: %s id %u: %s\n", debugSeverity.c_str(), debugType.c_str(), debugSource.c_str(), id, message);
     223             :     }
     224           0 : }
     225             : 
     226             : } // anonymous namespace
     227             : 
     228             : // static
     229           0 : std::unique_ptr<IDevice> CDevice::Create(SDL_Window* window, const bool arb)
     230             : {
     231           0 :     std::unique_ptr<CDevice> device(new CDevice());
     232             : 
     233           0 :     if (window)
     234             :     {
     235             :         // According to https://wiki.libsdl.org/SDL_CreateWindow we don't need to
     236             :         // call SDL_GL_LoadLibrary if we have a window with SDL_WINDOW_OPENGL,
     237             :         // because it'll be called internally for the first created window.
     238           0 :         device->m_Window = window;
     239           0 :         device->m_Context = SDL_GL_CreateContext(device->m_Window);
     240           0 :         if (!device->m_Context)
     241             :         {
     242           0 :             LOGERROR("SDL_GL_CreateContext failed: '%s'", SDL_GetError());
     243           0 :             return nullptr;
     244             :         }
     245           0 :         SDL_GL_GetDrawableSize(window, &device->m_SurfaceDrawableWidth, &device->m_SurfaceDrawableHeight);
     246             : 
     247             : #if OS_WIN
     248             :         ogl_Init(SDL_GL_GetProcAddress, wutil_GetAppHDC());
     249             : #elif (defined(SDL_VIDEO_DRIVER_X11) || defined(SDL_VIDEO_DRIVER_WAYLAND)) && !CONFIG2_GLES
     250             :         SDL_SysWMinfo wminfo;
     251             :         // The info structure must be initialized with the SDL version.
     252           0 :         SDL_VERSION(&wminfo.version);
     253           0 :         if (!SDL_GetWindowWMInfo(window, &wminfo))
     254             :         {
     255           0 :             LOGERROR("Failed to query SDL WM info: %s", SDL_GetError());
     256           0 :             return nullptr;
     257             :         }
     258           0 :         switch (wminfo.subsystem)
     259             :         {
     260             : #if defined(SDL_VIDEO_DRIVER_WAYLAND)
     261           0 :         case SDL_SYSWM_WAYLAND:
     262             :             // TODO: maybe we need to load X11 functions
     263             :             // dynamically as well.
     264           0 :             ogl_Init(SDL_GL_GetProcAddress,
     265           0 :                 GetWaylandDisplay(device->m_Window),
     266           0 :                 static_cast<int>(wminfo.subsystem));
     267           0 :             break;
     268             : #endif
     269             : #if defined(SDL_VIDEO_DRIVER_X11)
     270           0 :         case SDL_SYSWM_X11:
     271           0 :             ogl_Init(SDL_GL_GetProcAddress,
     272           0 :                 GetX11Display(device->m_Window),
     273           0 :                 static_cast<int>(wminfo.subsystem));
     274           0 :             break;
     275             : #endif
     276           0 :         default:
     277           0 :             ogl_Init(SDL_GL_GetProcAddress, nullptr,
     278           0 :                 static_cast<int>(wminfo.subsystem));
     279           0 :             break;
     280             :         }
     281             : #else
     282             :         ogl_Init(SDL_GL_GetProcAddress);
     283             : #endif
     284             :     }
     285             :     else
     286             :     {
     287             : #if OS_WIN
     288             :         ogl_Init(SDL_GL_GetProcAddress, wutil_GetAppHDC());
     289             : #elif (defined(SDL_VIDEO_DRIVER_X11) || defined(SDL_VIDEO_DRIVER_WAYLAND)) && !CONFIG2_GLES
     290           0 :         bool initialized = false;
     291             :         // Currently we don't have access to the backend type without
     292             :         // the window. So we use hack to detect X11.
     293             : #if defined(SDL_VIDEO_DRIVER_X11)
     294           0 :         Display* display = XOpenDisplay(NULL);
     295           0 :         if (display)
     296             :         {
     297           0 :             ogl_Init(SDL_GL_GetProcAddress, display, static_cast<int>(SDL_SYSWM_X11));
     298           0 :             initialized = true;
     299             :         }
     300             : #endif
     301             : #if defined(SDL_VIDEO_DRIVER_WAYLAND)
     302           0 :         if (!initialized)
     303             :         {
     304             :             // glad will find default EGLDisplay internally.
     305           0 :             ogl_Init(SDL_GL_GetProcAddress, nullptr, static_cast<int>(SDL_SYSWM_WAYLAND));
     306           0 :             initialized = true;
     307             :         }
     308             : #endif
     309           0 :         if (!initialized)
     310             :         {
     311           0 :             LOGERROR("Can't initialize GL");
     312           0 :             return nullptr;
     313             :         }
     314             : #else
     315             :         ogl_Init(SDL_GL_GetProcAddress);
     316             : #endif
     317             : 
     318             : #if OS_WIN || defined(SDL_VIDEO_DRIVER_X11) && !CONFIG2_GLES
     319             :         // Hack to stop things looking very ugly when scrolling in Atlas.
     320           0 :         ogl_SetVsyncEnabled(true);
     321             : #endif
     322             :     }
     323             : 
     324             :     // If we don't have GL2.0 then we don't have GLSL in core.
     325           0 :     if (!arb && !ogl_HaveVersion(2, 0))
     326           0 :         return nullptr;
     327             : 
     328           0 :     if ((ogl_HaveExtensions(0, "GL_ARB_vertex_program", "GL_ARB_fragment_program", nullptr) // ARB
     329           0 :         && !ogl_HaveVersion(2, 0)) // GLSL
     330           0 :         || !ogl_HaveExtension("GL_ARB_vertex_buffer_object") // VBO
     331           0 :         || ogl_HaveExtensions(0, "GL_ARB_multitexture", "GL_EXT_draw_range_elements", nullptr)
     332           0 :         || (!ogl_HaveExtension("GL_EXT_framebuffer_object") && !ogl_HaveExtension("GL_ARB_framebuffer_object")))
     333             :     {
     334             :         // It doesn't make sense to continue working here, because we're not
     335             :         // able to display anything.
     336           0 :         DEBUG_DISPLAY_FATAL_ERROR(
     337             :             L"Your graphics card doesn't appear to be fully compatible with OpenGL shaders."
     338             :             L" The game does not support pre-shader graphics cards."
     339             :             L" You are advised to try installing newer drivers and/or upgrade your graphics card."
     340             :             L" For more information, please see http://www.wildfiregames.com/forum/index.php?showtopic=16734"
     341             :         );
     342             :     }
     343             : 
     344           0 :     device->m_ARB = arb;
     345             : 
     346           0 :     device->m_Name = GetNameImpl();
     347           0 :     device->m_Version = GetVersionImpl();
     348           0 :     device->m_DriverInformation = GetDriverInformationImpl();
     349           0 :     device->m_Extensions = GetExtensionsImpl();
     350             : 
     351             :     // Set packing parameters for uploading and downloading data.
     352           0 :     glPixelStorei(GL_PACK_ALIGNMENT, 1);
     353           0 :     glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
     354             : 
     355           0 :     glEnable(GL_TEXTURE_2D);
     356             : 
     357           0 :     if (arb)
     358             :     {
     359             : #if !CONFIG2_GLES
     360           0 :         glEnable(GL_VERTEX_PROGRAM_ARB);
     361           0 :         glEnable(GL_FRAGMENT_PROGRAM_ARB);
     362             : #endif
     363             :     }
     364             : 
     365             : #if CONFIG2_GLES
     366             :     device->m_UseFramebufferInvalidating = ogl_HaveExtension("GL_EXT_discard_framebuffer");
     367             : #else
     368           0 :     device->m_UseFramebufferInvalidating = !arb && ogl_HaveExtension("GL_ARB_invalidate_subdata");
     369             : #endif
     370             : 
     371           0 :     Capabilities& capabilities = device->m_Capabilities;
     372           0 :     capabilities.ARBShaders = !ogl_HaveExtensions(0, "GL_ARB_vertex_program", "GL_ARB_fragment_program", nullptr);
     373           0 :     if (capabilities.ARBShaders)
     374           0 :         capabilities.ARBShadersShadow = ogl_HaveExtension("GL_ARB_fragment_program_shadow");
     375           0 :     capabilities.computeShaders = ogl_HaveVersion(4, 3) || ogl_HaveExtension("GL_ARB_compute_shader");
     376             : #if CONFIG2_GLES
     377             :     // Some GLES implementations have GL_EXT_texture_compression_dxt1
     378             :     // but that only supports DXT1 so we can't use it.
     379             :     capabilities.S3TC = ogl_HaveExtensions(0, "GL_EXT_texture_compression_s3tc", nullptr) == 0;
     380             : #else
     381             :     // Note: we don't bother checking for GL_S3_s3tc - it is incompatible
     382             :     // and irrelevant (was never widespread).
     383           0 :     capabilities.S3TC = ogl_HaveExtensions(0, "GL_ARB_texture_compression", "GL_EXT_texture_compression_s3tc", nullptr) == 0;
     384             : #endif
     385             : #if CONFIG2_GLES
     386             :     capabilities.multisampling = false;
     387             :     capabilities.maxSampleCount = 1;
     388             : #else
     389           0 :     capabilities.multisampling =
     390           0 :         ogl_HaveVersion(3, 3) &&
     391           0 :         ogl_HaveExtension("GL_ARB_multisample") &&
     392           0 :         ogl_HaveExtension("GL_ARB_texture_multisample");
     393           0 :     if (capabilities.multisampling)
     394             :     {
     395             :         // By default GL_MULTISAMPLE should be enabled, but enable it for buggy drivers.
     396           0 :         glEnable(GL_MULTISAMPLE);
     397           0 :         GLint maxSamples = 1;
     398           0 :         glGetIntegerv(GL_MAX_SAMPLES, &maxSamples);
     399           0 :         capabilities.maxSampleCount = maxSamples;
     400             :     }
     401             : #endif
     402           0 :     capabilities.anisotropicFiltering = ogl_HaveExtension("GL_EXT_texture_filter_anisotropic");
     403           0 :     if (capabilities.anisotropicFiltering)
     404             :     {
     405           0 :         GLfloat maxAnisotropy = 1.0f;
     406           0 :         glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAnisotropy);
     407           0 :         capabilities.maxAnisotropy = maxAnisotropy;
     408             :     }
     409           0 :     GLint maxTextureSize = 1024;
     410           0 :     glGetIntegerv(GL_MAX_TEXTURE_SIZE, &maxTextureSize);
     411           0 :     capabilities.maxTextureSize = maxTextureSize;
     412             : 
     413             : #if CONFIG2_GLES
     414             :     const bool isDebugInCore = ogl_HaveVersion(3, 2);
     415             : #else
     416           0 :     const bool isDebugInCore = ogl_HaveVersion(4, 3);
     417             : #endif
     418           0 :     const bool hasDebug = isDebugInCore || ogl_HaveExtension("GL_KHR_debug");
     419           0 :     if (hasDebug)
     420             :     {
     421             : #ifdef NDEBUG
     422             :         bool enableDebugMessages = false;
     423             :         CFG_GET_VAL("renderer.backend.debugmessages", enableDebugMessages);
     424             :         capabilities.debugLabels = false;
     425             :         CFG_GET_VAL("renderer.backend.debuglabels", capabilities.debugLabels);
     426             :         capabilities.debugScopedLabels = false;
     427             :         CFG_GET_VAL("renderer.backend.debugscopedlabels", capabilities.debugScopedLabels);
     428             : #else
     429           0 :         const bool enableDebugMessages = true;
     430           0 :         capabilities.debugLabels = true;
     431           0 :         capabilities.debugScopedLabels = true;
     432             : #endif
     433             :         if (enableDebugMessages)
     434             :         {
     435           0 :             glEnable(GL_DEBUG_OUTPUT);
     436             : #if !CONFIG2_GLES
     437           0 :             glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
     438             : #else
     439             : #warning GLES without GL_DEBUG_OUTPUT_SYNCHRONOUS might call the callback from different threads which might be unsafe.
     440             : #endif
     441           0 :             glDebugMessageCallback(OnDebugMessage, nullptr);
     442             : 
     443             :             // Filter out our own debug group messages
     444           0 :             const GLuint id = 0x0AD;
     445           0 :             glDebugMessageControl(
     446             :                 GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PUSH_GROUP, GL_DONT_CARE, 1, &id, GL_FALSE);
     447           0 :             glDebugMessageControl(
     448             :                 GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_POP_GROUP, GL_DONT_CARE, 1, &id, GL_FALSE);
     449             :         }
     450             :     }
     451             : 
     452             : #if CONFIG2_GLES
     453             :     capabilities.instancing = false;
     454             : #else
     455           0 :     capabilities.instancing =
     456           0 :         !device->m_ARB &&
     457           0 :         (ogl_HaveVersion(3, 3) ||
     458           0 :         (ogl_HaveExtension("GL_ARB_draw_instanced") &&
     459           0 :         ogl_HaveExtension("GL_ARB_instanced_arrays")));
     460             : #endif
     461             : 
     462           0 :     return device;
     463             : }
     464             : 
     465             : CDevice::CDevice() = default;
     466             : 
     467           0 : CDevice::~CDevice()
     468             : {
     469           0 :     if (m_Context)
     470           0 :         SDL_GL_DeleteContext(m_Context);
     471           0 : }
     472             : 
     473           0 : void CDevice::Report(const ScriptRequest& rq, JS::HandleValue settings)
     474             : {
     475           0 :     const char* errstr = "(error)";
     476             : 
     477           0 :     Script::SetProperty(rq, settings, "name", m_ARB ? "glarb" : "gl");
     478             : 
     479             : #define INTEGER(id) do { \
     480             :     GLint i = -1; \
     481             :     glGetIntegerv(GL_##id, &i); \
     482             :     if (ogl_SquelchError(GL_INVALID_ENUM)) \
     483             :         Script::SetProperty(rq, settings, "GL_" #id, errstr); \
     484             :     else \
     485             :         Script::SetProperty(rq, settings, "GL_" #id, i); \
     486             :     } while (false)
     487             : 
     488             : #define INTEGER2(id) do { \
     489             :     GLint i[2] = { -1, -1 }; \
     490             :     glGetIntegerv(GL_##id, i); \
     491             :     if (ogl_SquelchError(GL_INVALID_ENUM)) { \
     492             :         Script::SetProperty(rq, settings, "GL_" #id "[0]", errstr); \
     493             :         Script::SetProperty(rq, settings, "GL_" #id "[1]", errstr); \
     494             :     } else { \
     495             :         Script::SetProperty(rq, settings, "GL_" #id "[0]", i[0]); \
     496             :         Script::SetProperty(rq, settings, "GL_" #id "[1]", i[1]); \
     497             :     } \
     498             :     } while (false)
     499             : 
     500             : #define FLOAT(id) do { \
     501             :     GLfloat f = std::numeric_limits<GLfloat>::quiet_NaN(); \
     502             :     glGetFloatv(GL_##id, &f); \
     503             :     if (ogl_SquelchError(GL_INVALID_ENUM)) \
     504             :         Script::SetProperty(rq, settings, "GL_" #id, errstr); \
     505             :     else \
     506             :         Script::SetProperty(rq, settings, "GL_" #id, f); \
     507             :     } while (false)
     508             : 
     509             : #define FLOAT2(id) do { \
     510             :     GLfloat f[2] = { std::numeric_limits<GLfloat>::quiet_NaN(), std::numeric_limits<GLfloat>::quiet_NaN() }; \
     511             :     glGetFloatv(GL_##id, f); \
     512             :     if (ogl_SquelchError(GL_INVALID_ENUM)) { \
     513             :         Script::SetProperty(rq, settings, "GL_" #id "[0]", errstr); \
     514             :         Script::SetProperty(rq, settings, "GL_" #id "[1]", errstr); \
     515             :     } else { \
     516             :         Script::SetProperty(rq, settings, "GL_" #id "[0]", f[0]); \
     517             :         Script::SetProperty(rq, settings, "GL_" #id "[1]", f[1]); \
     518             :     } \
     519             :     } while (false)
     520             : 
     521             : #define STRING(id) do { \
     522             :     const char* c = (const char*)glGetString(GL_##id); \
     523             :     if (!c) c = ""; \
     524             :     if (ogl_SquelchError(GL_INVALID_ENUM)) c = errstr; \
     525             :     Script::SetProperty(rq, settings, "GL_" #id, std::string(c)); \
     526             :     }  while (false)
     527             : 
     528             : #define QUERY(target, pname) do { \
     529             :     GLint i = -1; \
     530             :     glGetQueryivARB(GL_##target, GL_##pname, &i); \
     531             :     if (ogl_SquelchError(GL_INVALID_ENUM)) \
     532             :         Script::SetProperty(rq, settings, "GL_" #target ".GL_" #pname, errstr); \
     533             :     else \
     534             :         Script::SetProperty(rq, settings, "GL_" #target ".GL_" #pname, i); \
     535             :     } while (false)
     536             : 
     537             : #define VERTEXPROGRAM(id) do { \
     538             :     GLint i = -1; \
     539             :     glGetProgramivARB(GL_VERTEX_PROGRAM_ARB, GL_##id, &i); \
     540             :     if (ogl_SquelchError(GL_INVALID_ENUM)) \
     541             :         Script::SetProperty(rq, settings, "GL_VERTEX_PROGRAM_ARB.GL_" #id, errstr); \
     542             :     else \
     543             :         Script::SetProperty(rq, settings, "GL_VERTEX_PROGRAM_ARB.GL_" #id, i); \
     544             :     } while (false)
     545             : 
     546             : #define FRAGMENTPROGRAM(id) do { \
     547             :     GLint i = -1; \
     548             :     glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, GL_##id, &i); \
     549             :     if (ogl_SquelchError(GL_INVALID_ENUM)) \
     550             :         Script::SetProperty(rq, settings, "GL_FRAGMENT_PROGRAM_ARB.GL_" #id, errstr); \
     551             :     else \
     552             :         Script::SetProperty(rq, settings, "GL_FRAGMENT_PROGRAM_ARB.GL_" #id, i); \
     553             :     } while (false)
     554             : 
     555             : #define BOOL(id) INTEGER(id)
     556             : 
     557           0 :     ogl_WarnIfError();
     558             : 
     559             :     // Core OpenGL 1.3:
     560             :     // (We don't bother checking extension strings for anything older than 1.3;
     561             :     // it'll just produce harmless warnings)
     562           0 :     STRING(VERSION);
     563           0 :     STRING(VENDOR);
     564           0 :     STRING(RENDERER);
     565           0 :     STRING(EXTENSIONS);
     566             : 
     567             : #if !CONFIG2_GLES
     568           0 :     INTEGER(MAX_CLIP_PLANES);
     569             : #endif
     570           0 :     INTEGER(SUBPIXEL_BITS);
     571             : #if !CONFIG2_GLES
     572           0 :     INTEGER(MAX_3D_TEXTURE_SIZE);
     573             : #endif
     574           0 :     INTEGER(MAX_TEXTURE_SIZE);
     575           0 :     INTEGER(MAX_CUBE_MAP_TEXTURE_SIZE);
     576           0 :     INTEGER2(MAX_VIEWPORT_DIMS);
     577             : 
     578             : #if !CONFIG2_GLES
     579           0 :     BOOL(RGBA_MODE);
     580           0 :     BOOL(INDEX_MODE);
     581           0 :     BOOL(DOUBLEBUFFER);
     582           0 :     BOOL(STEREO);
     583             : #endif
     584             : 
     585           0 :     FLOAT2(ALIASED_POINT_SIZE_RANGE);
     586           0 :     FLOAT2(ALIASED_LINE_WIDTH_RANGE);
     587             : #if !CONFIG2_GLES
     588           0 :     INTEGER(MAX_ELEMENTS_INDICES);
     589           0 :     INTEGER(MAX_ELEMENTS_VERTICES);
     590           0 :     INTEGER(MAX_TEXTURE_UNITS);
     591             : #endif
     592           0 :     INTEGER(SAMPLE_BUFFERS);
     593           0 :     INTEGER(SAMPLES);
     594             :     // TODO: compressed texture formats
     595           0 :     INTEGER(RED_BITS);
     596           0 :     INTEGER(GREEN_BITS);
     597           0 :     INTEGER(BLUE_BITS);
     598           0 :     INTEGER(ALPHA_BITS);
     599             : #if !CONFIG2_GLES
     600           0 :     INTEGER(INDEX_BITS);
     601             : #endif
     602           0 :     INTEGER(DEPTH_BITS);
     603           0 :     INTEGER(STENCIL_BITS);
     604             : 
     605             : #if !CONFIG2_GLES
     606             : 
     607             :     // Core OpenGL 2.0 (treated as extensions):
     608             : 
     609           0 :     if (ogl_HaveExtension("GL_EXT_texture_lod_bias"))
     610             :     {
     611           0 :         FLOAT(MAX_TEXTURE_LOD_BIAS_EXT);
     612             :     }
     613             : 
     614           0 :     if (ogl_HaveExtension("GL_ARB_occlusion_query"))
     615             :     {
     616           0 :         QUERY(SAMPLES_PASSED, QUERY_COUNTER_BITS);
     617             :     }
     618             : 
     619           0 :     if (ogl_HaveExtension("GL_ARB_shading_language_100"))
     620             :     {
     621           0 :         STRING(SHADING_LANGUAGE_VERSION_ARB);
     622             :     }
     623             : 
     624           0 :     if (ogl_HaveExtension("GL_ARB_vertex_shader"))
     625             :     {
     626           0 :         INTEGER(MAX_VERTEX_ATTRIBS_ARB);
     627           0 :         INTEGER(MAX_VERTEX_UNIFORM_COMPONENTS_ARB);
     628           0 :         INTEGER(MAX_VARYING_FLOATS_ARB);
     629           0 :         INTEGER(MAX_COMBINED_TEXTURE_IMAGE_UNITS_ARB);
     630           0 :         INTEGER(MAX_VERTEX_TEXTURE_IMAGE_UNITS_ARB);
     631             :     }
     632             : 
     633           0 :     if (ogl_HaveExtension("GL_ARB_fragment_shader"))
     634             :     {
     635           0 :         INTEGER(MAX_FRAGMENT_UNIFORM_COMPONENTS_ARB);
     636             :     }
     637             : 
     638           0 :     if (ogl_HaveExtension("GL_ARB_vertex_shader") || ogl_HaveExtension("GL_ARB_fragment_shader") ||
     639           0 :         ogl_HaveExtension("GL_ARB_vertex_program") || ogl_HaveExtension("GL_ARB_fragment_program"))
     640             :     {
     641           0 :         INTEGER(MAX_TEXTURE_IMAGE_UNITS_ARB);
     642           0 :         INTEGER(MAX_TEXTURE_COORDS_ARB);
     643             :     }
     644             : 
     645           0 :     if (ogl_HaveExtension("GL_ARB_draw_buffers"))
     646             :     {
     647           0 :         INTEGER(MAX_DRAW_BUFFERS_ARB);
     648             :     }
     649             : 
     650             :     // Core OpenGL 3.0:
     651             : 
     652           0 :     if (ogl_HaveExtension("GL_EXT_gpu_shader4"))
     653             :     {
     654           0 :         INTEGER(MIN_PROGRAM_TEXEL_OFFSET_EXT); // no _EXT version of these in glext.h
     655           0 :         INTEGER(MAX_PROGRAM_TEXEL_OFFSET_EXT);
     656             :     }
     657             : 
     658           0 :     if (ogl_HaveExtension("GL_EXT_framebuffer_object"))
     659             :     {
     660           0 :         INTEGER(MAX_COLOR_ATTACHMENTS_EXT);
     661           0 :         INTEGER(MAX_RENDERBUFFER_SIZE_EXT);
     662             :     }
     663             : 
     664           0 :     if (ogl_HaveExtension("GL_EXT_framebuffer_multisample"))
     665             :     {
     666           0 :         INTEGER(MAX_SAMPLES_EXT);
     667             :     }
     668             : 
     669           0 :     if (ogl_HaveExtension("GL_EXT_texture_array"))
     670             :     {
     671           0 :         INTEGER(MAX_ARRAY_TEXTURE_LAYERS_EXT);
     672             :     }
     673             : 
     674           0 :     if (ogl_HaveExtension("GL_EXT_transform_feedback"))
     675             :     {
     676           0 :         INTEGER(MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS_EXT);
     677           0 :         INTEGER(MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS_EXT);
     678           0 :         INTEGER(MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS_EXT);
     679             :     }
     680             : 
     681             : 
     682             :     // Other interesting extensions:
     683             : 
     684           0 :     if (ogl_HaveExtension("GL_EXT_timer_query") || ogl_HaveExtension("GL_ARB_timer_query"))
     685             :     {
     686           0 :         QUERY(TIME_ELAPSED, QUERY_COUNTER_BITS);
     687             :     }
     688             : 
     689           0 :     if (ogl_HaveExtension("GL_ARB_timer_query"))
     690             :     {
     691           0 :         QUERY(TIMESTAMP, QUERY_COUNTER_BITS);
     692             :     }
     693             : 
     694           0 :     if (ogl_HaveExtension("GL_EXT_texture_filter_anisotropic"))
     695             :     {
     696           0 :         FLOAT(MAX_TEXTURE_MAX_ANISOTROPY_EXT);
     697             :     }
     698             : 
     699           0 :     if (ogl_HaveExtension("GL_ARB_texture_rectangle"))
     700             :     {
     701           0 :         INTEGER(MAX_RECTANGLE_TEXTURE_SIZE_ARB);
     702             :     }
     703             : 
     704           0 :     if (m_ARB)
     705             :     {
     706           0 :         if (ogl_HaveExtension("GL_ARB_vertex_program") || ogl_HaveExtension("GL_ARB_fragment_program"))
     707             :         {
     708           0 :             INTEGER(MAX_PROGRAM_MATRICES_ARB);
     709           0 :             INTEGER(MAX_PROGRAM_MATRIX_STACK_DEPTH_ARB);
     710             :         }
     711             : 
     712           0 :         if (ogl_HaveExtension("GL_ARB_vertex_program"))
     713             :         {
     714           0 :             VERTEXPROGRAM(MAX_PROGRAM_ENV_PARAMETERS_ARB);
     715           0 :             VERTEXPROGRAM(MAX_PROGRAM_LOCAL_PARAMETERS_ARB);
     716           0 :             VERTEXPROGRAM(MAX_PROGRAM_INSTRUCTIONS_ARB);
     717           0 :             VERTEXPROGRAM(MAX_PROGRAM_TEMPORARIES_ARB);
     718           0 :             VERTEXPROGRAM(MAX_PROGRAM_PARAMETERS_ARB);
     719           0 :             VERTEXPROGRAM(MAX_PROGRAM_ATTRIBS_ARB);
     720           0 :             VERTEXPROGRAM(MAX_PROGRAM_ADDRESS_REGISTERS_ARB);
     721           0 :             VERTEXPROGRAM(MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB);
     722           0 :             VERTEXPROGRAM(MAX_PROGRAM_NATIVE_TEMPORARIES_ARB);
     723           0 :             VERTEXPROGRAM(MAX_PROGRAM_NATIVE_PARAMETERS_ARB);
     724           0 :             VERTEXPROGRAM(MAX_PROGRAM_NATIVE_ATTRIBS_ARB);
     725           0 :             VERTEXPROGRAM(MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB);
     726             : 
     727           0 :             if (ogl_HaveExtension("GL_ARB_fragment_program"))
     728             :             {
     729             :                 // The spec seems to say these should be supported, but
     730             :                 // Mesa complains about them so let's not bother
     731             :                 /*
     732             :                 VERTEXPROGRAM(MAX_PROGRAM_ALU_INSTRUCTIONS_ARB);
     733             :                 VERTEXPROGRAM(MAX_PROGRAM_TEX_INSTRUCTIONS_ARB);
     734             :                 VERTEXPROGRAM(MAX_PROGRAM_TEX_INDIRECTIONS_ARB);
     735             :                 VERTEXPROGRAM(MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB);
     736             :                 VERTEXPROGRAM(MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB);
     737             :                 VERTEXPROGRAM(MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB);
     738             :                 */
     739             :             }
     740             :         }
     741             : 
     742           0 :         if (ogl_HaveExtension("GL_ARB_fragment_program"))
     743             :         {
     744           0 :             FRAGMENTPROGRAM(MAX_PROGRAM_ENV_PARAMETERS_ARB);
     745           0 :             FRAGMENTPROGRAM(MAX_PROGRAM_LOCAL_PARAMETERS_ARB);
     746           0 :             FRAGMENTPROGRAM(MAX_PROGRAM_INSTRUCTIONS_ARB);
     747           0 :             FRAGMENTPROGRAM(MAX_PROGRAM_ALU_INSTRUCTIONS_ARB);
     748           0 :             FRAGMENTPROGRAM(MAX_PROGRAM_TEX_INSTRUCTIONS_ARB);
     749           0 :             FRAGMENTPROGRAM(MAX_PROGRAM_TEX_INDIRECTIONS_ARB);
     750           0 :             FRAGMENTPROGRAM(MAX_PROGRAM_TEMPORARIES_ARB);
     751           0 :             FRAGMENTPROGRAM(MAX_PROGRAM_PARAMETERS_ARB);
     752           0 :             FRAGMENTPROGRAM(MAX_PROGRAM_ATTRIBS_ARB);
     753           0 :             FRAGMENTPROGRAM(MAX_PROGRAM_NATIVE_INSTRUCTIONS_ARB);
     754           0 :             FRAGMENTPROGRAM(MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB);
     755           0 :             FRAGMENTPROGRAM(MAX_PROGRAM_NATIVE_TEX_INSTRUCTIONS_ARB);
     756           0 :             FRAGMENTPROGRAM(MAX_PROGRAM_NATIVE_TEX_INDIRECTIONS_ARB);
     757           0 :             FRAGMENTPROGRAM(MAX_PROGRAM_NATIVE_TEMPORARIES_ARB);
     758           0 :             FRAGMENTPROGRAM(MAX_PROGRAM_NATIVE_PARAMETERS_ARB);
     759           0 :             FRAGMENTPROGRAM(MAX_PROGRAM_NATIVE_ATTRIBS_ARB);
     760             : 
     761           0 :             if (ogl_HaveExtension("GL_ARB_vertex_program"))
     762             :             {
     763             :                 // The spec seems to say these should be supported, but
     764             :                 // Intel drivers on Windows complain about them so let's not bother
     765             :                 /*
     766             :                 FRAGMENTPROGRAM(MAX_PROGRAM_ADDRESS_REGISTERS_ARB);
     767             :                 FRAGMENTPROGRAM(MAX_PROGRAM_NATIVE_ADDRESS_REGISTERS_ARB);
     768             :                 */
     769             :             }
     770             :         }
     771             :     }
     772             : 
     773           0 :     if (ogl_HaveExtension("GL_ARB_geometry_shader4"))
     774             :     {
     775           0 :         INTEGER(MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_ARB);
     776           0 :         INTEGER(MAX_GEOMETRY_OUTPUT_VERTICES_ARB);
     777           0 :         INTEGER(MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_ARB);
     778           0 :         INTEGER(MAX_GEOMETRY_UNIFORM_COMPONENTS_ARB);
     779           0 :         INTEGER(MAX_GEOMETRY_VARYING_COMPONENTS_ARB);
     780           0 :         INTEGER(MAX_VERTEX_VARYING_COMPONENTS_ARB);
     781             :     }
     782             : 
     783             : #else // CONFIG2_GLES
     784             : 
     785             :     // Core OpenGL ES 2.0:
     786             : 
     787             :     STRING(SHADING_LANGUAGE_VERSION);
     788             :     INTEGER(MAX_VERTEX_ATTRIBS);
     789             :     INTEGER(MAX_VERTEX_UNIFORM_VECTORS);
     790             :     INTEGER(MAX_VARYING_VECTORS);
     791             :     INTEGER(MAX_COMBINED_TEXTURE_IMAGE_UNITS);
     792             :     INTEGER(MAX_VERTEX_TEXTURE_IMAGE_UNITS);
     793             :     INTEGER(MAX_FRAGMENT_UNIFORM_VECTORS);
     794             :     INTEGER(MAX_TEXTURE_IMAGE_UNITS);
     795             :     INTEGER(MAX_RENDERBUFFER_SIZE);
     796             : 
     797             : #endif // CONFIG2_GLES
     798             : 
     799             : 
     800             : // TODO: Support OpenGL platforms which don't use GLX as well.
     801             : #if defined(SDL_VIDEO_DRIVER_X11) && !CONFIG2_GLES
     802             : 
     803             : #define GLXQCR_INTEGER(id) do { \
     804             :     unsigned int i = UINT_MAX; \
     805             :     if (glXQueryCurrentRendererIntegerMESA(id, &i)) \
     806             :         Script::SetProperty(rq, settings, #id, i); \
     807             :     } while (false)
     808             : 
     809             : #define GLXQCR_INTEGER2(id) do { \
     810             :     unsigned int i[2] = { UINT_MAX, UINT_MAX }; \
     811             :     if (glXQueryCurrentRendererIntegerMESA(id, i)) { \
     812             :         Script::SetProperty(rq, settings, #id "[0]", i[0]); \
     813             :         Script::SetProperty(rq, settings, #id "[1]", i[1]); \
     814             :     } \
     815             :     } while (false)
     816             : 
     817             : #define GLXQCR_INTEGER3(id) do { \
     818             :     unsigned int i[3] = { UINT_MAX, UINT_MAX, UINT_MAX }; \
     819             :     if (glXQueryCurrentRendererIntegerMESA(id, i)) { \
     820             :         Script::SetProperty(rq, settings, #id "[0]", i[0]); \
     821             :         Script::SetProperty(rq, settings, #id "[1]", i[1]); \
     822             :         Script::SetProperty(rq, settings, #id "[2]", i[2]); \
     823             :     } \
     824             :     } while (false)
     825             : 
     826             : #define GLXQCR_STRING(id) do { \
     827             :     const char* str = glXQueryCurrentRendererStringMESA(id); \
     828             :     if (str) \
     829             :         Script::SetProperty(rq, settings, #id ".string", str); \
     830             :     } while (false)
     831             : 
     832             : 
     833             :     SDL_SysWMinfo wminfo;
     834           0 :     SDL_VERSION(&wminfo.version);
     835           0 :     const int ret = SDL_GetWindowWMInfo(m_Window, &wminfo);
     836           0 :     if (ret && wminfo.subsystem == SDL_SYSWM_X11)
     837             :     {
     838           0 :         Display* dpy = wminfo.info.x11.display;
     839           0 :         int scrnum = DefaultScreen(dpy);
     840             : 
     841           0 :         const char* glxexts = glXQueryExtensionsString(dpy, scrnum);
     842             : 
     843           0 :         Script::SetProperty(rq, settings, "glx_extensions", glxexts);
     844             : 
     845           0 :         if (strstr(glxexts, "GLX_MESA_query_renderer") && glXQueryCurrentRendererIntegerMESA && glXQueryCurrentRendererStringMESA)
     846             :         {
     847           0 :             GLXQCR_INTEGER(GLX_RENDERER_VENDOR_ID_MESA);
     848           0 :             GLXQCR_INTEGER(GLX_RENDERER_DEVICE_ID_MESA);
     849           0 :             GLXQCR_INTEGER3(GLX_RENDERER_VERSION_MESA);
     850           0 :             GLXQCR_INTEGER(GLX_RENDERER_ACCELERATED_MESA);
     851           0 :             GLXQCR_INTEGER(GLX_RENDERER_VIDEO_MEMORY_MESA);
     852           0 :             GLXQCR_INTEGER(GLX_RENDERER_UNIFIED_MEMORY_ARCHITECTURE_MESA);
     853           0 :             GLXQCR_INTEGER(GLX_RENDERER_PREFERRED_PROFILE_MESA);
     854           0 :             GLXQCR_INTEGER2(GLX_RENDERER_OPENGL_CORE_PROFILE_VERSION_MESA);
     855           0 :             GLXQCR_INTEGER2(GLX_RENDERER_OPENGL_COMPATIBILITY_PROFILE_VERSION_MESA);
     856           0 :             GLXQCR_INTEGER2(GLX_RENDERER_OPENGL_ES_PROFILE_VERSION_MESA);
     857           0 :             GLXQCR_INTEGER2(GLX_RENDERER_OPENGL_ES2_PROFILE_VERSION_MESA);
     858           0 :             GLXQCR_STRING(GLX_RENDERER_VENDOR_ID_MESA);
     859           0 :             GLXQCR_STRING(GLX_RENDERER_DEVICE_ID_MESA);
     860             :         }
     861             :     }
     862             : #endif // SDL_VIDEO_DRIVER_X11
     863           0 : }
     864             : 
     865           0 : std::unique_ptr<IDeviceCommandContext> CDevice::CreateCommandContext()
     866             : {
     867           0 :     std::unique_ptr<CDeviceCommandContext> commandContet = CDeviceCommandContext::Create(this);
     868           0 :     m_ActiveCommandContext = commandContet.get();
     869           0 :     return commandContet;
     870             : }
     871             : 
     872           0 : std::unique_ptr<IGraphicsPipelineState> CDevice::CreateGraphicsPipelineState(
     873             :     const SGraphicsPipelineStateDesc& pipelineStateDesc)
     874             : {
     875           0 :     return CGraphicsPipelineState::Create(this, pipelineStateDesc);
     876             : }
     877             : 
     878           0 : std::unique_ptr<IVertexInputLayout> CDevice::CreateVertexInputLayout(
     879             :     const PS::span<const SVertexAttributeFormat> attributes)
     880             : {
     881           0 :     return std::make_unique<CVertexInputLayout>(this, attributes);
     882             : }
     883             : 
     884           0 : std::unique_ptr<ITexture> CDevice::CreateTexture(
     885             :     const char* name, const ITexture::Type type, const uint32_t usage,
     886             :     const Format format, const uint32_t width, const uint32_t height,
     887             :     const Sampler::Desc& defaultSamplerDesc, const uint32_t MIPLevelCount, const uint32_t sampleCount)
     888             : {
     889           0 :     return CTexture::Create(this, name, type, usage,
     890           0 :         format, width, height, defaultSamplerDesc, MIPLevelCount, sampleCount);
     891             : }
     892             : 
     893           0 : std::unique_ptr<ITexture> CDevice::CreateTexture2D(
     894             :     const char* name, const uint32_t usage,
     895             :     const Format format, const uint32_t width, const uint32_t height,
     896             :     const Sampler::Desc& defaultSamplerDesc, const uint32_t MIPLevelCount, const uint32_t sampleCount)
     897             : {
     898             :     return CreateTexture(name, CTexture::Type::TEXTURE_2D, usage,
     899           0 :         format, width, height, defaultSamplerDesc, MIPLevelCount, sampleCount);
     900             : }
     901             : 
     902           0 : std::unique_ptr<IFramebuffer> CDevice::CreateFramebuffer(
     903             :     const char* name, SColorAttachment* colorAttachment,
     904             :     SDepthStencilAttachment* depthStencilAttachment)
     905             : {
     906           0 :     return CFramebuffer::Create(
     907           0 :         this, name, colorAttachment, depthStencilAttachment);
     908             : }
     909             : 
     910           0 : std::unique_ptr<IBuffer> CDevice::CreateBuffer(
     911             :     const char* name, const IBuffer::Type type, const uint32_t size, const bool dynamic)
     912             : {
     913           0 :     return CBuffer::Create(this, name, type, size, dynamic);
     914             : }
     915             : 
     916           0 : std::unique_ptr<IShaderProgram> CDevice::CreateShaderProgram(
     917             :     const CStr& name, const CShaderDefines& defines)
     918             : {
     919           0 :     return CShaderProgram::Create(this, name, defines);
     920             : }
     921             : 
     922           0 : bool CDevice::AcquireNextBackbuffer()
     923             : {
     924           0 :     ENSURE(!m_BackbufferAcquired);
     925           0 :     m_BackbufferAcquired = true;
     926           0 :     return true;
     927             : }
     928             : 
     929           0 : size_t CDevice::BackbufferKeyHash::operator()(const BackbufferKey& key) const
     930             : {
     931           0 :     size_t seed = 0;
     932           0 :     hash_combine(seed, std::get<0>(key));
     933           0 :     hash_combine(seed, std::get<1>(key));
     934           0 :     hash_combine(seed, std::get<2>(key));
     935           0 :     hash_combine(seed, std::get<3>(key));
     936           0 :     return seed;
     937             : }
     938             : 
     939           0 : IFramebuffer* CDevice::GetCurrentBackbuffer(
     940             :     const AttachmentLoadOp colorAttachmentLoadOp,
     941             :     const AttachmentStoreOp colorAttachmentStoreOp,
     942             :     const AttachmentLoadOp depthStencilAttachmentLoadOp,
     943             :     const AttachmentStoreOp depthStencilAttachmentStoreOp)
     944             : {
     945             :     const BackbufferKey key{
     946             :         colorAttachmentLoadOp, colorAttachmentStoreOp,
     947           0 :         depthStencilAttachmentLoadOp, depthStencilAttachmentStoreOp};
     948           0 :     auto it = m_Backbuffers.find(key);
     949           0 :     if (it == m_Backbuffers.end())
     950             :     {
     951           0 :         it = m_Backbuffers.emplace(key, CFramebuffer::CreateBackbuffer(
     952             :             this, m_SurfaceDrawableWidth, m_SurfaceDrawableHeight,
     953             :             colorAttachmentLoadOp, colorAttachmentStoreOp,
     954           0 :             depthStencilAttachmentLoadOp, depthStencilAttachmentStoreOp)).first;
     955             :     }
     956           0 :     return it->second.get();
     957             : }
     958             : 
     959           0 : void CDevice::Present()
     960             : {
     961           0 :     ENSURE(m_BackbufferAcquired);
     962           0 :     m_BackbufferAcquired = false;
     963             : 
     964           0 :     if (m_Window)
     965             :     {
     966           0 :         PROFILE3("swap buffers");
     967           0 :         SDL_GL_SwapWindow(m_Window);
     968           0 :         ogl_WarnIfError();
     969             :     }
     970             : 
     971           0 :     bool checkGLErrorAfterSwap = false;
     972           0 :     CFG_GET_VAL("gl.checkerrorafterswap", checkGLErrorAfterSwap);
     973             : #if defined(NDEBUG)
     974             :     if (!checkGLErrorAfterSwap)
     975             :         return;
     976             : #endif
     977           0 :     PROFILE3("error check");
     978             :     // We have to check GL errors after SwapBuffer to avoid possible
     979             :     // synchronizations during rendering.
     980           0 :     if (GLenum err = glGetError())
     981           0 :         ONCE(LOGERROR("GL error %s (0x%04x) occurred", ogl_GetErrorName(err), err));
     982           0 : }
     983             : 
     984           0 : void CDevice::OnWindowResize(const uint32_t width, const uint32_t height)
     985             : {
     986           0 :     ENSURE(!m_BackbufferAcquired);
     987           0 :     m_Backbuffers.clear();
     988           0 :     m_SurfaceDrawableWidth = width;
     989           0 :     m_SurfaceDrawableHeight = height;
     990           0 : }
     991             : 
     992           0 : bool CDevice::IsTextureFormatSupported(const Format format) const
     993             : {
     994           0 :     bool supported = false;
     995           0 :     switch (format)
     996             :     {
     997           0 :     case Format::UNDEFINED:
     998           0 :         break;
     999             : 
    1000           0 :     case Format::R8G8B8_UNORM: FALLTHROUGH;
    1001             :     case Format::R8G8B8A8_UNORM: FALLTHROUGH;
    1002             :     case Format::A8_UNORM: FALLTHROUGH;
    1003             :     case Format::L8_UNORM:
    1004           0 :         supported = true;
    1005           0 :         break;
    1006             : 
    1007           0 :     case Format::R32_SFLOAT: FALLTHROUGH;
    1008             :     case Format::R32G32_SFLOAT: FALLTHROUGH;
    1009             :     case Format::R32G32B32_SFLOAT: FALLTHROUGH;
    1010             :     case Format::R32G32B32A32_SFLOAT:
    1011           0 :         break;
    1012             : 
    1013           0 :     case Format::D16_UNORM: FALLTHROUGH;
    1014             :     case Format::D24_UNORM: FALLTHROUGH;
    1015             :     case Format::D32_SFLOAT:
    1016           0 :         supported = true;
    1017           0 :         break;
    1018           0 :     case Format::D24_UNORM_S8_UINT:
    1019             : #if !CONFIG2_GLES
    1020           0 :         supported = true;
    1021             : #endif
    1022           0 :         break;
    1023             : 
    1024           0 :     case Format::D32_SFLOAT_S8_UINT:
    1025           0 :         break;
    1026             : 
    1027           0 :     case Format::BC1_RGB_UNORM: FALLTHROUGH;
    1028             :     case Format::BC1_RGBA_UNORM: FALLTHROUGH;
    1029             :     case Format::BC2_UNORM: FALLTHROUGH;
    1030             :     case Format::BC3_UNORM:
    1031           0 :         supported = m_Capabilities.S3TC;
    1032           0 :         break;
    1033             : 
    1034           0 :     default:
    1035           0 :         break;
    1036             :     }
    1037           0 :     return supported;
    1038             : }
    1039             : 
    1040           0 : bool CDevice::IsFramebufferFormatSupported(const Format format) const
    1041             : {
    1042           0 :     bool supported = false;
    1043           0 :     switch (format)
    1044             :     {
    1045           0 :     case Format::UNDEFINED:
    1046           0 :         break;
    1047             : #if !CONFIG2_GLES
    1048           0 :     case Format::R8_UNORM:
    1049           0 :         supported = ogl_HaveVersion(3, 0);
    1050           0 :         break;
    1051             : #endif
    1052           0 :     case Format::R8G8B8A8_UNORM:
    1053           0 :         supported = true;
    1054           0 :         break;
    1055           0 :     default:
    1056           0 :         break;
    1057             :     }
    1058           0 :     return supported;
    1059             : }
    1060             : 
    1061           0 : Format CDevice::GetPreferredDepthStencilFormat(
    1062             :     const uint32_t UNUSED(usage), const bool depth, const bool stencil) const
    1063             : {
    1064           0 :     ENSURE(depth || stencil);
    1065           0 :     if (stencil)
    1066             : #if CONFIG2_GLES
    1067             :         return Format::UNDEFINED;
    1068             : #else
    1069           0 :         return Format::D24_UNORM_S8_UINT;
    1070             : #endif
    1071             :     else
    1072           0 :         return Format::D24_UNORM;
    1073             : }
    1074             : 
    1075           0 : std::unique_ptr<IDevice> CreateDevice(SDL_Window* window, const bool arb)
    1076             : {
    1077           0 :     return GL::CDevice::Create(window, arb);
    1078             : }
    1079             : 
    1080             : } // namespace GL
    1081             : 
    1082             : } // namespace Backend
    1083             : 
    1084           3 : } // namespace Renderer

Generated by: LCOV version 1.13