Allow window size/scale properties to be accessed from other threads.
This commit is contained in:
@@ -23,122 +23,165 @@ namespace OpenRA.Platforms.Default
|
|||||||
|
|
||||||
public IGraphicsContext Context { get { return context; } }
|
public IGraphicsContext Context { get { return context; } }
|
||||||
|
|
||||||
internal readonly IntPtr Window;
|
readonly IntPtr window;
|
||||||
bool disposed;
|
bool disposed;
|
||||||
|
|
||||||
public Size WindowSize { get; private set; }
|
readonly object syncObject = new object();
|
||||||
public float WindowScale { get; private set; }
|
Size windowSize;
|
||||||
|
Size surfaceSize;
|
||||||
|
float windowScale;
|
||||||
|
|
||||||
|
internal IntPtr Window
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (syncObject)
|
||||||
|
return window;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Size WindowSize
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (syncObject)
|
||||||
|
return windowSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public float WindowScale
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (syncObject)
|
||||||
|
return windowScale;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal Size SurfaceSize
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
lock (syncObject)
|
||||||
|
return surfaceSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal Size SurfaceSize { get; private set; }
|
|
||||||
public event Action<float, float> OnWindowScaleChanged = (before, after) => { };
|
public event Action<float, float> OnWindowScaleChanged = (before, after) => { };
|
||||||
|
|
||||||
[DllImport("user32.dll")]
|
[DllImport("user32.dll")]
|
||||||
static extern bool SetProcessDPIAware();
|
static extern bool SetProcessDPIAware();
|
||||||
|
|
||||||
public Sdl2PlatformWindow(Size windowSize, WindowMode windowMode)
|
public Sdl2PlatformWindow(Size requestWindowSize, WindowMode windowMode)
|
||||||
{
|
{
|
||||||
Console.WriteLine("Using SDL 2 with OpenGL renderer");
|
Console.WriteLine("Using SDL 2 with OpenGL renderer");
|
||||||
WindowSize = windowSize;
|
|
||||||
|
|
||||||
// Disable legacy scaling on Windows
|
// Lock the Window/Surface properties until initialization is complete
|
||||||
if (Platform.CurrentPlatform == PlatformType.Windows && !Game.Settings.Graphics.DisableWindowsDPIScaling)
|
lock (syncObject)
|
||||||
SetProcessDPIAware();
|
|
||||||
|
|
||||||
SDL.SDL_Init(SDL.SDL_INIT_NOPARACHUTE | SDL.SDL_INIT_VIDEO);
|
|
||||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_DOUBLEBUFFER, 1);
|
|
||||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_RED_SIZE, 8);
|
|
||||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_GREEN_SIZE, 8);
|
|
||||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_BLUE_SIZE, 8);
|
|
||||||
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_ALPHA_SIZE, 0);
|
|
||||||
|
|
||||||
SDL.SDL_DisplayMode display;
|
|
||||||
SDL.SDL_GetCurrentDisplayMode(0, out display);
|
|
||||||
|
|
||||||
Console.WriteLine("Desktop resolution: {0}x{1}", display.w, display.h);
|
|
||||||
if (WindowSize.Width == 0 && WindowSize.Height == 0)
|
|
||||||
{
|
{
|
||||||
Console.WriteLine("No custom resolution provided, using desktop resolution");
|
windowSize = requestWindowSize;
|
||||||
WindowSize = new Size(display.w, display.h);
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine("Using resolution: {0}x{1}", WindowSize.Width, WindowSize.Height);
|
// Disable legacy scaling on Windows
|
||||||
|
if (Platform.CurrentPlatform == PlatformType.Windows && !Game.Settings.Graphics.DisableWindowsDPIScaling)
|
||||||
|
SetProcessDPIAware();
|
||||||
|
|
||||||
var windowFlags = SDL.SDL_WindowFlags.SDL_WINDOW_OPENGL | SDL.SDL_WindowFlags.SDL_WINDOW_ALLOW_HIGHDPI;
|
SDL.SDL_Init(SDL.SDL_INIT_NOPARACHUTE | SDL.SDL_INIT_VIDEO);
|
||||||
|
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_DOUBLEBUFFER, 1);
|
||||||
|
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_RED_SIZE, 8);
|
||||||
|
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_GREEN_SIZE, 8);
|
||||||
|
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_BLUE_SIZE, 8);
|
||||||
|
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_ALPHA_SIZE, 0);
|
||||||
|
|
||||||
// HiDPI doesn't work properly on OSX with (legacy) fullscreen mode
|
SDL.SDL_DisplayMode display;
|
||||||
if (Platform.CurrentPlatform == PlatformType.OSX && windowMode == WindowMode.Fullscreen)
|
SDL.SDL_GetCurrentDisplayMode(0, out display);
|
||||||
SDL.SDL_SetHint(SDL.SDL_HINT_VIDEO_HIGHDPI_DISABLED, "1");
|
|
||||||
|
|
||||||
Window = SDL.SDL_CreateWindow("OpenRA", SDL.SDL_WINDOWPOS_CENTERED, SDL.SDL_WINDOWPOS_CENTERED,
|
Console.WriteLine("Desktop resolution: {0}x{1}", display.w, display.h);
|
||||||
WindowSize.Width, WindowSize.Height, windowFlags);
|
if (windowSize.Width == 0 && windowSize.Height == 0)
|
||||||
|
|
||||||
SurfaceSize = WindowSize;
|
|
||||||
WindowScale = 1;
|
|
||||||
|
|
||||||
// Enable high resolution rendering for Retina displays
|
|
||||||
if (Platform.CurrentPlatform == PlatformType.OSX)
|
|
||||||
{
|
|
||||||
// OSX defines the window size in "points", with a device-dependent number of pixels per point.
|
|
||||||
// The window scale is simply the ratio of GL pixels / window points.
|
|
||||||
int width, height;
|
|
||||||
SDL.SDL_GL_GetDrawableSize(Window, out width, out height);
|
|
||||||
SurfaceSize = new Size(width, height);
|
|
||||||
WindowScale = width * 1f / WindowSize.Width;
|
|
||||||
}
|
|
||||||
else if (Platform.CurrentPlatform == PlatformType.Windows)
|
|
||||||
{
|
|
||||||
float ddpi, hdpi, vdpi;
|
|
||||||
if (!Game.Settings.Graphics.DisableWindowsDPIScaling && SDL.SDL_GetDisplayDPI(0, out ddpi, out hdpi, out vdpi) == 0)
|
|
||||||
{
|
{
|
||||||
WindowScale = ddpi / 96;
|
Console.WriteLine("No custom resolution provided, using desktop resolution");
|
||||||
WindowSize = new Size((int)(SurfaceSize.Width / WindowScale), (int)(SurfaceSize.Height / WindowScale));
|
windowSize = new Size(display.w, display.h);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
float scale = 1;
|
|
||||||
var scaleVariable = Environment.GetEnvironmentVariable("OPENRA_DISPLAY_SCALE");
|
|
||||||
if (scaleVariable != null && float.TryParse(scaleVariable, out scale))
|
|
||||||
{
|
|
||||||
WindowScale = scale;
|
|
||||||
WindowSize = new Size((int)(SurfaceSize.Width / WindowScale), (int)(SurfaceSize.Height / WindowScale));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Console.WriteLine("Using window scale {0:F2}", WindowScale);
|
Console.WriteLine("Using resolution: {0}x{1}", windowSize.Width, windowSize.Height);
|
||||||
|
|
||||||
if (Game.Settings.Game.LockMouseWindow)
|
var windowFlags = SDL.SDL_WindowFlags.SDL_WINDOW_OPENGL | SDL.SDL_WindowFlags.SDL_WINDOW_ALLOW_HIGHDPI;
|
||||||
GrabWindowMouseFocus();
|
|
||||||
else
|
|
||||||
ReleaseWindowMouseFocus();
|
|
||||||
|
|
||||||
if (windowMode == WindowMode.Fullscreen)
|
// HiDPI doesn't work properly on OSX with (legacy) fullscreen mode
|
||||||
{
|
if (Platform.CurrentPlatform == PlatformType.OSX && windowMode == WindowMode.Fullscreen)
|
||||||
SDL.SDL_SetWindowFullscreen(Window, (uint)SDL.SDL_WindowFlags.SDL_WINDOW_FULLSCREEN);
|
SDL.SDL_SetHint(SDL.SDL_HINT_VIDEO_HIGHDPI_DISABLED, "1");
|
||||||
|
|
||||||
// Fullscreen mode on OSX will ignore the configured display resolution
|
window = SDL.SDL_CreateWindow("OpenRA", SDL.SDL_WINDOWPOS_CENTERED, SDL.SDL_WINDOWPOS_CENTERED,
|
||||||
// and instead always picks an arbitrary scaled resolution choice that may
|
windowSize.Width, windowSize.Height, windowFlags);
|
||||||
// not match the window size, leading to graphical and input issues.
|
|
||||||
// We work around this by force disabling HiDPI and resetting the window and
|
surfaceSize = windowSize;
|
||||||
// surface sizes to match the size that is forced by SDL.
|
windowScale = 1;
|
||||||
// This is usually not what the player wants, but is the best we can consistently do.
|
|
||||||
|
// Enable high resolution rendering for Retina displays
|
||||||
if (Platform.CurrentPlatform == PlatformType.OSX)
|
if (Platform.CurrentPlatform == PlatformType.OSX)
|
||||||
{
|
{
|
||||||
|
// OSX defines the window size in "points", with a device-dependent number of pixels per point.
|
||||||
|
// The window scale is simply the ratio of GL pixels / window points.
|
||||||
int width, height;
|
int width, height;
|
||||||
SDL.SDL_GetWindowSize(Window, out width, out height);
|
|
||||||
WindowSize = SurfaceSize = new Size(width, height);
|
|
||||||
WindowScale = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (windowMode == WindowMode.PseudoFullscreen)
|
|
||||||
{
|
|
||||||
// Work around a visual glitch in OSX: the window is offset
|
|
||||||
// partially offscreen if the dock is at the left of the screen
|
|
||||||
if (Platform.CurrentPlatform == PlatformType.OSX)
|
|
||||||
SDL.SDL_SetWindowPosition(Window, 0, 0);
|
|
||||||
|
|
||||||
SDL.SDL_SetWindowFullscreen(Window, (uint)SDL.SDL_WindowFlags.SDL_WINDOW_FULLSCREEN_DESKTOP);
|
SDL.SDL_GL_GetDrawableSize(Window, out width, out height);
|
||||||
SDL.SDL_SetHint(SDL.SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
|
surfaceSize = new Size(width, height);
|
||||||
|
windowScale = width * 1f / windowSize.Width;
|
||||||
|
}
|
||||||
|
else if (Platform.CurrentPlatform == PlatformType.Windows)
|
||||||
|
{
|
||||||
|
float ddpi, hdpi, vdpi;
|
||||||
|
if (!Game.Settings.Graphics.DisableWindowsDPIScaling && SDL.SDL_GetDisplayDPI(0, out ddpi, out hdpi, out vdpi) == 0)
|
||||||
|
{
|
||||||
|
windowScale = ddpi / 96;
|
||||||
|
windowSize = new Size((int)(surfaceSize.Width / windowScale), (int)(surfaceSize.Height / windowScale));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
float scale = 1;
|
||||||
|
var scaleVariable = Environment.GetEnvironmentVariable("OPENRA_DISPLAY_SCALE");
|
||||||
|
if (scaleVariable != null && float.TryParse(scaleVariable, out scale))
|
||||||
|
{
|
||||||
|
windowScale = scale;
|
||||||
|
windowSize = new Size((int)(surfaceSize.Width / windowScale), (int)(surfaceSize.Height / windowScale));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("Using window scale {0:F2}", windowScale);
|
||||||
|
|
||||||
|
if (Game.Settings.Game.LockMouseWindow)
|
||||||
|
GrabWindowMouseFocus();
|
||||||
|
else
|
||||||
|
ReleaseWindowMouseFocus();
|
||||||
|
|
||||||
|
if (windowMode == WindowMode.Fullscreen)
|
||||||
|
{
|
||||||
|
SDL.SDL_SetWindowFullscreen(Window, (uint)SDL.SDL_WindowFlags.SDL_WINDOW_FULLSCREEN);
|
||||||
|
|
||||||
|
// Fullscreen mode on OSX will ignore the configured display resolution
|
||||||
|
// and instead always picks an arbitrary scaled resolution choice that may
|
||||||
|
// not match the window size, leading to graphical and input issues.
|
||||||
|
// We work around this by force disabling HiDPI and resetting the window and
|
||||||
|
// surface sizes to match the size that is forced by SDL.
|
||||||
|
// This is usually not what the player wants, but is the best we can consistently do.
|
||||||
|
if (Platform.CurrentPlatform == PlatformType.OSX)
|
||||||
|
{
|
||||||
|
int width, height;
|
||||||
|
SDL.SDL_GetWindowSize(Window, out width, out height);
|
||||||
|
windowSize = surfaceSize = new Size(width, height);
|
||||||
|
windowScale = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (windowMode == WindowMode.PseudoFullscreen)
|
||||||
|
{
|
||||||
|
// Work around a visual glitch in OSX: the window is offset
|
||||||
|
// partially offscreen if the dock is at the left of the screen
|
||||||
|
if (Platform.CurrentPlatform == PlatformType.OSX)
|
||||||
|
SDL.SDL_SetWindowPosition(Window, 0, 0);
|
||||||
|
|
||||||
|
SDL.SDL_SetWindowFullscreen(Window, (uint)SDL.SDL_WindowFlags.SDL_WINDOW_FULLSCREEN_DESKTOP);
|
||||||
|
SDL.SDL_SetHint(SDL.SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "0");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
context = new Sdl2GraphicsContext(this);
|
context = new Sdl2GraphicsContext(this);
|
||||||
@@ -207,11 +250,15 @@ namespace OpenRA.Platforms.Default
|
|||||||
|
|
||||||
if (width != SurfaceSize.Width || height != SurfaceSize.Height)
|
if (width != SurfaceSize.Width || height != SurfaceSize.Height)
|
||||||
{
|
{
|
||||||
var oldScale = WindowScale;
|
float oldScale;
|
||||||
SurfaceSize = new Size(width, height);
|
lock (syncObject)
|
||||||
WindowScale = width * 1f / WindowSize.Width;
|
{
|
||||||
|
oldScale = windowScale;
|
||||||
|
surfaceSize = new Size(width, height);
|
||||||
|
windowScale = width * 1f / windowSize.Width;
|
||||||
|
}
|
||||||
|
|
||||||
OnWindowScaleChanged(oldScale, WindowScale);
|
OnWindowScaleChanged(oldScale, windowScale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user