mirror of
https://github.com/SK-la/osu-framework.git
synced 2026-03-13 11:20:31 +00:00
116 lines
4.6 KiB
C#
116 lines
4.6 KiB
C#
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
|
|
// See the LICENCE file in the repository root for full licence text.
|
|
|
|
using System;
|
|
using System.Diagnostics.CodeAnalysis;
|
|
using System.Runtime.InteropServices;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using osu.Framework.Bindables;
|
|
using osu.Framework.Graphics.OpenGL;
|
|
using osu.Framework.Logging;
|
|
using osuTK.Graphics.ES30;
|
|
|
|
namespace osu.Framework.Platform.Windows
|
|
{
|
|
internal class WindowsGLRenderer : GLRenderer, IWindowsRenderer
|
|
{
|
|
public IBindable<FullscreenCapability> FullscreenCapability => fullscreenCapability;
|
|
private readonly Bindable<FullscreenCapability> fullscreenCapability = new Bindable<FullscreenCapability>();
|
|
|
|
private readonly WindowsGameHost host;
|
|
|
|
public WindowsGLRenderer(WindowsGameHost host)
|
|
{
|
|
this.host = host;
|
|
}
|
|
|
|
protected override void Initialise(IGraphicsSurface graphicsSurface)
|
|
{
|
|
base.Initialise(graphicsSurface);
|
|
|
|
bool isIntel = GL.GetString(StringName.Vendor).Trim() == "Intel";
|
|
|
|
if (isIntel)
|
|
{
|
|
// Exclusive fullscreen is always supported on Intel.
|
|
fullscreenCapability.Value = Windows.FullscreenCapability.Capable;
|
|
}
|
|
else
|
|
{
|
|
// For all other vendors, support depends on the system setup - e.g. NVIDIA Optimus doesn't support exclusive fullscreen with OpenGL.
|
|
host.Window.IsActive.BindValueChanged(_ => detectFullscreenCapability(host.Window));
|
|
host.Window.WindowStateChanged += _ => detectFullscreenCapability(host.Window);
|
|
detectFullscreenCapability(host.Window);
|
|
}
|
|
}
|
|
|
|
private CancellationTokenSource? fullscreenCapabilityDetectionCancellationSource;
|
|
|
|
private void detectFullscreenCapability(IWindow window)
|
|
{
|
|
fullscreenCapabilityDetectionCancellationSource?.Cancel();
|
|
fullscreenCapabilityDetectionCancellationSource?.Dispose();
|
|
fullscreenCapabilityDetectionCancellationSource = null;
|
|
|
|
if (window.WindowState != WindowState.Fullscreen || !window.IsActive.Value || fullscreenCapability.Value != Windows.FullscreenCapability.Unknown)
|
|
return;
|
|
|
|
var cancellationSource = fullscreenCapabilityDetectionCancellationSource = new CancellationTokenSource();
|
|
var cancellationToken = cancellationSource.Token;
|
|
|
|
// 50 attempts, 100ms apart = run the detection for a total of 5 seconds before yielding an incapable state.
|
|
const int max_attempts = 50;
|
|
const int time_per_attempt = 100;
|
|
int attempts = 0;
|
|
|
|
queueNextAttempt();
|
|
|
|
void queueNextAttempt() => Task.Delay(time_per_attempt, cancellationToken).ContinueWith(_ =>
|
|
{
|
|
if (cancellationToken.IsCancellationRequested || window.WindowState != WindowState.Fullscreen || !window.IsActive.Value)
|
|
return;
|
|
|
|
attempts++;
|
|
|
|
try
|
|
{
|
|
SHQueryUserNotificationState(out var notificationState);
|
|
|
|
var capability = notificationState == QueryUserNotificationState.QUNS_RUNNING_D3D_FULL_SCREEN
|
|
? Windows.FullscreenCapability.Capable
|
|
: Windows.FullscreenCapability.Incapable;
|
|
|
|
if (capability == Windows.FullscreenCapability.Incapable && attempts < max_attempts)
|
|
{
|
|
queueNextAttempt();
|
|
return;
|
|
}
|
|
|
|
fullscreenCapability.Value = capability;
|
|
Logger.Log($"Exclusive fullscreen capability: {fullscreenCapability.Value} ({notificationState})");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Logger.Error(ex, "Failed to detect fullscreen capabilities.");
|
|
fullscreenCapability.Value = Windows.FullscreenCapability.Capable;
|
|
}
|
|
}, cancellationToken);
|
|
}
|
|
|
|
[DllImport("shell32.dll")]
|
|
private static extern int SHQueryUserNotificationState(out QueryUserNotificationState state);
|
|
|
|
[SuppressMessage("ReSharper", "InconsistentNaming")]
|
|
private enum QueryUserNotificationState
|
|
{
|
|
QUNS_NOT_PRESENT = 1,
|
|
QUNS_BUSY = 2,
|
|
QUNS_RUNNING_D3D_FULL_SCREEN = 3,
|
|
QUNS_PRESENTATION_MODE = 4,
|
|
QUNS_ACCEPTS_NOTIFICATIONS = 5,
|
|
QUNS_QUIET_TIME = 6
|
|
}
|
|
}
|
|
}
|