Add support for retina displays on OSX.
This commit is contained in:
@@ -43,6 +43,8 @@ namespace OpenRA
|
|||||||
IShader CreateShader(string name);
|
IShader CreateShader(string name);
|
||||||
|
|
||||||
Size WindowSize { get; }
|
Size WindowSize { get; }
|
||||||
|
float WindowScale { get; }
|
||||||
|
event Action<float, float> OnWindowScaleChanged;
|
||||||
|
|
||||||
void Clear();
|
void Clear();
|
||||||
void Present();
|
void Present();
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ namespace OpenRA
|
|||||||
fontSheetBuilder.Dispose();
|
fontSheetBuilder.Dispose();
|
||||||
fontSheetBuilder = new SheetBuilder(SheetType.BGRA);
|
fontSheetBuilder = new SheetBuilder(SheetType.BGRA);
|
||||||
Fonts = modData.Manifest.Fonts.ToDictionary(x => x.Key,
|
Fonts = modData.Manifest.Fonts.ToDictionary(x => x.Key,
|
||||||
x => new SpriteFont(x.Value.First, modData.DefaultFileSystem.Open(x.Value.First).ReadAllBytes(), x.Value.Second, fontSheetBuilder)).AsReadOnly();
|
x => new SpriteFont(x.Value.First, modData.DefaultFileSystem.Open(x.Value.First).ReadAllBytes(), x.Value.Second, Device.WindowScale, fontSheetBuilder)).AsReadOnly();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,10 +21,15 @@ namespace OpenRA.Platforms.Default
|
|||||||
sealed class Sdl2GraphicsDevice : ThreadAffine, IGraphicsDevice
|
sealed class Sdl2GraphicsDevice : ThreadAffine, IGraphicsDevice
|
||||||
{
|
{
|
||||||
readonly Sdl2Input input;
|
readonly Sdl2Input input;
|
||||||
|
|
||||||
IntPtr context, window;
|
IntPtr context, window;
|
||||||
bool disposed;
|
bool disposed;
|
||||||
|
|
||||||
public Size WindowSize { get; private set; }
|
public Size WindowSize { get; private set; }
|
||||||
|
public float WindowScale { get; private set; }
|
||||||
|
|
||||||
|
internal Size SurfaceSize { get; private set; }
|
||||||
|
public event Action<float, float> OnWindowScaleChanged = (before, after) => { };
|
||||||
|
|
||||||
public Sdl2GraphicsDevice(Size windowSize, WindowMode windowMode)
|
public Sdl2GraphicsDevice(Size windowSize, WindowMode windowMode)
|
||||||
{
|
{
|
||||||
@@ -50,8 +55,28 @@ namespace OpenRA.Platforms.Default
|
|||||||
|
|
||||||
Console.WriteLine("Using resolution: {0}x{1}", WindowSize.Width, WindowSize.Height);
|
Console.WriteLine("Using resolution: {0}x{1}", WindowSize.Width, WindowSize.Height);
|
||||||
|
|
||||||
|
var windowFlags = SDL.SDL_WindowFlags.SDL_WINDOW_OPENGL;
|
||||||
|
if (Platform.CurrentPlatform == PlatformType.OSX)
|
||||||
|
windowFlags |= SDL.SDL_WindowFlags.SDL_WINDOW_ALLOW_HIGHDPI;
|
||||||
|
|
||||||
window = SDL.SDL_CreateWindow("OpenRA", SDL.SDL_WINDOWPOS_CENTERED, SDL.SDL_WINDOWPOS_CENTERED,
|
window = SDL.SDL_CreateWindow("OpenRA", SDL.SDL_WINDOWPOS_CENTERED, SDL.SDL_WINDOWPOS_CENTERED,
|
||||||
WindowSize.Width, WindowSize.Height, SDL.SDL_WindowFlags.SDL_WINDOW_OPENGL);
|
WindowSize.Width, WindowSize.Height, windowFlags);
|
||||||
|
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("Using window scale {0:F2}", WindowScale);
|
||||||
|
|
||||||
if (Game.Settings.Game.LockMouseWindow)
|
if (Game.Settings.Game.LockMouseWindow)
|
||||||
GrabWindowMouseFocus();
|
GrabWindowMouseFocus();
|
||||||
@@ -114,6 +139,26 @@ namespace OpenRA.Platforms.Default
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void WindowSizeChanged()
|
||||||
|
{
|
||||||
|
// The ratio between pixels and points can change when moving between displays in OSX
|
||||||
|
// We need to recalculate our scale to account for the potential change in the actual rendered area
|
||||||
|
if (Platform.CurrentPlatform == PlatformType.OSX)
|
||||||
|
{
|
||||||
|
int width, height;
|
||||||
|
SDL.SDL_GL_GetDrawableSize(window, out width, out height);
|
||||||
|
|
||||||
|
if (width != SurfaceSize.Width || height != SurfaceSize.Height)
|
||||||
|
{
|
||||||
|
var oldScale = WindowScale;
|
||||||
|
SurfaceSize = new Size(width, height);
|
||||||
|
WindowScale = width * 1f / WindowSize.Width;
|
||||||
|
|
||||||
|
OnWindowScaleChanged(oldScale, WindowScale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
sealed class SDL2HardwareCursor : IHardwareCursor
|
sealed class SDL2HardwareCursor : IHardwareCursor
|
||||||
{
|
{
|
||||||
public IntPtr Cursor { get; private set; }
|
public IntPtr Cursor { get; private set; }
|
||||||
@@ -315,7 +360,16 @@ namespace OpenRA.Platforms.Default
|
|||||||
if (height < 0)
|
if (height < 0)
|
||||||
height = 0;
|
height = 0;
|
||||||
|
|
||||||
OpenGL.glScissor(left, WindowSize.Height - (top + height), width, height);
|
var bottom = WindowSize.Height - (top + height);
|
||||||
|
if (WindowSize != SurfaceSize)
|
||||||
|
{
|
||||||
|
left = (int)Math.Round(WindowScale * left);
|
||||||
|
bottom = (int)Math.Round(WindowScale * bottom);
|
||||||
|
width = (int)Math.Round(WindowScale * width);
|
||||||
|
height = (int)Math.Round(WindowScale * height);
|
||||||
|
}
|
||||||
|
|
||||||
|
OpenGL.glScissor(left, bottom, width, height);
|
||||||
OpenGL.CheckGLError();
|
OpenGL.CheckGLError();
|
||||||
OpenGL.glEnable(OpenGL.GL_SCISSOR_TEST);
|
OpenGL.glEnable(OpenGL.GL_SCISSOR_TEST);
|
||||||
OpenGL.CheckGLError();
|
OpenGL.CheckGLError();
|
||||||
@@ -330,7 +384,7 @@ namespace OpenRA.Platforms.Default
|
|||||||
|
|
||||||
public Bitmap TakeScreenshot()
|
public Bitmap TakeScreenshot()
|
||||||
{
|
{
|
||||||
var rect = new Rectangle(Point.Empty, WindowSize);
|
var rect = new Rectangle(Point.Empty, SurfaceSize);
|
||||||
var bitmap = new Bitmap(rect.Width, rect.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
var bitmap = new Bitmap(rect.Width, rect.Height, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
||||||
var data = bitmap.LockBits(rect,
|
var data = bitmap.LockBits(rect,
|
||||||
System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
System.Drawing.Imaging.ImageLockMode.WriteOnly, System.Drawing.Imaging.PixelFormat.Format32bppArgb);
|
||||||
@@ -362,7 +416,7 @@ namespace OpenRA.Platforms.Default
|
|||||||
public void PumpInput(IInputHandler inputHandler)
|
public void PumpInput(IInputHandler inputHandler)
|
||||||
{
|
{
|
||||||
VerifyThreadAffinity();
|
VerifyThreadAffinity();
|
||||||
input.PumpInput(inputHandler);
|
input.PumpInput(this, inputHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetClipboardText()
|
public string GetClipboardText()
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ namespace OpenRA.Platforms.Default
|
|||||||
| ((raw & (int)SDL.SDL_Keymod.KMOD_SHIFT) != 0 ? Modifiers.Shift : 0);
|
| ((raw & (int)SDL.SDL_Keymod.KMOD_SHIFT) != 0 ? Modifiers.Shift : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void PumpInput(IInputHandler inputHandler)
|
public void PumpInput(Sdl2GraphicsDevice device, IInputHandler inputHandler)
|
||||||
{
|
{
|
||||||
var mods = MakeModifiers((int)SDL.SDL_GetModState());
|
var mods = MakeModifiers((int)SDL.SDL_GetModState());
|
||||||
var scrollDelta = 0;
|
var scrollDelta = 0;
|
||||||
@@ -67,6 +67,11 @@ namespace OpenRA.Platforms.Default
|
|||||||
case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_FOCUS_GAINED:
|
case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_FOCUS_GAINED:
|
||||||
Game.HasInputFocus = true;
|
Game.HasInputFocus = true;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// Triggered when moving between displays with different DPI settings
|
||||||
|
case SDL.SDL_WindowEventID.SDL_WINDOWEVENT_SIZE_CHANGED:
|
||||||
|
device.WindowSizeChanged();
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
|||||||
Reference in New Issue
Block a user