Fix compat mode, fullscreen, more work on ANGLE swap chain.

This commit is contained in:
Pieter-Jan Briers
2021-09-01 01:13:32 +02:00
parent 4ba5654253
commit 6938787863
12 changed files with 226 additions and 143 deletions

View File

@@ -14,9 +14,9 @@ namespace Robust.Client.Graphics.Clyde
private void InitGLContextManager()
{
// Advanced GL contexts currently disabled due to lack of testing etc.
/*
if (OperatingSystem.IsWindows() && _cfg.GetCVar(CVars.DisplayAngle))
{
/*
if (_cfg.GetCVar(CVars.DisplayAngleCustomSwapChain))
{
_sawmillOgl.Debug("Trying custom swap chain ANGLE.");
@@ -26,10 +26,14 @@ namespace Robust.Client.Graphics.Clyde
{
_sawmillOgl.Debug("Successfully initialized custom ANGLE");
_glContext = ctxAngle;
ctxAngle.EarlyInit();
return;
}
}
*/
/*
if (_cfg.GetCVar(CVars.DisplayEgl))
{
_sawmillOgl.Debug("Trying EGL");
@@ -38,8 +42,10 @@ namespace Robust.Client.Graphics.Clyde
_glContext = ctxEgl;
return;
}
*/
}
/*
if (OperatingSystem.IsLinux() && _cfg.GetCVar(CVars.DisplayEgl))
{
_sawmillOgl.Debug("Trying EGL");
@@ -59,6 +65,8 @@ namespace Robust.Client.Graphics.Clyde
public int Minor;
public GLContextProfile Profile;
public GLContextCreationApi CreationApi;
// Used by GLContextWindow to figure out which GL version managed to initialize.
public RendererOpenGLVersion OpenGLVersion;
}
private enum GLContextProfile

View File

@@ -23,6 +23,7 @@ namespace Robust.Client.Graphics.Clyde
private bool _hasGLVertexArrayObject;
private bool _hasGLVertexArrayObjectOes;
private bool _hasGLFloatFramebuffers;
private bool _hasGLES3Shaders;
private bool HasGLAnyMapBuffer => _hasGLMapBuffer || _hasGLMapBufferRange || _hasGLMapBufferOes;
private bool _hasGLMapBuffer;
private bool _hasGLMapBufferOes;
@@ -99,13 +100,28 @@ namespace Robust.Client.Graphics.Clyde
CheckGLCap(ref _hasGLMapBufferRange, "map_buffer_range", (3, 0));
CheckGLCap(ref _hasGLPixelBufferObjects, "pixel_buffer_object", (3, 0));
CheckGLCap(ref _hasGLStandardDerivatives, "standard_derivatives", (3, 0), "GL_OES_standard_derivatives");
_hasGLSrgb = major >= 3;
CheckGLCap(ref _hasGLReadFramebuffer, "read_framebuffer", (3, 0));
CheckGLCap(ref _hasGLPrimitiveRestart, "primitive_restart", (3, 1));
CheckGLCap(ref _hasGLUniformBuffers, "uniform_buffers", (3, 0));
CheckGLCap(ref _hasGLFloatFramebuffers, "float_framebuffers", (3, 2), "GL_EXT_color_buffer_float");
CheckGLCap(ref _hasGLES3Shaders, "gles3_shaders", (3, 0));
if (major >= 3)
{
if (_glContext!.HasBrokenWindowSrgb)
{
_sawmillOgl.Debug(" sRGB: false (window broken sRGB)");
}
else
{
_sawmillOgl.Debug(" sRGB: true");
}
}
else
{
_hasGLSrgb = false;
_sawmillOgl.Debug(" sRGB: false");
}
}
_sawmillOgl.Debug($" GLES: {_isGLES}");
@@ -149,7 +165,8 @@ namespace Robust.Client.Graphics.Clyde
"read_framebuffer",
"primitive_restart",
"uniform_buffers",
"float_framebuffers"
"float_framebuffers",
"gles3_shaders",
};
foreach (var cvar in cvars)

View File

@@ -150,7 +150,7 @@ namespace Robust.Client.Graphics.Clyde
if (_isGLES)
{
if (_openGLVersion == RendererOpenGLVersion.GLES3)
if (_hasGLES3Shaders)
{
versionHeader = "#version 300 es\n";
}

View File

@@ -380,7 +380,7 @@ namespace Robust.Client.Graphics.Clyde
ReadOnlySpan<T> buf)
where T : unmanaged, IPixel<T>
{
if (!_hasGLTextureSwizzle && typeof(T) == typeof(A8) && typeof(T) == typeof(L8))
if (!_hasGLTextureSwizzle && (typeof(T) == typeof(A8) || typeof(T) == typeof(L8)))
{
var swizzleBuf = ArrayPool<Rgba32>.Shared.Rent(buf.Length);

View File

@@ -3,6 +3,7 @@ using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using System.Threading.Tasks;
using OpenToolkit.Graphics.OpenGL4;
using Robust.Client.Input;
using Robust.Client.UserInterface;
using Robust.Shared;
@@ -156,58 +157,39 @@ namespace Robust.Client.Graphics.Clyde
DebugTools.AssertNotNull(_glContext);
_chosenRenderer = Renderer.OpenGL;
_openGLVersion = (RendererOpenGLVersion) _cfg.GetCVar(CVars.DisplayOpenGLVersion);
RendererOpenGLVersion[] versions;
if (_glContext!.GlesOnly || _cfg.GetCVar(CVars.DisplayCompat))
{
versions = new[]
{
RendererOpenGLVersion.GLES3,
RendererOpenGLVersion.GLES2
};
}
else
{
versions = new[]
{
RendererOpenGLVersion.GL33,
RendererOpenGLVersion.GL31,
RendererOpenGLVersion.GLES3,
RendererOpenGLVersion.GLES2
};
}
if (_openGLVersion != RendererOpenGLVersion.Auto)
{
if (Array.IndexOf(versions, _openGLVersion) != -1)
versions = new[] {_openGLVersion};
else
Logger.ErrorS("clyde.win", $"Requested OpenGL version {_openGLVersion} not supported.");
}
var succeeded = false;
string? lastError = null;
foreach (var version in versions)
if (_glContext!.RequireWindowGL)
{
var glSpec = _glContext!.SpecWithOpenGLVersion(version);
var specs = _glContext!.SpecsToTry;
if (!TryInitMainWindow(glSpec, out lastError))
foreach (var glSpec in specs)
{
Logger.DebugS("clyde.win", $"OpenGL {version} unsupported: {lastError}");
continue;
if (!TryInitMainWindow(glSpec, out lastError))
{
Logger.DebugS("clyde.win", $"OpenGL {glSpec.OpenGLVersion} unsupported: {lastError}");
continue;
}
succeeded = true;
break;
}
// We should have a main window now.
DebugTools.AssertNotNull(_mainWindow);
succeeded = true;
_openGLVersion = version;
_isGLES = _openGLVersion is RendererOpenGLVersion.GLES2 or RendererOpenGLVersion.GLES3;
_isCore = _openGLVersion is RendererOpenGLVersion.GL33;
break;
}
else
{
if (!TryInitMainWindow(null, out lastError))
Logger.DebugS("clyde.win", $"Failed to create window: {lastError}");
else
succeeded = true;
}
// We should have a main window now.
DebugTools.AssertNotNull(_mainWindow);
// _openGLVersion must be set by _glContext.
DebugTools.Assert(_openGLVersion != RendererOpenGLVersion.Auto);
if (!succeeded)
{
@@ -235,6 +217,14 @@ namespace Robust.Client.Graphics.Clyde
InitOpenGL();
_sawmillOgl.Debug("Setting viewport and rendering splash...");
GL.Viewport(0, 0, ScreenSize.X, ScreenSize.Y);
CheckGlError();
// Quickly do a render with _drawingSplash = true so the screen isn't blank.
Render();
return true;
}
@@ -338,12 +328,13 @@ namespace Robust.Client.Graphics.Clyde
{
Size = reg.FramebufferSize,
IsWindow = true,
WindowId = reg.Id
WindowId = reg.Id,
IsSrgb = true
});
reg.RenderTarget = new RenderWindow(this, rtId);
_glContext!.WindowCreated(reg);
_glContext!.WindowCreated(glSpec, reg);
}
// Pass through result whether successful or not, caller handles it.

View File

@@ -161,13 +161,17 @@ namespace Robust.Client.Graphics.Clyde
private void InitOpenGL()
{
_isGLES = _openGLVersion is RendererOpenGLVersion.GLES2 or RendererOpenGLVersion.GLES3;
_isCore = _openGLVersion is RendererOpenGLVersion.GL33;
GLInitBindings(_isGLES);
var vendor = GL.GetString(StringName.Vendor);
var renderer = GL.GetString(StringName.Renderer);
var version = GL.GetString(StringName.Version);
var major = GL.GetInteger(GetPName.MajorVersion);
var minor = GL.GetInteger(GetPName.MinorVersion);
// GLES2 doesn't allow you to query major/minor version. Seriously.
var major = _openGLVersion == RendererOpenGLVersion.GLES2 ? 2 : GL.GetInteger(GetPName.MajorVersion);
var minor = _openGLVersion == RendererOpenGLVersion.GLES2 ? 0 :GL.GetInteger(GetPName.MinorVersion);
_sawmillOgl.Debug("OpenGL Vendor: {0}", vendor);
_sawmillOgl.Debug("OpenGL Renderer: {0}", renderer);
@@ -230,14 +234,6 @@ namespace Robust.Client.Graphics.Clyde
_sawmillOgl.Debug("Setting up RenderHandle...");
_renderHandle = new RenderHandle(this);
_sawmillOgl.Debug("Setting viewport and rendering splash...");
GL.Viewport(0, 0, ScreenSize.X, ScreenSize.Y);
CheckGlError();
// Quickly do a render with _drawingSplash = true so the screen isn't blank.
Render();
}
private (int major, int minor)? ParseGLOverrideVersion()
@@ -333,7 +329,8 @@ namespace Robust.Client.Graphics.Clyde
screenBufferHandle = new GLHandle(GL.GenTexture());
GL.BindTexture(TextureTarget.Texture2D, screenBufferHandle.Handle);
ApplySampleParameters(TextureSampleParameters.Default);
ScreenBufferTexture = GenTexture(screenBufferHandle, _mainWindow!.FramebufferSize, true, null, TexturePixelType.Rgba32);
// TODO: This is atrocious and broken and awful why did I merge this
ScreenBufferTexture = GenTexture(screenBufferHandle, (1920, 1080), true, null, TexturePixelType.Rgba32);
}
private GLHandle MakeQuadVao()

View File

@@ -39,6 +39,7 @@ namespace Robust.Client.Graphics.Clyde
public const int EGL_WINDOW_BIT = 0x0004;
public const int EGL_OPENGL_ES_API = 0x30A0;
public const int EGL_RENDERABLE_TYPE = 0x3040;
public const int EGL_OPENGL_ES2_BIT = 0x00000004;
public const int EGL_OPENGL_ES3_BIT = 0x00000040;
public const int EGL_CONTEXT_CLIENT_VERSION = 0x3098;
public const int EGL_TEXTURE_FORMAT = 0x3080;

View File

@@ -1,5 +1,5 @@
/*
// Commented out because I can't be bothered to figure out trimming for TerraFX.
// Commented out because I can't be bothered to figure out trimming for TerraFX.
/*
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
@@ -15,7 +15,6 @@ using static Robust.Client.Graphics.Clyde.Egl;
using static TerraFX.Interop.D3D_DRIVER_TYPE;
using static TerraFX.Interop.D3D_FEATURE_LEVEL;
using static TerraFX.Interop.DXGI_FORMAT;
using static TerraFX.Interop.DXGI_MEMORY_SEGMENT_GROUP;
using static TerraFX.Interop.DXGI_SWAP_EFFECT;
using static TerraFX.Interop.Windows;
@@ -39,16 +38,21 @@ namespace Robust.Client.Graphics.Clyde
private IDXGIAdapter1* _adapter;
private ID3D11Device* _device;
private ID3D11DeviceContext* _deviceContext;
private D3D_FEATURE_LEVEL _deviceFl;
private void* _eglDevice;
private void* _eglDisplay;
private void* _eglContext;
private void* _eglConfig;
private bool _es3;
private uint _swapInterval;
private readonly Dictionary<WindowId, WindowData> _windowData = new();
public override bool GlesOnly => true;
public override GLContextSpec[] SpecsToTry => Array.Empty<GLContextSpec>();
public override bool RequireWindowGL => false;
public override bool EarlyContextInit => true;
public override bool HasBrokenWindowSrgb => false;
public GLContextAngle(Clyde clyde) : base(clyde)
{
@@ -65,7 +69,7 @@ namespace Robust.Client.Graphics.Clyde
_swapInterval = (uint) (Clyde._vSync ? 1 : 0);
}
public override void WindowCreated(WindowReg reg)
public override void WindowCreated(GLContextSpec? spec, WindowReg reg)
{
var data = new WindowData
{
@@ -73,29 +77,16 @@ namespace Robust.Client.Graphics.Clyde
};
_windowData[reg.Id] = data;
IDXGIFactory2* factory2;
var iid = IID_IDXGIFactory2;
if (FAILED(_factory->QueryInterface(&iid, (void**) &factory2)))
factory2 = null;
var hWnd = Clyde._windowing!.WindowGetWin32Window(reg)!.Value;
// todo: exception management.
if (factory2 != null && !Clyde._cfg.GetCVar(CVars.DisplayAngleDxgi1))
{
CreateSwapChain2(factory2, hWnd, data);
}
else
{
CreateSwapChain1(data);
}
CreateSwapChain1(hWnd, data);
_factory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER);
var rt = Clyde.RtToLoaded(reg.RenderTarget);
rt.FlipY = true;
if (factory2 != null)
factory2->Release();
if (reg.IsMainWindow)
{
UpdateVSync();
@@ -143,52 +134,47 @@ namespace Robust.Client.Graphics.Clyde
attributes);
}
private void CreateSwapChain2(IDXGIFactory2* factory2, nint hWnd, WindowData data)
private void CreateSwapChain1(nint hWnd, WindowData data)
{
var desc = new DXGI_SWAP_CHAIN_DESC1
var desc = new DXGI_SWAP_CHAIN_DESC
{
Width = (uint) data.Reg.FramebufferSize.X,
Height = (uint) data.Reg.FramebufferSize.Y,
Format = DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
BufferDesc =
{
Width = (uint) data.Reg.FramebufferSize.X,
Height = (uint) data.Reg.FramebufferSize.Y,
Format = Clyde._hasGLSrgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM
},
SampleDesc =
{
Count = 1
},
OutputWindow = hWnd,
BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT | DXGI_USAGE_SHADER_INPUT,
BufferCount = 2,
SwapEffect = DXGI_SWAP_EFFECT_DISCARD
SwapEffect = DXGI_SWAP_EFFECT_DISCARD,
Windowed = 1
};
IDXGISwapChain1* swapChain1;
ThrowIfFailed("CreateSwapChainForHwnd", factory2->CreateSwapChainForHwnd(
(IUnknown*) _device,
hWnd,
&desc,
null,
null,
&swapChain1
));
fixed (IDXGISwapChain** swapPtr = &data.SwapChain)
{
var iid = IID_IDXGISwapChain;
ThrowIfFailed("QueryInterface", swapChain1->QueryInterface(&iid, (void**) swapPtr));
ThrowIfFailed("CreateSwapChain", _factory->CreateSwapChain(
(IUnknown*) _device,
&desc,
swapPtr
));
}
swapChain1->Release();
SetupBackbuffer(data);
}
private void CreateSwapChain1(WindowData data)
{
throw new NotImplementedException();
}
public override void WindowDestroyed(WindowReg reg)
{
throw new NotImplementedException();
var data = _windowData[reg.Id];
DestroyBackbuffer(data);
data.SwapChain->Release();
_windowData.Remove(reg.Id);
}
public bool TryInitialize()
@@ -207,6 +193,14 @@ namespace Robust.Client.Graphics.Clyde
return true;
}
public void EarlyInit()
{
// Early GL context init so that feature detection runs before window creation,
// and so that we can know _hasGLSrgb in window creation.
eglMakeCurrent(_eglDisplay, null, null, _eglContext);
Clyde.InitOpenGL();
}
private void TryInitializeCore()
{
var extensions = Marshal.PtrToStringUTF8((nint) eglQueryString(null, EGL_EXTENSIONS));
@@ -245,13 +239,12 @@ namespace Robust.Client.Graphics.Clyde
var attribs = stackalloc int[]
{
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
// EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_STENCIL_SIZE, 8,
EGL_RENDERABLE_TYPE, EGL_OPENGL_ES3_BIT,
EGL_NONE
};
@@ -275,9 +268,14 @@ namespace Robust.Client.Graphics.Clyde
_eglConfig = configs[0];
int supportedRenderableTypes;
eglGetConfigAttrib(_eglDisplay, _eglConfig, EGL_RENDERABLE_TYPE, &supportedRenderableTypes);
_es3 = (supportedRenderableTypes & EGL_OPENGL_ES3_BIT) != 0;
var createAttribs = stackalloc int[]
{
EGL_CONTEXT_CLIENT_VERSION, 3,
EGL_CONTEXT_CLIENT_VERSION, _es3 ? 3 : 2,
EGL_NONE
};
@@ -286,6 +284,8 @@ namespace Robust.Client.Graphics.Clyde
throw new Exception("eglCreateContext failed!");
Logger.DebugS("clyde.ogl.angle", "EGL context created!");
Clyde._openGLVersion = _es3 ? RendererOpenGLVersion.GLES3 : RendererOpenGLVersion.GLES2;
}
private void CreateD3D11Device()
@@ -317,21 +317,28 @@ namespace Robust.Client.Graphics.Clyde
Logger.DebugS("clyde.ogl.angle", $"Found display adapter with name: {adapterName}");
}
var featureLevels = stackalloc D3D_FEATURE_LEVEL[]
Span<D3D_FEATURE_LEVEL> featureLevels = stackalloc D3D_FEATURE_LEVEL[]
{
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0
// 11_0 can do GLES3
D3D_FEATURE_LEVEL_11_0,
// 9_3 can do GLES2
D3D_FEATURE_LEVEL_9_3,
// If we get a 9_1 FL we can't do D3D11 based ANGLE,
// but ANGLE can do it manually via the D3D9 renderer.
// In this case, abort custom swap chain and let ANGLE handle everything.
D3D_FEATURE_LEVEL_9_1
};
fixed (ID3D11Device** device = &_device)
fixed (D3D_FEATURE_LEVEL* fl = &featureLevels[0])
{
ThrowIfFailed("D3D11CreateDevice", D3D11CreateDevice(
(IDXGIAdapter*) _adapter,
_adapter == null ? D3D_DRIVER_TYPE_HARDWARE : D3D_DRIVER_TYPE_UNKNOWN,
IntPtr.Zero,
0,
featureLevels,
1,
fl,
(uint) featureLevels.Length,
D3D11_SDK_VERSION,
device,
null,
@@ -350,7 +357,22 @@ namespace Robust.Client.Graphics.Clyde
ThrowIfFailed("GetParent", dxgiDevice->GetParent(&iid, (void**) ptrAdapter));
}
_deviceFl = _device->GetFeatureLevel();
DXGI_ADAPTER_DESC1 desc;
ThrowIfFailed("GetDesc1", _adapter->GetDesc1(&desc));
var descName = new ReadOnlySpan<char>(desc.Description, 128).TrimEnd('\0');
Logger.DebugS("clyde.ogl.angle", "Successfully created D3D11 device!");
Logger.DebugS("clyde.ogl.angle", $"D3D11 Device Adapter: {descName.ToString()}");
Logger.DebugS("clyde.ogl.angle", $"D3D11 Device FL: {_deviceFl}");
if (_deviceFl == D3D_FEATURE_LEVEL_9_1)
{
throw new Exception(
"D3D11 device has too low FL (need at least 9_3). Aborting custom swap chain!");
}
}
finally
{
@@ -359,7 +381,6 @@ namespace Robust.Client.Graphics.Clyde
}
}
public override void Shutdown()
{
// Shut down ANGLE.
@@ -396,7 +417,7 @@ namespace Robust.Client.Graphics.Clyde
ThrowIfFailed("ResizeBuffers", data.SwapChain->ResizeBuffers(
2,
(uint) reg.FramebufferSize.X, (uint) reg.FramebufferSize.Y,
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
Clyde._hasGLSrgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM,
0));
SetupBackbuffer(data);
@@ -467,7 +488,7 @@ namespace Robust.Client.Graphics.Clyde
{
var sb = new StringBuilder();
sb.Append($"cfg: {Get(EGL_CONFIG_ID):00} | ");
sb.Append($"cfg: {Get(EGL_CONFIG_ID):000} | ");
sb.AppendFormat(
"R/G/B/A/D/S: {0}/{1}/{2}/{3}/{4:00}/{5} | ",
Get(EGL_RED_SIZE), Get(EGL_GREEN_SIZE), Get(EGL_BLUE_SIZE), Get(EGL_ALPHA_SIZE),
@@ -480,7 +501,8 @@ namespace Robust.Client.Graphics.Clyde
sb.Append($"NAT: {Get(EGL_NATIVE_VISUAL_ID)} | ");
sb.Append($"SAMPLES: {Get(EGL_SAMPLES)} | ");
sb.Append($"SAMPLE_BUFFERS: {Get(EGL_SAMPLE_BUFFERS)} | ");
sb.Append($"ORIENTATION: {Get(EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE)}");
sb.Append($"ORIENTATION: {Get(EGL_OPTIMAL_SURFACE_ORIENTATION_ANGLE)} | ");
sb.Append($"RENDERABLE: {Get(EGL_RENDERABLE_TYPE)}");
return sb.ToString();

View File

@@ -1,6 +1,5 @@
using System;
using OpenToolkit;
using OpenToolkit.Graphics.OpenGL4;
using Robust.Shared.Map;
using Robust.Shared.Maths;
@@ -28,19 +27,23 @@ namespace Robust.Client.Graphics.Clyde
return SpecWithOpenGLVersion(Clyde._openGLVersion);
}
public virtual bool EarlyContextInit => false;
public abstract GLContextSpec? SpecWithOpenGLVersion(RendererOpenGLVersion version);
public abstract void UpdateVSync();
public abstract void WindowCreated(WindowReg reg);
public abstract void WindowCreated(GLContextSpec? spec, WindowReg reg);
public abstract void WindowDestroyed(WindowReg reg);
public abstract void Shutdown();
public abstract bool GlesOnly { get; }
public abstract GLContextSpec[] SpecsToTry { get; }
public abstract bool RequireWindowGL { get; }
public abstract bool HasBrokenWindowSrgb { get; }
protected static GLContextSpec GetVersionSpec(RendererOpenGLVersion version)
{
var spec = new GLContextSpec();
var spec = new GLContextSpec { OpenGLVersion = version };
switch (version)
{

View File

@@ -26,6 +26,8 @@ namespace Robust.Client.Graphics.Clyde
private void* _eglContext;
private void* _eglConfig;
public override bool HasBrokenWindowSrgb => Clyde._isGLES && OperatingSystem.IsWindows();
public GLContextEgl(Clyde clyde) : base(clyde)
{
}
@@ -48,7 +50,7 @@ namespace Robust.Client.Graphics.Clyde
Logger.DebugS("clyde.ogl.egl", $"EGL client extensions: {extensions}!");
}
public override void WindowCreated(WindowReg reg)
public override void WindowCreated(GLContextSpec? spec, WindowReg reg)
{
var data = new WindowData
{
@@ -193,7 +195,8 @@ namespace Robust.Client.Graphics.Clyde
}
}
public override bool GlesOnly => true;
public override GLContextSpec[] SpecsToTry => Array.Empty<GLContextSpec>();
public override bool RequireWindowGL => false;
public override void SwapAllBuffers()
{

View File

@@ -18,7 +18,36 @@ namespace Robust.Client.Graphics.Clyde
{
private readonly Dictionary<WindowId, WindowData> _windowData = new();
public override bool GlesOnly => false;
public override GLContextSpec[] SpecsToTry
{
get
{
// Compat mode: only GLES2.
if (Clyde._cfg.GetCVar(CVars.DisplayCompat))
return new[] { GetVersionSpec(RendererOpenGLVersion.GLES2) };
var requestedVersion = (RendererOpenGLVersion) Clyde._cfg.GetCVar(CVars.DisplayOpenGLVersion);
if (requestedVersion != RendererOpenGLVersion.Auto)
{
return new[]
{
GetVersionSpec(requestedVersion)
};
}
return new[]
{
GetVersionSpec(RendererOpenGLVersion.GL33),
GetVersionSpec(RendererOpenGLVersion.GL31),
GetVersionSpec(RendererOpenGLVersion.GLES3),
GetVersionSpec(RendererOpenGLVersion.GLES2),
};
}
}
public override bool RequireWindowGL => true;
// ANGLE does not support main window sRGB.
public override bool HasBrokenWindowSrgb => Clyde._isGLES && OperatingSystem.IsWindows();
public GLContextWindow(Clyde clyde) : base(clyde)
{
@@ -38,7 +67,7 @@ namespace Robust.Client.Graphics.Clyde
Clyde._windowing.GLSwapInterval(Clyde._vSync ? 1 : 0);
}
public override void WindowCreated(WindowReg reg)
public override void WindowCreated(GLContextSpec? spec, WindowReg reg)
{
reg.RenderTarget.MakeGLFence = true;
@@ -51,6 +80,7 @@ namespace Robust.Client.Graphics.Clyde
if (reg.IsMainWindow)
{
Clyde._openGLVersion = spec!.Value.OpenGLVersion;
UpdateVSync();
}
else

View File

@@ -129,29 +129,27 @@ namespace Robust.Client.Graphics.Clyde
public void UpdateMainWindowMode()
{
/*if (_mainWindow == null)
{
if (_clyde._mainWindow == null)
return;
}
var win = _mainWindow;
var win = (GlfwWindowReg) _clyde._mainWindow;
if (_clyde._windowMode == WindowMode.Fullscreen)
{
_mainWindow.PrevWindowSize = win.WindowSize;
_mainWindow.PrevWindowPos = win.PrevWindowPos;
win.PrevWindowSize = win.WindowSize;
win.PrevWindowPos = win.PrevWindowPos;
SendCmd(new CmdWinSetFullscreen((nint) _mainWindow.GlfwWindow));
SendCmd(new CmdWinSetFullscreen((nint) win.GlfwWindow));
}
else
{
SendCmd(new CmdWinSetMonitor(
(nint) _mainWindow.GlfwWindow,
(nint) win.GlfwWindow,
0,
_mainWindow.PrevWindowPos.X, _mainWindow.PrevWindowPos.Y,
_mainWindow.PrevWindowSize.X, _mainWindow.PrevWindowSize.Y,
win.PrevWindowPos.X, win.PrevWindowPos.Y,
win.PrevWindowSize.X, win.PrevWindowSize.Y,
0
));
}*/
}
}
private void WinThreadWinSetFullscreen(CmdWinSetFullscreen cmd)
@@ -442,10 +440,23 @@ namespace Robust.Client.Graphics.Clyde
_winThreadMonitors.TryGetValue(parameters.Monitor.Id, out var monitorReg))
{
monitor = monitorReg.Ptr;
var mode = GLFW.GetVideoMode(monitor);
// Set refresh rate to monitor's so that GLFW doesn't manually select one.
GLFW.WindowHint(WindowHintInt.RefreshRate, mode->RefreshRate);
}
else
{
GLFW.WindowHint(WindowHintInt.RefreshRate, -1);
}
GLFW.WindowHint(WindowHintBool.Visible, false);
GLFW.WindowHint(WindowHintInt.RedBits, 8);
GLFW.WindowHint(WindowHintInt.GreenBits, 8);
GLFW.WindowHint(WindowHintInt.BlueBits, 8);
GLFW.WindowHint(WindowHintInt.AlphaBits, 8);
GLFW.WindowHint(WindowHintInt.StencilBits, 8);
var window = GLFW.CreateWindow(
parameters.Width, parameters.Height,
parameters.Title,