mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
Fix compat mode, fullscreen, more work on ANGLE swap chain.
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -150,7 +150,7 @@ namespace Robust.Client.Graphics.Clyde
|
||||
|
||||
if (_isGLES)
|
||||
{
|
||||
if (_openGLVersion == RendererOpenGLVersion.GLES3)
|
||||
if (_hasGLES3Shaders)
|
||||
{
|
||||
versionHeader = "#version 300 es\n";
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user