Rename to graphics surface and invert data path

This commit is contained in:
Dan Balasescu
2022-12-02 21:40:43 +09:00
parent 325ee2e6eb
commit 695c3b6f73
25 changed files with 168 additions and 169 deletions

View File

@@ -38,7 +38,7 @@ namespace osu.Framework.Android
base.SetupConfig(defaultOverrides);
}
protected override IWindow CreateWindow() => new AndroidGameWindow(gameView);
protected override IWindow CreateWindow(GraphicsSurfaceType preferredSurface) => new AndroidGameWindow(gameView);
public override bool CanExit => false;

View File

@@ -47,7 +47,7 @@ namespace osu.Framework.iOS
true);
}
protected override IWindow CreateWindow() => new IOSGameWindow(gameView);
protected override IWindow CreateWindow(GraphicsSurfaceType preferredSurface) => new IOSGameWindow(gameView);
protected override void SetupConfig(IDictionary<FrameworkSetting, object> defaultOverrides)
{

View File

@@ -23,14 +23,12 @@ namespace osu.Framework.Graphics.OpenGL
{
internal class GLRenderer : Renderer
{
public override GraphicsBackend BackendType => GraphicsBackend.OpenGL;
private IOpenGLWindowGraphics openGLGraphics = null!;
private IOpenGLGraphicsSurface openGLSurface = null!;
public override bool VerticalSync
{
get => openGLGraphics.VerticalSync;
set => openGLGraphics.VerticalSync = value;
get => openGLSurface.VerticalSync;
set => openGLSurface.VerticalSync = value;
}
/// <summary>
@@ -49,10 +47,13 @@ namespace osu.Framework.Graphics.OpenGL
private bool? lastBlendingEnabledState;
protected override void Initialise(IWindowGraphics graphics)
protected override void Initialise(IGraphicsSurface graphicsSurface)
{
openGLGraphics = graphics as IOpenGLWindowGraphics ?? throw new ArgumentException($"Window must implement {nameof(IOpenGLWindowGraphics)}.");
openGLGraphics.MakeCurrent(openGLGraphics.WindowContext);
if (graphicsSurface.Type != GraphicsSurfaceType.OpenGL)
throw new InvalidOperationException($"{nameof(GLRenderer)} only supports OpenGL graphics surfaces.");
openGLSurface = (IOpenGLGraphicsSurface)graphicsSurface;
openGLSurface.MakeCurrent(openGLSurface.WindowContext);
string version = GL.GetString(StringName.Version);
IsEmbedded = version.Contains("OpenGL ES"); // As defined by https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glGetString.xml
@@ -70,7 +71,7 @@ namespace osu.Framework.Graphics.OpenGL
GL Vendor: {GL.GetString(StringName.Vendor)}
GL Extensions: {GL.GetString(StringName.Extensions)}");
openGLGraphics.ClearCurrent();
openGLSurface.ClearCurrent();
}
protected internal override void BeginFrame(Vector2 windowSize)
@@ -83,9 +84,9 @@ namespace osu.Framework.Graphics.OpenGL
base.BeginFrame(windowSize);
}
protected internal override void MakeCurrent() => openGLGraphics.MakeCurrent(openGLGraphics.WindowContext);
protected internal override void ClearCurrent() => openGLGraphics.ClearCurrent();
protected internal override void SwapBuffers() => openGLGraphics.SwapBuffers();
protected internal override void MakeCurrent() => openGLSurface.MakeCurrent(openGLSurface.WindowContext);
protected internal override void ClearCurrent() => openGLSurface.ClearCurrent();
protected internal override void SwapBuffers() => openGLSurface.SwapBuffers();
protected internal override void WaitUntilIdle() => GL.Finish();
public bool BindBuffer(BufferTarget target, int buffer)
@@ -180,7 +181,8 @@ namespace osu.Framework.Graphics.OpenGL
return true;
}
protected override void SetFrameBufferImplementation(IFrameBuffer? frameBuffer) => GL.BindFramebuffer(FramebufferTarget.Framebuffer, ((GLFrameBuffer?)frameBuffer)?.FrameBuffer ?? BackbufferFramebuffer);
protected override void SetFrameBufferImplementation(IFrameBuffer? frameBuffer) =>
GL.BindFramebuffer(FramebufferTarget.Framebuffer, ((GLFrameBuffer?)frameBuffer)?.FrameBuffer ?? BackbufferFramebuffer);
/// <summary>
/// Deletes a frame buffer.
@@ -366,7 +368,8 @@ namespace osu.Framework.Graphics.OpenGL
return new GLFrameBuffer(this, glFormats, glFilteringMode);
}
protected override INativeTexture CreateNativeTexture(int width, int height, bool manualMipmaps = false, TextureFilteringMode filteringMode = TextureFilteringMode.Linear, Rgba32 initialisationColour = default)
protected override INativeTexture CreateNativeTexture(int width, int height, bool manualMipmaps = false, TextureFilteringMode filteringMode = TextureFilteringMode.Linear,
Rgba32 initialisationColour = default)
{
All glFilteringMode;

View File

@@ -25,7 +25,6 @@ namespace osu.Framework.Graphics.Rendering.Dummy
public ref readonly MaskingInfo CurrentMaskingInfo => ref maskingInfo;
private readonly MaskingInfo maskingInfo;
public GraphicsBackend BackendType => default;
public bool VerticalSync { get; set; } = true;
public RectangleI Viewport => RectangleI.Empty;
public RectangleF Ortho => RectangleF.Empty;
@@ -49,7 +48,7 @@ namespace osu.Framework.Graphics.Rendering.Dummy
WhitePixel = new Texture(new DummyNativeTexture(this), WrapMode.None, WrapMode.None);
}
void IRenderer.Initialise(IWindowGraphics graphics)
void IRenderer.Initialise(IGraphicsSurface graphicsSurface)
{
IsInitialised = true;
}

View File

@@ -42,11 +42,6 @@ namespace osu.Framework.Graphics.Rendering
/// </summary>
public const int MAX_QUADS = ushort.MaxValue / INDICES_PER_QUAD;
/// <summary>
/// The type of the graphics backend represented by this renderer.
/// </summary>
GraphicsBackend BackendType { get; }
/// <summary>
/// Enables or disables vertical sync.
/// </summary>
@@ -142,7 +137,7 @@ namespace osu.Framework.Graphics.Rendering
/// <summary>
/// Performs a once-off initialisation of this <see cref="IRenderer"/>.
/// </summary>
protected internal void Initialise(IWindowGraphics graphics);
protected internal void Initialise(IGraphicsSurface graphicsSurface);
/// <summary>
/// Resets any states to prepare for drawing a new frame.

View File

@@ -33,8 +33,6 @@ namespace osu.Framework.Graphics.Rendering
/// </summary>
private const int vbo_free_check_interval = 300;
public virtual GraphicsBackend BackendType => GraphicsBackend.OpenGL;
public abstract bool VerticalSync { get; set; }
public int MaxTextureSize { get; protected set; } = 4096; // default value is to allow roughly normal flow in cases we don't have graphics context, like headless CI.
@@ -133,9 +131,20 @@ namespace osu.Framework.Graphics.Rendering
new TextureAtlas(this, TextureAtlas.WHITE_PIXEL_SIZE + TextureAtlas.PADDING, TextureAtlas.WHITE_PIXEL_SIZE + TextureAtlas.PADDING, true).WhitePixel);
}
void IRenderer.Initialise(IWindowGraphics graphics)
void IRenderer.Initialise(IGraphicsSurface graphicsSurface)
{
Initialise(graphics);
switch (graphicsSurface.Type)
{
case GraphicsSurfaceType.OpenGL:
Trace.Assert(graphicsSurface is IOpenGLGraphicsSurface, $"Window must implement {nameof(IOpenGLGraphicsSurface)}.");
break;
case GraphicsSurfaceType.Metal:
Trace.Assert(graphicsSurface is IMetalGraphicsSurface, $"Window graphics API must implement {nameof(IMetalGraphicsSurface)}.");
break;
}
Initialise(graphicsSurface);
defaultQuadBatch = CreateQuadBatch<TexturedVertex2D>(100, 1000);
resetScheduler.AddDelayed(disposalQueue.CheckPendingDisposals, 0, true);
@@ -280,7 +289,7 @@ namespace osu.Framework.Graphics.Rendering
/// <summary>
/// Performs a once-off initialisation of this <see cref="Renderer"/>.
/// </summary>
protected abstract void Initialise(IWindowGraphics graphics);
protected abstract void Initialise(IGraphicsSurface graphicsSurface);
/// <summary>
/// Swaps the back buffer with the front buffer to display the new frame.

View File

@@ -15,36 +15,12 @@ using osuTK.Graphics;
using SixLabors.ImageSharp.PixelFormats;
using Veldrid;
using Veldrid.OpenGL;
using GraphicsBackend = osu.Framework.Platform.GraphicsBackend;
using PixelFormat = Veldrid.PixelFormat;
namespace osu.Framework.Graphics.Veldrid
{
internal class VeldridRenderer : Renderer
{
private IWindowGraphics graphics = null!;
public override GraphicsBackend BackendType
{
get
{
switch (RuntimeInfo.OS)
{
case RuntimeInfo.Platform.Windows:
return GraphicsBackend.Direct3D11;
case RuntimeInfo.Platform.macOS:
case RuntimeInfo.Platform.iOS:
return GraphicsBackend.Metal;
default:
case RuntimeInfo.Platform.Linux:
case RuntimeInfo.Platform.Android:
return GraphicsBackend.Vulkan;
}
}
}
public override bool VerticalSync
{
get => Device.SyncToVerticalBlank;
@@ -57,6 +33,8 @@ namespace osu.Framework.Graphics.Veldrid
public CommandList Commands { get; private set; } = null!;
private IGraphicsSurface graphicsSurface = null!;
private GraphicsPipelineDescription pipeline = new GraphicsPipelineDescription
{
RasterizerState = RasterizerStateDescription.CullNone,
@@ -64,15 +42,13 @@ namespace osu.Framework.Graphics.Veldrid
ShaderSet = { VertexLayouts = new VertexLayoutDescription[1] }
};
protected override void Initialise(IWindowGraphics graphics)
protected override void Initialise(IGraphicsSurface graphicsSurface)
{
// Veldrid must either be initialised on the main/"input" thread, or in a separate thread away from the draw thread at least.
// Otherwise the window may not render anything on some platforms (macOS at least).
Debug.Assert(!ThreadSafety.IsDrawThread, "Veldrid cannot be initialised on the draw thread.");
this.graphics = graphics;
var size = graphics.GetDrawableSize();
this.graphicsSurface = graphicsSurface;
var options = new GraphicsDeviceOptions
{
@@ -86,6 +62,8 @@ namespace osu.Framework.Graphics.Veldrid
ResourceBindingModel = ResourceBindingModel.Improved,
};
var size = graphicsSurface.GetDrawableSize();
var swapchain = new SwapchainDescription
{
Width = (uint)size.Width,
@@ -100,11 +78,11 @@ namespace osu.Framework.Graphics.Veldrid
switch (RuntimeInfo.OS)
{
case RuntimeInfo.Platform.Windows:
swapchain.Source = SwapchainSource.CreateWin32(graphics.WindowHandle, IntPtr.Zero);
swapchain.Source = SwapchainSource.CreateWin32(graphicsSurface.WindowHandle, IntPtr.Zero);
break;
case RuntimeInfo.Platform.macOS:
var metalGraphics = graphics as IMetalWindowGraphics ?? throw new InvalidOperationException($"Window graphics API must implement {nameof(IMetalWindowGraphics)}.");
var metalGraphics = (IMetalGraphicsSurface)graphicsSurface;
swapchain.Source = SwapchainSource.CreateNSView(metalGraphics.CreateMetalView());
break;
@@ -114,10 +92,10 @@ namespace osu.Framework.Graphics.Veldrid
break;
}
switch (BackendType)
switch (graphicsSurface.Type)
{
case GraphicsBackend.OpenGL:
var openGLGraphics = graphics as IOpenGLWindowGraphics ?? throw new InvalidOperationException($"Window graphics API must implement {nameof(IOpenGLWindowGraphics)}");
case GraphicsSurfaceType.OpenGL:
var openGLGraphics = (IOpenGLGraphicsSurface)graphicsSurface;
Device = GraphicsDevice.CreateOpenGL(options, new OpenGLPlatformInfo(
openGLContextHandle: openGLGraphics.WindowContext,
@@ -132,17 +110,17 @@ namespace osu.Framework.Graphics.Veldrid
Device.LogOpenGL(out maxTextureSize);
break;
case GraphicsBackend.Vulkan:
case GraphicsSurfaceType.Vulkan:
Device = GraphicsDevice.CreateVulkan(options, swapchain);
Device.LogVulkan(out maxTextureSize);
break;
case GraphicsBackend.Direct3D11:
case GraphicsSurfaceType.Direct3D11:
Device = GraphicsDevice.CreateD3D11(options, swapchain);
Device.LogD3D11(out maxTextureSize);
break;
case GraphicsBackend.Metal:
case GraphicsSurfaceType.Metal:
Device = GraphicsDevice.CreateMetal(options, swapchain);
Device.LogMetal(out maxTextureSize);
break;
@@ -183,18 +161,18 @@ namespace osu.Framework.Graphics.Veldrid
protected internal override void MakeCurrent()
{
if (BackendType == GraphicsBackend.OpenGL)
if (graphicsSurface.Type == GraphicsSurfaceType.OpenGL)
{
var openGLGraphics = (IOpenGLWindowGraphics)graphics;
var openGLGraphics = (IOpenGLGraphicsSurface)graphicsSurface;
openGLGraphics.MakeCurrent(openGLGraphics.WindowContext);
}
}
protected internal override void ClearCurrent()
{
if (BackendType == GraphicsBackend.OpenGL)
if (graphicsSurface.Type == GraphicsSurfaceType.OpenGL)
{
var openGLGraphics = (IOpenGLWindowGraphics)graphics;
var openGLGraphics = (IOpenGLGraphicsSurface)graphicsSurface;
openGLGraphics.ClearCurrent();
}
}

View File

@@ -171,7 +171,7 @@ namespace osu.Framework.Platform
/// <summary>
/// Creates the game window for the host. Should be implemented per-platform if required.
/// </summary>
protected virtual IWindow CreateWindow(GraphicsBackend backend) => null;
protected virtual IWindow CreateWindow(GraphicsSurfaceType preferredSurface) => null;
[CanBeNull]
public virtual Clipboard GetClipboard() => null;
@@ -530,7 +530,7 @@ namespace osu.Framework.Platform
{
Renderer.SwapBuffers();
if (Renderer.BackendType == GraphicsBackend.OpenGL && Renderer.VerticalSync)
if (Window.GraphicsSurface.Type == GraphicsSurfaceType.OpenGL && Renderer.VerticalSync)
// without waiting (i.e. glFinish), vsync is basically unplayable due to the extra latency introduced.
// we will likely want to give the user control over this in the future as an advanced setting.
Renderer.WaitUntilIdle();
@@ -699,7 +699,7 @@ namespace osu.Framework.Platform
SetupForRun();
Window = CreateWindow(Renderer.BackendType);
Window = CreateWindow(GraphicsSurfaceType.OpenGL);
populateInputHandlers();
@@ -714,7 +714,7 @@ namespace osu.Framework.Platform
Window.Create();
Window.Title = $@"osu!framework (running ""{Name}"")";
Renderer.Initialise(Window.Graphics);
Renderer.Initialise(Window);
currentDisplayMode = Window.CurrentDisplayMode.GetBoundCopy();
currentDisplayMode.BindValueChanged(_ => updateFrameSyncMode());

View File

@@ -1,26 +0,0 @@
// 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.ComponentModel;
using osu.Framework.Graphics.Rendering;
namespace osu.Framework.Platform
{
/// <summary>
/// The graphics backend represented by the <see cref="IRenderer"/>.
/// </summary>
public enum GraphicsBackend
{
[Description("OpenGL")]
OpenGL,
[Description("Metal")]
Metal,
[Description("Vulkan")]
Vulkan,
[Description("Direct3D 11")]
Direct3D11,
}
}

View File

@@ -0,0 +1,37 @@
// 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.ComponentModel;
namespace osu.Framework.Platform
{
/// <summary>
/// The graphics surface of an <see cref="IWindow"/>.
/// </summary>
public enum GraphicsSurfaceType
{
/// <summary>
/// An OpenGL graphics surface. The window must implement <see cref="IOpenGLGraphicsSurface"/>.
/// </summary>
[Description("OpenGL")]
OpenGL,
/// <summary>
/// A Metal graphics surface. The window must implement <see cref="IMetalGraphicsSurface"/>.
/// </summary>
[Description("Metal")]
Metal,
/// <summary>
/// A Vulkan graphics surface.
/// </summary>
[Description("Vulkan")]
Vulkan,
/// <summary>
/// A Direct3D11 graphics surface.
/// </summary>
[Description("Direct3D 11")]
Direct3D11,
}
}

View File

@@ -7,9 +7,9 @@ using System.Drawing;
namespace osu.Framework.Platform
{
/// <summary>
/// Represents the graphics API provided by an <see cref="IWindow"/>.
/// Represents the graphics API surface provided by an <see cref="IWindow"/>.
/// </summary>
public interface IWindowGraphics
public interface IGraphicsSurface
{
/// <summary>
/// A pointer representing a handle to this window, provided by the operating system.
@@ -23,9 +23,9 @@ namespace osu.Framework.Platform
IntPtr DisplayHandle { get; }
/// <summary>
/// The type of the graphics backend represented by this renderer.
/// The type of surface.
/// </summary>
GraphicsBackend BackendType { get; }
GraphicsSurfaceType Type { get; }
/// <summary>
/// Performs an initialisation of the graphics backend after <see cref="IWindow"/> has been created.

View File

@@ -8,7 +8,7 @@ namespace osu.Framework.Platform
/// <summary>
/// Represents Metal-specific graphics API provided by an <see cref="IWindow"/>.
/// </summary>
public interface IMetalWindowGraphics
public interface IMetalGraphicsSurface
{
/// <summary>
/// Creates an NSView backed with a Metal layer.

View File

@@ -8,7 +8,7 @@ namespace osu.Framework.Platform
/// <summary>
/// Represents OpenGL-specific graphics API provided by an <see cref="IWindow"/>.
/// </summary>
public interface IOpenGLWindowGraphics
public interface IOpenGLGraphicsSurface
{
/// <summary>
/// Enables or disables vertical sync.

View File

@@ -21,7 +21,7 @@ namespace osu.Framework.Platform
/// <summary>
/// The graphics API for this window.
/// </summary>
internal IWindowGraphics Graphics { get; }
internal IGraphicsSurface GraphicsSurface { get; }
/// <summary>
/// Cycles through the available <see cref="WindowMode"/>s as determined by <see cref="SupportedWindowModes"/>.

View File

@@ -35,7 +35,7 @@ namespace osu.Framework.Platform.Linux
base.SetupForRun();
}
protected override IWindow CreateWindow(GraphicsBackend backend) => new SDL2DesktopWindow(backend);
protected override IWindow CreateWindow(GraphicsSurfaceType preferredSurface) => new SDL2DesktopWindow(preferredSurface);
public override IEnumerable<string> UserStoragePaths
{

View File

@@ -21,7 +21,7 @@ namespace osu.Framework.Platform.MacOS
{
}
protected override IWindow CreateWindow(GraphicsBackend backend) => new MacOSWindow(backend);
protected override IWindow CreateWindow(GraphicsSurfaceType preferredSurface) => new MacOSWindow(preferredSurface);
public override IEnumerable<string> UserStoragePaths
{
@@ -50,7 +50,7 @@ namespace osu.Framework.Platform.MacOS
base.Swap();
// It has been reported that this helps performance on macOS (https://github.com/ppy/osu/issues/7447)
if (Renderer.BackendType == GraphicsBackend.OpenGL && !Renderer.VerticalSync)
if (Window.GraphicsSurface.Type == GraphicsSurfaceType.OpenGL && !Renderer.VerticalSync)
Renderer.WaitUntilIdle();
}

View File

@@ -24,8 +24,8 @@ namespace osu.Framework.Platform.MacOS
private IntPtr originalScrollWheel;
private ScrollWheelDelegate scrollWheelHandler;
public MacOSWindow(GraphicsBackend backend)
: base(backend)
public MacOSWindow(GraphicsSurfaceType surfaceType)
: base(surfaceType)
{
}

View File

@@ -12,11 +12,11 @@ using osuTK.Platform;
namespace osu.Framework.Platform
{
public class OsuTKWindowGraphics : IWindowGraphics, IOpenGLWindowGraphics
public class OsuTKGraphicsSurface : IGraphicsSurface, IOpenGLGraphicsSurface
{
private readonly IGameWindow window;
public GraphicsBackend BackendType => GraphicsBackend.OpenGL;
public GraphicsSurfaceType Type => GraphicsSurfaceType.OpenGL;
public IntPtr WindowHandle => window.WindowInfo.Handle;
public IntPtr DisplayHandle => throw new NotSupportedException($@"{nameof(DisplayHandle)} is not supported.");
@@ -29,7 +29,7 @@ namespace osu.Framework.Platform
internal Version GLSLVersion;
internal bool IsEmbedded;
public OsuTKWindowGraphics(IGameWindow window)
public OsuTKGraphicsSurface(IGameWindow window)
{
this.window = window;
}

View File

@@ -24,9 +24,8 @@ namespace osu.Framework.Platform
{
public abstract class OsuTKWindow : IWindow, IGameWindow
{
private readonly IWindowGraphics graphics;
IWindowGraphics IWindow.Graphics => graphics;
private readonly IGraphicsSurface graphicsSurface;
IGraphicsSurface IWindow.GraphicsSurface => graphicsSurface;
/// <summary>
/// The <see cref="IGraphicsContext"/> associated with this <see cref="OsuTKWindow"/>.
@@ -142,8 +141,8 @@ namespace osu.Framework.Platform
UpdateFrame += (_, _) => UpdateFrameScheduler.Update();
graphics = new OsuTKWindowGraphics(this);
graphics.Initialise();
graphicsSurface = new OsuTKGraphicsSurface(this);
graphicsSurface.Initialise();
}
/// <summary>

View File

@@ -903,18 +903,18 @@ namespace osu.Framework.Platform.SDL2
return 0;
}
public static SDL.SDL_WindowFlags ToFlags(this GraphicsBackend backend)
public static SDL.SDL_WindowFlags ToFlags(this GraphicsSurfaceType surfaceType)
{
switch (backend)
switch (surfaceType)
{
case GraphicsBackend.OpenGL:
case GraphicsSurfaceType.OpenGL:
return SDL.SDL_WindowFlags.SDL_WINDOW_OPENGL;
case GraphicsBackend.Vulkan when !RuntimeInfo.IsApple:
case GraphicsSurfaceType.Vulkan when !RuntimeInfo.IsApple:
return SDL.SDL_WindowFlags.SDL_WINDOW_VULKAN;
case GraphicsBackend.Metal:
case GraphicsBackend.Vulkan when RuntimeInfo.IsApple:
case GraphicsSurfaceType.Metal:
case GraphicsSurfaceType.Vulkan when RuntimeInfo.IsApple:
return SDL.SDL_WindowFlags.SDL_WINDOW_METAL;
}

View File

@@ -13,7 +13,7 @@ using SDL2;
namespace osu.Framework.Platform.SDL2
{
public class SDL2WindowGraphics : IWindowGraphics, IOpenGLWindowGraphics, IMetalWindowGraphics
public class SDL2GraphicsSurface : IGraphicsSurface, IOpenGLGraphicsSurface, IMetalGraphicsSurface
{
private readonly SDL2DesktopWindow window;
@@ -22,21 +22,32 @@ namespace osu.Framework.Platform.SDL2
public IntPtr WindowHandle => window.WindowHandle;
public IntPtr DisplayHandle => window.DisplayHandle;
public GraphicsBackend BackendType { get; }
public GraphicsSurfaceType Type { get; }
public SDL2WindowGraphics(SDL2DesktopWindow window, GraphicsBackend backend)
public SDL2GraphicsSurface(SDL2DesktopWindow window, GraphicsSurfaceType surfaceType)
{
this.window = window;
Type = surfaceType;
BackendType = backend;
switch (surfaceType)
{
case GraphicsSurfaceType.OpenGL:
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_STENCIL_SIZE, 8);
break;
if (backend == GraphicsBackend.OpenGL)
SDL.SDL_GL_SetAttribute(SDL.SDL_GLattr.SDL_GL_STENCIL_SIZE, 8);
case GraphicsSurfaceType.Vulkan:
case GraphicsSurfaceType.Metal:
case GraphicsSurfaceType.Direct3D11:
break;
default:
throw new ArgumentException($"Unexpected graphics surface: {Type}.", nameof(surfaceType));
}
}
public void Initialise()
{
if (BackendType == GraphicsBackend.OpenGL)
if (Type == GraphicsSurfaceType.OpenGL)
initialiseOpenGL();
}
@@ -44,27 +55,25 @@ namespace osu.Framework.Platform.SDL2
{
int width, height;
switch (BackendType)
switch (Type)
{
case GraphicsBackend.OpenGL:
case GraphicsSurfaceType.OpenGL:
default:
SDL.SDL_GL_GetDrawableSize(window.SDLWindowHandle, out width, out height);
break;
case GraphicsBackend.Vulkan:
case GraphicsSurfaceType.Vulkan:
SDL.SDL_Vulkan_GetDrawableSize(window.SDLWindowHandle, out width, out height);
break;
case GraphicsBackend.Metal:
case GraphicsSurfaceType.Metal:
SDL.SDL_Metal_GetDrawableSize(window.SDLWindowHandle, out width, out height);
break;
case GraphicsBackend.Direct3D11:
case GraphicsSurfaceType.Direct3D11:
// todo: SDL has no "drawable size" method for D3D11, return window size for now.
SDL.SDL_GetWindowSize(window.SDLWindowHandle, out width, out height);
break;
default:
throw new InvalidOperationException($"Unexpected graphics backend: {BackendType}.");
}
return new Size(width, height);
@@ -140,27 +149,27 @@ namespace osu.Framework.Platform.SDL2
return ret;
}
bool IOpenGLWindowGraphics.VerticalSync
bool IOpenGLGraphicsSurface.VerticalSync
{
get => SDL.SDL_GL_GetSwapInterval() != 0;
set => SDL.SDL_GL_SetSwapInterval(value ? 1 : 0);
}
IntPtr IOpenGLWindowGraphics.WindowContext => context;
IntPtr IOpenGLWindowGraphics.CurrentContext => SDL.SDL_GL_GetCurrentContext();
IntPtr IOpenGLGraphicsSurface.WindowContext => context;
IntPtr IOpenGLGraphicsSurface.CurrentContext => SDL.SDL_GL_GetCurrentContext();
void IOpenGLWindowGraphics.SwapBuffers() => SDL.SDL_GL_SwapWindow(window.SDLWindowHandle);
void IOpenGLWindowGraphics.CreateContext() => SDL.SDL_GL_CreateContext(window.SDLWindowHandle);
void IOpenGLWindowGraphics.DeleteContext(IntPtr context) => SDL.SDL_GL_DeleteContext(context);
void IOpenGLWindowGraphics.MakeCurrent(IntPtr context) => SDL.SDL_GL_MakeCurrent(window.SDLWindowHandle, context);
void IOpenGLWindowGraphics.ClearCurrent() => SDL.SDL_GL_MakeCurrent(window.SDLWindowHandle, IntPtr.Zero);
IntPtr IOpenGLWindowGraphics.GetProcAddress(string symbol) => getProcAddress(symbol);
void IOpenGLGraphicsSurface.SwapBuffers() => SDL.SDL_GL_SwapWindow(window.SDLWindowHandle);
void IOpenGLGraphicsSurface.CreateContext() => SDL.SDL_GL_CreateContext(window.SDLWindowHandle);
void IOpenGLGraphicsSurface.DeleteContext(IntPtr context) => SDL.SDL_GL_DeleteContext(context);
void IOpenGLGraphicsSurface.MakeCurrent(IntPtr context) => SDL.SDL_GL_MakeCurrent(window.SDLWindowHandle, context);
void IOpenGLGraphicsSurface.ClearCurrent() => SDL.SDL_GL_MakeCurrent(window.SDLWindowHandle, IntPtr.Zero);
IntPtr IOpenGLGraphicsSurface.GetProcAddress(string symbol) => getProcAddress(symbol);
#endregion
#region Metal-specific implementation
IntPtr IMetalWindowGraphics.CreateMetalView() => SDL.SDL_Metal_CreateView(window.SDLWindowHandle);
IntPtr IMetalGraphicsSurface.CreateMetalView() => SDL.SDL_Metal_CreateView(window.SDLWindowHandle);
#endregion
}

View File

@@ -28,9 +28,8 @@ namespace osu.Framework.Platform
{
internal IntPtr SDLWindowHandle { get; private set; } = IntPtr.Zero;
private readonly SDL2WindowGraphics graphics;
IWindowGraphics IWindow.Graphics => graphics;
private readonly SDL2GraphicsSurface graphicsSurface;
IGraphicsSurface IWindow.GraphicsSurface => graphicsSurface;
/// <summary>
/// Returns true if window has been created.
@@ -160,7 +159,7 @@ namespace osu.Framework.Platform
[UsedImplicitly]
private SDL.SDL_EventFilter? eventFilterDelegate;
public SDL2DesktopWindow(GraphicsBackend backend)
public SDL2DesktopWindow(GraphicsSurfaceType surfaceType)
{
if (SDL.SDL_Init(SDL.SDL_INIT_VIDEO | SDL.SDL_INIT_GAMECONTROLLER) < 0)
{
@@ -176,8 +175,7 @@ namespace osu.Framework.Platform
Logger.Log($@"SDL {category.ReadableName()} log [{priority.ReadableName()}]: {message}");
}, IntPtr.Zero);
graphics = CreateGraphics(backend);
graphicsSurface = new SDL2GraphicsSurface(this, surfaceType);
SupportedWindowModes = new BindableList<WindowMode>(DefaultSupportedWindowModes);
CursorStateBindable.ValueChanged += evt =>
@@ -202,7 +200,7 @@ namespace osu.Framework.Platform
SDL.SDL_WindowFlags.SDL_WINDOW_HIDDEN; // shown after first swap to avoid white flash on startup (windows)
flags |= WindowState.ToFlags();
flags |= graphics.BackendType.ToFlags();
flags |= graphicsSurface.Type.ToFlags();
SDL.SDL_SetHint(SDL.SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4, "1");
SDL.SDL_SetHint(SDL.SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS, "1");
@@ -219,7 +217,7 @@ namespace osu.Framework.Platform
Exists = true;
graphics.Initialise();
graphicsSurface.Initialise();
initialiseWindowingAfterCreation();
}
@@ -446,8 +444,6 @@ namespace osu.Framework.Platform
#endregion
protected virtual SDL2WindowGraphics CreateGraphics(GraphicsBackend backend) => new SDL2WindowGraphics(this, backend);
public void SetIconFromStream(Stream stream)
{
using (var ms = new MemoryStream())

View File

@@ -24,11 +24,11 @@ namespace osu.Framework.Platform.Windows
this.host = host;
}
protected override void Initialise(IWindowGraphics graphics)
protected override void Initialise(IGraphicsSurface graphicsSurface)
{
base.Initialise(graphics);
base.Initialise(graphicsSurface);
WindowsWindow window = (WindowsWindow)host.Window;
WindowsWindow windowsWindow = (WindowsWindow)host.Window;
bool isIntel = GL.GetString(StringName.Vendor).Trim() == "Intel";
@@ -40,9 +40,9 @@ namespace osu.Framework.Platform.Windows
else
{
// For all other vendors, support depends on the system setup - e.g. NVIDIA Optimus doesn't support exclusive fullscreen with OpenGL.
window.IsActive.BindValueChanged(_ => detectFullscreenCapability(window));
window.WindowStateChanged += _ => detectFullscreenCapability(window);
detectFullscreenCapability(window);
windowsWindow.IsActive.BindValueChanged(_ => detectFullscreenCapability(windowsWindow));
windowsWindow.WindowStateChanged += _ => detectFullscreenCapability(windowsWindow);
detectFullscreenCapability(windowsWindow);
}
}

View File

@@ -80,7 +80,7 @@ namespace osu.Framework.Platform.Windows
timePeriod = new TimePeriod(1);
}
protected override IWindow CreateWindow(GraphicsBackend backend) => new WindowsWindow(backend);
protected override IWindow CreateWindow(GraphicsSurfaceType preferredSurface) => new WindowsWindow(preferredSurface);
public override IEnumerable<KeyBinding> PlatformKeyBindings => base.PlatformKeyBindings.Concat(new[]
{

View File

@@ -30,8 +30,8 @@ namespace osu.Framework.Platform.Windows
private const int wm_killfocus = 8;
public WindowsWindow(GraphicsBackend backend)
: base(backend)
public WindowsWindow(GraphicsSurfaceType surfaceType)
: base(surfaceType)
{
try
{