⚡ Sangsakala Proxy 🏠 Home
Skip to content

Commit ba36bd8

Browse files
committed
More work on uservideomodes
1 parent ca19b33 commit ba36bd8

7 files changed

Lines changed: 171 additions & 19 deletions

File tree

‎Source.Common/Engine/IVideoMode.cs‎

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using Source.Common.Bitmap;
22

3+
using System.Numerics;
4+
35
namespace Source.Common.Engine;
46

57

@@ -11,12 +13,51 @@ public struct ViewRect
1113
/// <summary>
1214
/// General merging of things, differentiates from Source's garbage when managing video modes. Allows arbitrary user data for the video mode
1315
/// </summary>
14-
public struct UserVideoMode {
16+
public struct UserVideoMode
17+
{
1518
public int Width;
1619
public int Height;
1720
public int RefreshRate;
1821
public bool Windowed;
1922
public bool Borderless;
23+
24+
public UserVideoMode(int width, int height) {
25+
Width = width;
26+
Height = height;
27+
}
28+
public UserVideoMode(int width, int height, bool windowed) {
29+
Width = width;
30+
Height = height;
31+
Windowed = windowed;
32+
}
33+
public UserVideoMode(int width, int height, bool windowed, bool borderless) {
34+
Width = width;
35+
Height = height;
36+
Windowed = windowed;
37+
Borderless = borderless;
38+
}
39+
private static int GCD(int a, int b) {
40+
while (b != 0) {
41+
int t = b;
42+
b = a % b;
43+
a = t;
44+
}
45+
return a;
46+
}
47+
public static void ProduceAvailableResolutionList(int numerator, int denominator, int monitorWidth, int monitorHeight, List<Vector2> modes) {
48+
int g = GCD(numerator, denominator);
49+
int baseW = numerator / g;
50+
int baseH = denominator / g;
51+
52+
int maxK = Math.Min(monitorWidth / baseW, monitorHeight / baseH);
53+
54+
for (int k = 1; k <= maxK; k++) {
55+
int w = baseW * k;
56+
int h = baseH * k;
57+
58+
modes.Add(new(w, h));
59+
}
60+
}
2061
}
2162

2263
public interface IVideoMode

‎Source.Common/ShaderAPI/IShaderDevice.cs‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ public enum ShaderType
3333
}
3434
public static class GraphicsAPIVersion_Exts
3535
{
36+
public static GraphicsDriver GetDriver(this GraphicsDriver version) {
37+
return version & GraphicsDriver.DriverMask;
38+
}
39+
public static bool IsDriver(this GraphicsDriver version, GraphicsDriver driver) {
40+
return driver == (version & GraphicsDriver.DriverMask);
41+
}
3642
/// <summary>
3743
/// Generate a file extension, consiting of (DRIVER)(VERSION).(SHADERTYPEEXT).
3844
/// <br/>

‎Source.Engine/CommandLine.cs‎

Lines changed: 94 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ unsafe void ParseCommandLine() {
1111
CleanUpParms();
1212
if (cmdLine == null) return;
1313

14-
fixed(char* pCharFx = cmdLine) {
14+
fixed (char* pCharFx = cmdLine) {
1515
char* pChar = pCharFx;
1616

1717
while (*pChar > 0 && char.IsWhiteSpace(*pChar))
@@ -30,8 +30,8 @@ unsafe void ParseCommandLine() {
3030
continue;
3131
}
3232

33-
if(firstLetter == null) {
34-
if(*pChar == '\"') {
33+
if (firstLetter == null) {
34+
if (*pChar == '\"') {
3535
inQuotes = true;
3636
firstLetter = pChar + 1;
3737
continue;
@@ -107,20 +107,20 @@ public unsafe void CreateCmdLine(ReadOnlySpan<char> commandLine) {
107107
full[0] = '\0';
108108

109109
char* dst = full;
110-
fixed(char* pCommandLine = commandLine) {
110+
fixed (char* pCommandLine = commandLine) {
111111
char* src = pCommandLine;
112112
bool inQuotes = false;
113113
char* inQuotesStart = null;
114-
while(*src > 0) {
115-
if(*src == '"') {
116-
if(src == pCommandLine || (src[-1] != '/' && src[-1] != '\\')) {
114+
while (*src > 0) {
115+
if (*src == '"') {
116+
if (src == pCommandLine || (src[-1] != '/' && src[-1] != '\\')) {
117117
inQuotes = !inQuotes;
118118
inQuotesStart = src + 1;
119119
}
120120
}
121121

122-
if(*src == '*') {
123-
if(src == pCommandLine || (inQuotes && char.IsWhiteSpace(src[-1])) || (inQuotes && src == inQuotesStart)){
122+
if (*src == '*') {
123+
if (src == pCommandLine || (inQuotes && char.IsWhiteSpace(src[-1])) || (inQuotes && src == inQuotesStart)) {
124124
LoadParametersFromFile(src, dst, MAX_BUFFER_LEN - ((nint)dst - (nint)full), inQuotes);
125125
continue;
126126
}
@@ -224,11 +224,93 @@ public string GetParm(int index) {
224224
return parms[index + 1];
225225
}
226226

227-
public unsafe void RemoveParm(string name) {
228-
throw new NotImplementedException();
227+
228+
static int StrLen(char[] buffer, int start) {
229+
int len = 0;
230+
while (buffer[start + len] != '\0')
231+
len++;
232+
return len;
233+
}
234+
235+
static int StrIStr(char[] buffer, int start, string needle) {
236+
int haystackLen = StrLen(buffer, start);
237+
if (needle.Length > haystackLen)
238+
return -1;
239+
240+
for (int i = 0; i <= haystackLen - needle.Length; i++) {
241+
bool match = true;
242+
for (int j = 0; j < needle.Length; j++) {
243+
if (char.ToLowerInvariant(buffer[start + i + j]) != char.ToLowerInvariant(needle[j])) {
244+
match = false;
245+
break;
246+
}
247+
}
248+
if (match)
249+
return start + i;
250+
}
251+
252+
return -1;
253+
}
254+
255+
public void RemoveParm(string name) {
256+
if (cmdLine == null)
257+
return;
258+
259+
int nParmLen = name.Length;
260+
261+
char[] buffer = new char[cmdLine.Length + 1];
262+
cmdLine.AsSpan().CopyTo(buffer);
263+
buffer[cmdLine.Length] = '\0';
264+
265+
int p = 0;
266+
while (buffer[p] != '\0') {
267+
int curlen = StrLen(buffer, p);
268+
269+
int found = StrIStr(buffer, p, name);
270+
if (found == -1)
271+
break;
272+
273+
int nextparam = found + 1;
274+
bool hadQuote = false;
275+
if (found > 0 && buffer[found - 1] == '"')
276+
hadQuote = true;
277+
278+
while (buffer[nextparam] != '\0' && buffer[nextparam] != ' ' && buffer[nextparam] != '"')
279+
nextparam++;
280+
281+
if ((nextparam - found) > nParmLen) {
282+
p = nextparam;
283+
continue;
284+
}
285+
286+
while (buffer[nextparam] != '\0' && buffer[nextparam] != '-' && buffer[nextparam] != '+')
287+
nextparam++;
288+
289+
if (hadQuote)
290+
found--;
291+
292+
if (buffer[nextparam] != '\0') {
293+
int n = curlen - (nextparam - p);
294+
new Span<char>(buffer, nextparam, n).CopyTo(new Span<char>(buffer, found, n));
295+
buffer[found + n] = '\0';
296+
}
297+
else {
298+
int n = nextparam - found;
299+
new Span<char>(buffer, found, n).Clear();
300+
}
301+
}
302+
303+
int len = StrLen(buffer, 0);
304+
while (len > 0 && buffer[len - 1] == ' ')
305+
len--;
306+
307+
cmdLine = new string(buffer, 0, len);
308+
ParseCommandLine();
229309
}
230310

231311
public void SetParm(int index, string newParm) {
232-
throw new NotImplementedException();
312+
Dbg.Assert(index >= 0 && index < parms.Count);
313+
if (index >= 0 && index < parms.Count)
314+
parms[index] = newParm;
233315
}
234316
}

‎Source.Engine/MatSysInterface.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -800,7 +800,7 @@ static void mat_setvideomode(in TokenizedCommand args) {
800800
bool windowed = args.Arg(3, 0) > 0;
801801
bool borderless = args.ArgC() == 5 && args.Arg(4, 0) > 0;
802802

803-
Singleton<IVideoMode>().SetMode(width, height, windowed, borderless);
803+
Singleton<IVideoMode>().SetMode(new(width, height, windowed, borderless));
804804
}
805805
#endif
806806

‎Source.Engine/Mod.cs‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public bool Init(string initialMod, string initialGame) {
3030

3131
videomode.Init();
3232

33-
return videomode.CreateGameWindow(width, height, windowed, borderless);
33+
return videomode.CreateGameWindow(new(width, height, windowed, borderless));
3434
}
3535

3636
public IMod.Result Run() {

‎Source.MaterialSystem/MaterialSystem.cs‎

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -138,7 +138,6 @@ public void GenerateConfigFromConfigKeyValues(MaterialSystem_Config config, bool
138138
launcherMgr.GetNativeDisplayInfo(-1, out uint width, out uint height, out uint refreshHz);
139139
config.VideoMode.Width = (int)width;
140140
config.VideoMode.Height = (int)height;
141-
142141
}
143142

144143
public bool UpdateConfig(bool forceUpdate) {
@@ -496,7 +495,7 @@ private void ConvertModeStruct(MaterialSystem_Config config, out ShaderDeviceInf
496495
mode = new ShaderDeviceInfo();
497496
mode.DisplayMode.Width = config.VideoMode.Width;
498497
mode.DisplayMode.Height = config.VideoMode.Height;
499-
mode.DisplayMode.Format = config.VideoMode.Format;
498+
mode.DisplayMode.Format = config.Format;
500499
mode.DisplayMode.RefreshRateNumerator = config.VideoMode.RefreshRate;
501500
mode.DisplayMode.RefreshRateDenominator = config.VideoMode.RefreshRate >= 0 ? 1 : 0;
502501
mode.BackBufferCount = 1;

‎Source.SDLManager/SDL3_LauncherManager.cs‎

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,24 @@ public SDL3_LauncherManager(IServiceProvider services) {
9999
public bool CreateGameWindow(string title, bool windowed, bool borderless, int width, int height) {
100100
IMaterialSystem materials = services.GetRequiredService<IMaterialSystem>();
101101

102-
SDL_WindowFlags flags = SDL_WindowFlags.SDL_WINDOW_OPENGL;
103-
if (!windowed) flags |= SDL_WindowFlags.SDL_WINDOW_FULLSCREEN;
102+
SDL_WindowFlags flags = default;
103+
GraphicsDriver driver = GraphicsDriver.OpenGL46; // todo, dont hardcode
104+
switch(driver.GetDriver()){
105+
case GraphicsDriver.OpenGL: flags |= SDL_WindowFlags.SDL_WINDOW_OPENGL; break;
106+
case GraphicsDriver.Metal: flags |= SDL_WindowFlags.SDL_WINDOW_METAL; break;
107+
case GraphicsDriver.Vulkan: flags |= SDL_WindowFlags.SDL_WINDOW_VULKAN; break;
108+
default: throw new Exception("Need graphics driver support");
109+
}
110+
104111
if (borderless) flags |= SDL_WindowFlags.SDL_WINDOW_BORDERLESS;
105112

106113
window = new SDL3_Window(services).Create(title, width, height, flags);
107114

115+
if (!windowed) {
116+
SetExclusiveFullscreenMode(width, height);
117+
SDL3.SDL_SetWindowFullscreen(window.HardwareHandle, true);
118+
}
119+
108120
#if WIN32
109121
// Hack to fix SDL/GL promoting borderless windows to exclusive fullscreen
110122
// when the resolution matches desktop
@@ -211,10 +223,22 @@ public void SetApplicationIcon(ReadOnlySpan<char> appIconFile) {
211223
}
212224

213225
public void SetWindowFullScreen(bool fullscreen, int width, int height) {
226+
if (fullscreen)
227+
SetExclusiveFullscreenMode(width, height);
228+
else
229+
SDL3.SDL_SetWindowFullscreenMode(window.HardwareHandle, null);
230+
214231
SDL3.SDL_SetWindowFullscreen(window.HardwareHandle, fullscreen);
215232
SizeWindow(width, height);
216233
}
217234

235+
private void SetExclusiveFullscreenMode(int width, int height) {
236+
SDL_DisplayID display = SDL3.SDL_GetDisplayForWindow(window.HardwareHandle);
237+
SDL_DisplayMode closest;
238+
if (SDL3.SDL_GetClosestFullscreenDisplayMode(display, width, height, 0, false, &closest))
239+
SDL3.SDL_SetWindowFullscreenMode(window.HardwareHandle, &closest);
240+
}
241+
218242
public void SetWindowBordered(bool bordered) {
219243
SDL3.SDL_SetWindowBordered(window.HardwareHandle, bordered);
220244
}

0 commit comments

Comments
 (0)