Skip to content

Commit

Permalink
Merge pull request #25 from tannergooding/graphics
Browse files Browse the repository at this point in the history
Update the graphics stack to support rendering a clear screen.
  • Loading branch information
tannergooding committed Sep 9, 2019
2 parents 62ac660 + d91a639 commit a4665ad
Show file tree
Hide file tree
Showing 23 changed files with 2,312 additions and 53 deletions.
65 changes: 65 additions & 0 deletions samples/TerraFX/Graphics/HelloWindow.cs
@@ -0,0 +1,65 @@
// Copyright © Tanner Gooding and Contributors. Licensed under the MIT License (MIT). See License.md in the repository root for more information.

using System;
using System.Linq;
using System.Reflection;
using TerraFX.ApplicationModel;
using TerraFX.Graphics;
using TerraFX.UI;
using TerraFX.Utilities;

namespace TerraFX.Samples.Graphics
{
public sealed class HelloWindow : Sample
{
private IGraphicsContext? _graphicsContext;
private IWindow? _window;
private TimeSpan _elapsedTime;

public HelloWindow(string name, params Assembly[] compositionAssemblies)
: base(name, compositionAssemblies)
{
}

public override void OnIdle(object? sender, ApplicationIdleEventArgs eventArgs)
{
ExceptionUtilities.ThrowIfNull(sender, nameof(sender));

var application = (Application)sender;

if (_window is null)
{
var windowProvider = application.GetService<IWindowProvider>();
_window = windowProvider.CreateWindow();

_window.Show();
}
else if (_window.IsVisible)
{
if (_graphicsContext is null)
{
var graphicsProvider = application.GetService<IGraphicsProvider>();
var graphicsAdapter = graphicsProvider.GraphicsAdapters.First();

var graphicsSurface = _window.CreateGraphicsSurface(bufferCount: 2);
_graphicsContext = graphicsAdapter.CreateGraphicsContext(graphicsSurface);
}
else
{
_elapsedTime += eventArgs.Delta;

if (_elapsedTime.TotalSeconds >= 2.5)
{
application.RequestExit();
}

var backgroundColor = new ColorRgba(red: 100.0f / 255.0f, green: 149.0f / 255.0f, blue: 237.0f / 255.0f, alpha: 1.0f);
_graphicsContext.BeginFrame(backgroundColor);

_graphicsContext.EndFrame();
_graphicsContext.PresentFrame();
}
}
}
}
}
24 changes: 23 additions & 1 deletion samples/TerraFX/Program.cs
Expand Up @@ -4,6 +4,7 @@
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using TerraFX.ApplicationModel;
using TerraFX.Samples.Graphics;

Expand All @@ -17,6 +18,8 @@ public static unsafe class Program
private static readonly Sample[] s_samples = {
new EnumerateGraphicsAdapters("D3D12.EnumerateGraphicsAdapter", s_d3d12Provider),
new EnumerateGraphicsAdapters("Vulkan.EnumerateGraphicsAdapter", s_vulkanProvider),
new HelloWindow("D3D12.HelloWindow", s_d3d12Provider),
new HelloWindow("Vulkan.HelloWindow", s_vulkanProvider),
};

public static void Main(string[] args)
Expand Down Expand Up @@ -49,7 +52,26 @@ private static void PrintHelp()

foreach (var sample in s_samples)
{
Console.WriteLine($" {sample.Name}");
bool isSupported;
var compositionAssemblies = sample.CompositionAssemblies;

if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
{
isSupported = true;
}
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux))
{
isSupported = !compositionAssemblies.Contains(s_d3d12Provider);
}
else
{
isSupported = false;
}

if (isSupported)
{
Console.WriteLine($" {sample.Name}");
}
}
}

Expand Down
4 changes: 2 additions & 2 deletions samples/TerraFX/Properties/launchSettings.json
@@ -1,8 +1,8 @@
{
"profiles": {
"TerraFX.Samples.DirectX": {
"TerraFX.Samples": {
"commandName": "Project",
"commandLineArgs": "all"
}
}
}
}
26 changes: 26 additions & 0 deletions sources/Graphics/GraphicsSurfaceKind.cs
@@ -0,0 +1,26 @@
// Copyright © Tanner Gooding and Contributors. Licensed under the MIT License (MIT). See License.md in the repository root for more information.

namespace TerraFX.Graphics
{
/// <summary>Defines a graphics surface kind.</summary>
public enum GraphicsSurfaceKind
{
/// <summary>Defines an unknown graphics surface kind that may require specialized handling.</summary>
Unknown,

/// <summary>Defines an Android based graphics surface.</summary>
Android,

/// <summary>Defines a Wayland based graphics surface.</summary>
Wayland,

/// <summary>Defines a Win32 based graphics surface.</summary>
Win32,

/// <summary>Defines an XCB based graphics surface.</summary>
Xcb,

/// <summary>Defines an Xlib based graphics surface.</summary>
Xlib,
}
}
9 changes: 6 additions & 3 deletions sources/Graphics/IGraphicsAdapter.cs
Expand Up @@ -16,10 +16,13 @@ public interface IGraphicsAdapter
/// <summary>Gets the <see cref="IGraphicsProvider" /> for the instance.</summary>
IGraphicsProvider GraphicsProvider { get; }

/// <summary>Gets the underlying handle for the instance.</summary>
IntPtr Handle { get; }

/// <summary>Gets the PCI ID of the vendor.</summary>
uint VendorId { get; }

/// <summary>Creates a new <see cref="IGraphicsContext" />.</summary>
/// <param name="graphicsSurface">The <see cref="IGraphicsSurface" /> on which the graphics context can draw.</param>
/// <returns>A new <see cref="IGraphicsContext" /> which utilizes the current instance and which can draw on <paramref name="graphicsSurface" />.</returns>
/// <exception cref="ArgumentNullException"><paramref name="graphicsSurface" /> is <c>null</c>.</exception>
IGraphicsContext CreateGraphicsContext(IGraphicsSurface graphicsSurface);
}
}
24 changes: 24 additions & 0 deletions sources/Graphics/IGraphicsContext.cs
@@ -0,0 +1,24 @@
// Copyright © Tanner Gooding and Contributors. Licensed under the MIT License (MIT). See License.md in the repository root for more information.

namespace TerraFX.Graphics
{
/// <summary>Represents a graphics context, which can be used for rendering images.</summary>
public interface IGraphicsContext
{
/// <summary>Gets the <see cref="IGraphicsAdapter" /> for the instance.</summary>
IGraphicsAdapter GraphicsAdapter { get; }

/// <summary>Gets the <see cref="IGraphicsSurface" /> for the instance.</summary>
IGraphicsSurface GraphicsSurface { get; }

/// <summary>Begins a new frame for rendering.</summary>
/// <param name="backgroundColor">A color to which the background should be cleared.</param>
void BeginFrame(ColorRgba backgroundColor);

/// <summary>Ends the frame currently be rendered.</summary>
void EndFrame();

/// <summary>Presents the last frame rendered.</summary>
void PresentFrame();
}
}
3 changes: 0 additions & 3 deletions sources/Graphics/IGraphicsProvider.cs
Expand Up @@ -10,8 +10,5 @@ public interface IGraphicsProvider
{
/// <summary>Gets the <see cref="IGraphicsAdapter" /> instances currently available.</summary>
IEnumerable<IGraphicsAdapter> GraphicsAdapters { get; }

/// <summary>Gets the underlying handle for the instance.</summary>
IntPtr Handle { get; }
}
}
32 changes: 32 additions & 0 deletions sources/Graphics/IGraphicsSurface.cs
@@ -0,0 +1,32 @@
// Copyright © Tanner Gooding and Contributors. Licensed under the MIT License (MIT). See License.md in the repository root for more information.

using System;
using TerraFX.Numerics;

namespace TerraFX.Graphics
{
/// <summary>Represents a graphics surface.</summary>
public interface IGraphicsSurface
{
/// <summary>Gets the number of buffers for the instance.</summary>
int BufferCount { get; }

/// <summary>Gets the height of the instance.</summary>
float Height => Size.Y;

/// <summary>Gets the kind of surface represented by the instance.</summary>
GraphicsSurfaceKind Kind { get; }

/// <summary>Gets the size of the instance.</summary>
Vector2 Size { get; }

/// <summary>Gets the width of the instance.</summary>
float Width => Size.X;

/// <summary>Gets the window provider handle for the instance.</summary>
IntPtr WindowProviderHandle { get; }

/// <summary>Gets the window handle for the instance.</summary>
IntPtr WindowHandle { get; }
}
}
37 changes: 24 additions & 13 deletions sources/Provider/D3D12/Graphics/GraphicsAdapter.cs
Expand Up @@ -2,11 +2,9 @@

using System;
using System.Runtime.InteropServices;

using TerraFX.Graphics;
using TerraFX.Interop;
using TerraFX.Utilities;

using static TerraFX.Interop.Windows;
using static TerraFX.Utilities.ExceptionUtilities;
using static TerraFX.Utilities.State;
Expand All @@ -18,6 +16,7 @@ public sealed unsafe class GraphicsAdapter : IDisposable, IGraphicsAdapter
{
private readonly GraphicsProvider _graphicsProvider;
private readonly IDXGIAdapter1* _adapter;

private readonly string _deviceName;
private readonly uint _vendorId;
private readonly uint _deviceId;
Expand Down Expand Up @@ -45,30 +44,42 @@ internal GraphicsAdapter(GraphicsProvider graphicsProvider, IDXGIAdapter1* adapt
/// <summary>Gets the name of the device.</summary>
public string DeviceName => _deviceName;

/// <summary>Gets the <see cref="IDXGIAdapter1" /> for the instance.</summary>
/// <exception cref="ObjectDisposedException">The instance has already been disposed.</exception>
public IDXGIAdapter1* Adapter
{
get
{
_state.ThrowIfDisposedOrDisposing();
return _adapter;
}
}

/// <summary>Gets the <see cref="IGraphicsProvider" /> for the instance.</summary>
public IGraphicsProvider GraphicsProvider => _graphicsProvider;

/// <summary>Gets the underlying handle for the instance.</summary>
public IntPtr Handle => (IntPtr)_adapter;

/// <summary>Gets the PCI ID of the vendor.</summary>
public uint VendorId => _vendorId;

/// <summary>Creates a new <see cref="IGraphicsContext" />.</summary>
/// <param name="graphicsSurface">The <see cref="IGraphicsSurface" /> on which the graphics context can draw.</param>
/// <returns>A new <see cref="IGraphicsContext" /> which utilizes the current instance and which can draw on <paramref name="graphicsSurface" />.</returns>
/// <exception cref="ArgumentNullException"><paramref name="graphicsSurface" /> is <c>null</c>.</exception>
/// <exception cref="ObjectDisposedException">The instance has already been disposed.</exception>
public IGraphicsContext CreateGraphicsContext(IGraphicsSurface graphicsSurface)
{
_state.ThrowIfDisposedOrDisposing();
ThrowIfNull(graphicsSurface, nameof(graphicsSurface));
return new GraphicsContext(this, graphicsSurface);
}

/// <summary>Disposes of any unmanaged resources tracked by the instance.</summary>
public void Dispose()
{
Dispose(isDisposing: true);
GC.SuppressFinalize(this);
}

private static void ThrowIfDisposed(int state)
{
if (state >= Disposing) // (_state == Disposing) || (_state == Disposed)
{
ThrowObjectDisposedException(nameof(GraphicsProvider));
}
}

private void Dispose(bool isDisposing)
{
var priorState = _state.BeginDispose();
Expand Down

0 comments on commit a4665ad

Please sign in to comment.