Try to workaround some Linux Nvidia driver bug

This commit is contained in:
CasualPokePlayer 2024-08-25 15:47:41 -07:00
parent 436be60222
commit bb456e45be
2 changed files with 57 additions and 6 deletions

View File

@ -6,6 +6,11 @@ namespace BizHawk.Bizware.Graphics.Controls
{
internal sealed class OpenGLControl : GraphicsControl
{
// workaround a bug with proprietary Nvidia drivers resulting in some BadMatch on setting context to current
// seems they don't like whatever depth values mono's winforms ends up setting
// mono's winforms seems to try to copy from the "parent" window, so we need to create a "friendly" window
private static readonly Lazy<IntPtr> _x11GLParent = new(() => SDL2OpenGLContext.CreateDummyX11ParentWindow(3, 2, true));
private readonly Action _initGLState;
private SDL2OpenGLContext _context;
@ -35,6 +40,11 @@ namespace BizHawk.Bizware.Graphics.Controls
// According to OpenTK, this is necessary for OpenGL on windows
cp.ClassStyle |= CS_VREDRAW | CS_HREDRAW | CS_OWNDC;
}
else
{
// workaround buggy proprietary Nvidia drivers
cp.Parent = _x11GLParent.Value;
}
return cp;
}

View File

@ -5,6 +5,7 @@ using System.Runtime.InteropServices;
using Silk.NET.OpenGL;
#endif
using BizHawk.Common;
using static SDL2.SDL;
namespace BizHawk.Bizware.Graphics
@ -45,7 +46,40 @@ namespace BizHawk.Bizware.Graphics
private IntPtr _sdlWindow;
private IntPtr _glContext;
private void CreateContext(int majorVersion, int minorVersion, bool coreProfile, bool shareContext)
// helper function for OpenGLControl
public static IntPtr CreateDummyX11ParentWindow(int majorVersion, int minorVersion, bool coreProfile)
{
if (!OSTailoredCode.IsUnixHost)
{
throw new NotSupportedException("This function should only be called on Linux");
}
SetAttributes(majorVersion, minorVersion, coreProfile, shareContext: false);
var sdlWindow = SDL_CreateWindow(null, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1, 1,
SDL_WindowFlags.SDL_WINDOW_OPENGL | SDL_WindowFlags.SDL_WINDOW_HIDDEN);
if (sdlWindow == IntPtr.Zero)
{
throw new($"Could not create SDL Window! SDL Error: {SDL_GetError()}");
}
var wmInfo = default(SDL_SysWMinfo);
SDL_GetVersion(out wmInfo.version);
if (SDL_GetWindowWMInfo(sdlWindow, ref wmInfo) == SDL_bool.SDL_FALSE)
{
SDL_DestroyWindow(sdlWindow);
throw new($"Failed to obtain SDL window info! SDL error: {SDL_GetError()}");
}
if (wmInfo.subsystem != SDL_SYSWM_TYPE.SDL_SYSWM_X11)
{
SDL_DestroyWindow(sdlWindow);
throw new("Subsystem is not X11!");
}
return wmInfo.info.x11.window;
}
private static void SetAttributes(int majorVersion, int minorVersion, bool coreProfile, bool shareContext)
{
// set some sensible defaults
SDL_GL_ResetAttributes();
@ -88,7 +122,10 @@ namespace BizHawk.Bizware.Graphics
{
throw new($"Could not set share context attribute! SDL Error: {SDL_GetError()}");
}
}
private void CreateContext()
{
_glContext = SDL_GL_CreateContext(_sdlWindow);
if (_glContext == IntPtr.Zero)
{
@ -109,18 +146,24 @@ namespace BizHawk.Bizware.Graphics
public SDL2OpenGLContext(IntPtr nativeWindowhandle, int majorVersion, int minorVersion, bool coreProfile)
{
// Controls are not shared, they are the sharees
SetAttributes(majorVersion, minorVersion, coreProfile, shareContext: false);
_sdlWindow = SDL_CreateWindowFrom(nativeWindowhandle);
if (_sdlWindow == IntPtr.Zero)
{
throw new($"Could not create SDL Window! SDL Error: {SDL_GetError()}");
}
// Controls are not shared, they are the sharees
CreateContext(majorVersion, minorVersion, coreProfile, shareContext: false);
CreateContext();
}
public SDL2OpenGLContext(int majorVersion, int minorVersion, bool coreProfile)
{
// offscreen contexts are shared (as we want to send texture from it over to our control's context)
// make sure to set the current graphics control context before creating this context
SetAttributes(majorVersion, minorVersion, coreProfile, shareContext: true);
_sdlWindow = SDL_CreateWindow(null, SDL_WINDOWPOS_UNDEFINED, SDL_WINDOWPOS_UNDEFINED, 1, 1,
SDL_WindowFlags.SDL_WINDOW_OPENGL | SDL_WindowFlags.SDL_WINDOW_HIDDEN);
if (_sdlWindow == IntPtr.Zero)
@ -128,9 +171,7 @@ namespace BizHawk.Bizware.Graphics
throw new($"Could not create SDL Window! SDL Error: {SDL_GetError()}");
}
// offscreen contexts are shared (as we want to send texture from it over to our control's context)
// make sure to set the current graphics control context before creating this context
CreateContext(majorVersion, minorVersion, coreProfile, shareContext: true);
CreateContext();
}
public void Dispose()