diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs index 1ccdb57396..15c5c68756 100644 --- a/OpenRA.Game/Game.cs +++ b/OpenRA.Game/Game.cs @@ -679,21 +679,18 @@ namespace OpenRA } // worldRenderer is null during the initial install/download screen - if (worldRenderer != null) + // World rendering is disabled while the loading screen is displayed + // Use worldRenderer.World instead of OrderManager.World to avoid a rendering mismatch while processing orders + if (worldRenderer != null && !worldRenderer.World.IsLoadingGameSave) { - Renderer.BeginFrame(worldRenderer.Viewport.TopLeft, worldRenderer.Viewport.Zoom); + Renderer.BeginWorld(worldRenderer.Viewport.TopLeft, worldRenderer.Viewport.Zoom); Sound.SetListenerPosition(worldRenderer.Viewport.CenterPosition); - - // World rendering is disabled while the loading screen is displayed - // Use worldRenderer.World instead of OrderManager.World to avoid a rendering mismatch while processing orders - if (!worldRenderer.World.IsLoadingGameSave) - worldRenderer.Draw(); + worldRenderer.Draw(); } - else - Renderer.BeginFrame(int2.Zero, 1f); using (new PerfSample("render_widgets")) { + Renderer.BeginUI(); Ui.Draw(); if (ModData != null && ModData.CursorProvider != null) diff --git a/OpenRA.Game/Renderer.cs b/OpenRA.Game/Renderer.cs index fcaded25d3..3a416a5565 100644 --- a/OpenRA.Game/Renderer.cs +++ b/OpenRA.Game/Renderer.cs @@ -22,6 +22,8 @@ namespace OpenRA { public sealed class Renderer : IDisposable { + enum RenderType { None, World, UI } + public SpriteRenderer WorldSpriteRenderer { get; private set; } public RgbaSpriteRenderer WorldRgbaSpriteRenderer { get; private set; } public RgbaColorRenderer WorldRgbaColorRenderer { get; private set; } @@ -54,6 +56,7 @@ namespace OpenRA float lastZoom = -1f; ITexture currentPaletteTexture; IBatchRenderer currentBatchRenderer; + RenderType renderType = RenderType.None; public Renderer(IPlatform platform, GraphicSettings graphicSettings) { @@ -125,7 +128,7 @@ namespace OpenRA depthOffset = depthScale / 2; } - public void BeginFrame(int2 scroll, float zoom) + void BeginFrame() { Context.Clear(); @@ -151,33 +154,50 @@ namespace OpenRA } screenBuffer.Bind(); - SetViewportParams(scroll, zoom); - } - public void SetViewportParams(int2 scroll, float zoom) - { // In HiDPI windows we follow Apple's convention of defining window coordinates as for standard resolution windows // but to have a higher resolution backing surface with more than 1 texture pixel per viewport pixel. // We must convert the surface buffer size to a viewport size - in general this is NOT just the window size // rounded to the next power of two, as the NextPowerOf2 calculation is done in the surface pixel coordinates var scale = Window.WindowScale; - var surfaceBufferSize = Window.SurfaceSize.NextPowerOf2(); var bufferSize = new Size((int)(surfaceBufferSize.Width / scale), (int)(surfaceBufferSize.Height / scale)); - - // PERF: Calling SetViewportParams on each renderer is slow. Only call it when things change. - // If zoom evaluates as different due to floating point weirdness that's OK, it will be going away soon - if (lastBufferSize != bufferSize || lastScroll != scroll || lastZoom != zoom) + if (lastBufferSize != bufferSize) { - if (lastBufferSize != bufferSize) - SpriteRenderer.SetViewportParams(bufferSize, 0f, 0f, 1f, int2.Zero); + SpriteRenderer.SetViewportParams(bufferSize, 0f, 0f, 1f, int2.Zero); + lastBufferSize = bufferSize; + } + } + public void BeginWorld(int2 scroll, float zoom) + { + if (renderType != RenderType.None) + throw new InvalidOperationException("BeginWorld called with renderType = {0}, expected RenderType.None.".F(renderType)); + + var oldLastBufferSize = lastBufferSize; + BeginFrame(); + + var scale = Window.WindowScale; + var surfaceSize = Window.SurfaceSize; + var surfaceBufferSize = surfaceSize.NextPowerOf2(); + var bufferSize = new Size((int)(surfaceBufferSize.Width / scale), (int)(surfaceBufferSize.Height / scale)); + if (oldLastBufferSize != bufferSize || lastScroll != scroll || lastZoom != zoom) + { WorldSpriteRenderer.SetViewportParams(bufferSize, depthScale, depthOffset, zoom, scroll); WorldModelRenderer.SetViewportParams(bufferSize, zoom, scroll); - lastBufferSize = bufferSize; lastScroll = scroll; lastZoom = zoom; } + + renderType = RenderType.World; + } + + public void BeginUI() + { + if (renderType == RenderType.None) + BeginFrame(); + + renderType = RenderType.UI; } public void SetPalette(HardwarePalette palette) @@ -195,6 +215,9 @@ namespace OpenRA public void EndFrame(IInputHandler inputHandler) { + if (renderType != RenderType.UI) + throw new InvalidOperationException("EndFrame called with renderType = {0}, expected RenderType.UI.".F(renderType)); + Flush(); screenBuffer.Unbind(); @@ -207,6 +230,8 @@ namespace OpenRA Window.PumpInput(inputHandler); Context.Present(); + + renderType = RenderType.None; } public void DrawBatch(Vertex[] vertices, int numVertices, PrimitiveType type) diff --git a/OpenRA.Mods.Cnc/CncLoadScreen.cs b/OpenRA.Mods.Cnc/CncLoadScreen.cs index 506fbd31d9..85c4a23d61 100644 --- a/OpenRA.Mods.Cnc/CncLoadScreen.cs +++ b/OpenRA.Mods.Cnc/CncLoadScreen.cs @@ -86,7 +86,7 @@ namespace OpenRA.Mods.Cnc loadTimer.Restart(); loadTick = ++loadTick % 8; - r.BeginFrame(int2.Zero, 1f); + r.BeginUI(); r.RgbaSpriteRenderer.DrawSprite(gdiLogo, gdiPos); r.RgbaSpriteRenderer.DrawSprite(nodLogo, nodPos); r.RgbaSpriteRenderer.DrawSprite(evaLogo, evaPos); diff --git a/OpenRA.Mods.Common/LoadScreens/BlankLoadScreen.cs b/OpenRA.Mods.Common/LoadScreens/BlankLoadScreen.cs index 584542c1e9..28cbe5c702 100644 --- a/OpenRA.Mods.Common/LoadScreens/BlankLoadScreen.cs +++ b/OpenRA.Mods.Common/LoadScreens/BlankLoadScreen.cs @@ -35,7 +35,7 @@ namespace OpenRA.Mods.Common.LoadScreens return; // Draw a black screen - Game.Renderer.BeginFrame(int2.Zero, 1f); + Game.Renderer.BeginUI(); Game.Renderer.EndFrame(new NullInputHandler()); } diff --git a/OpenRA.Mods.Common/LoadScreens/LogoStripeLoadScreen.cs b/OpenRA.Mods.Common/LoadScreens/LogoStripeLoadScreen.cs index f8e6b382a0..f8444fae4c 100644 --- a/OpenRA.Mods.Common/LoadScreens/LogoStripeLoadScreen.cs +++ b/OpenRA.Mods.Common/LoadScreens/LogoStripeLoadScreen.cs @@ -70,7 +70,7 @@ namespace OpenRA.Mods.Common.LoadScreens var text = messages.Random(Game.CosmeticRandom); var textSize = r.Fonts["Bold"].Measure(text); - r.BeginFrame(int2.Zero, 1f); + r.BeginUI(); if (stripe != null) WidgetUtils.FillRectWithSprite(stripeRect, stripe); diff --git a/OpenRA.Mods.Common/LoadScreens/ModContentLoadScreen.cs b/OpenRA.Mods.Common/LoadScreens/ModContentLoadScreen.cs index 5809a795cf..6593941d40 100644 --- a/OpenRA.Mods.Common/LoadScreens/ModContentLoadScreen.cs +++ b/OpenRA.Mods.Common/LoadScreens/ModContentLoadScreen.cs @@ -43,7 +43,7 @@ namespace OpenRA.Mods.Common.LoadScreens if (r == null) return; - r.BeginFrame(int2.Zero, 1f); + r.BeginUI(); WidgetUtils.FillRectWithSprite(bounds, sprite); r.EndFrame(new NullInputHandler()); }