mirror of
https://github.com/Artemis-RGB/Artemis
synced 2026-11-11 19:36:28 +00:00
Core - Added the ability to change graphics context at runtime
Settings - Added setting for switching between software-based and Vulkan-based rendering
This commit is contained in:
1 parent
d7e302fb23
commit
f888fb5697
19 files changed
+281
-270
No files matched your search
@@ -2,9 +2,10 @@
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using Artemis.Core.JsonConverters;
|
||||
using Artemis.Core.Services;
|
||||
using Artemis.Core.Services.Core;
|
||||
using Artemis.Core.SkiaSharp;
|
||||
using Newtonsoft.Json;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
@@ -118,20 +119,10 @@ namespace Artemis.Core
|
||||
typeof(decimal)
|
||||
};
|
||||
|
||||
private static GRContext? _skiaGraphicsContext;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the graphics context to be used for rendering by SkiaSharp
|
||||
/// Gets the graphics context to be used for rendering by SkiaSharp. Can be set via
|
||||
/// <see cref="IRgbService.UpdateGraphicsContext" />.
|
||||
/// </summary>
|
||||
public static GRContext? SkiaGraphicsContext
|
||||
{
|
||||
get => _skiaGraphicsContext;
|
||||
set
|
||||
{
|
||||
if (_skiaGraphicsContext != null)
|
||||
throw new ArtemisCoreException($"{nameof(SkiaGraphicsContext)} can only be set once.");
|
||||
_skiaGraphicsContext = value;
|
||||
}
|
||||
}
|
||||
public static IManagedGraphicsContext? ManagedGraphicsContext { get; internal set; }
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
using System;
|
||||
|
||||
namespace Artemis.Core
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents SkiaSharp graphics-context related errors
|
||||
/// </summary>
|
||||
public class ArtemisGraphicsContextException : Exception
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public ArtemisGraphicsContextException()
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ArtemisGraphicsContextException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public ArtemisGraphicsContextException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,11 +36,11 @@ namespace Artemis.Core
|
||||
int width = (int) pathBounds.Width;
|
||||
int height = (int) pathBounds.Height;
|
||||
|
||||
SKImageInfo imageInfo = new SKImageInfo(width, height);
|
||||
if (Constants.SkiaGraphicsContext == null)
|
||||
SKImageInfo imageInfo = new(width, height);
|
||||
if (Constants.ManagedGraphicsContext?.GraphicsContext == null)
|
||||
Surface = SKSurface.Create(imageInfo);
|
||||
else
|
||||
Surface = SKSurface.Create(Constants.SkiaGraphicsContext, true, imageInfo);
|
||||
Surface = SKSurface.Create(Constants.ManagedGraphicsContext.GraphicsContext, true, imageInfo);
|
||||
|
||||
Path = new SKPath(path);
|
||||
Path.Transform(SKMatrix.CreateTranslation(pathBounds.Left * -1, pathBounds.Top * -1));
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.InteropServices;
|
||||
using Artemis.Core.SkiaSharp;
|
||||
using RGB.NET.Core;
|
||||
using RGB.NET.Presets.Textures.Sampler;
|
||||
using SkiaSharp;
|
||||
@@ -17,14 +16,14 @@ namespace Artemis.Core
|
||||
|
||||
#region Constructors
|
||||
|
||||
internal SKTexture(int width, int height, float renderScale)
|
||||
internal SKTexture(IManagedGraphicsContext? managedGraphicsContext, int width, int height, float renderScale)
|
||||
: base(width, height, 4, new AverageByteSampler())
|
||||
{
|
||||
ImageInfo = new SKImageInfo(width, height);
|
||||
if (Constants.SkiaGraphicsContext == null)
|
||||
if (managedGraphicsContext == null)
|
||||
Surface = SKSurface.Create(ImageInfo);
|
||||
else
|
||||
Surface = SKSurface.Create(Constants.SkiaGraphicsContext, true, ImageInfo);
|
||||
Surface = SKSurface.Create(managedGraphicsContext.GraphicsContext, true, ImageInfo);
|
||||
RenderScale = renderScale;
|
||||
}
|
||||
|
||||
|
||||
@@ -59,6 +59,7 @@ namespace Artemis.Core.Services
|
||||
|
||||
UpdatePluginCache();
|
||||
|
||||
_rgbService.IsRenderPaused = true;
|
||||
_rgbService.Surface.Updating += SurfaceOnUpdating;
|
||||
_loggingLevel.SettingChanged += (sender, args) => ApplyLoggingLevel();
|
||||
|
||||
@@ -242,6 +243,7 @@ namespace Artemis.Core.Services
|
||||
IsElevated
|
||||
);
|
||||
|
||||
_rgbService.IsRenderPaused = false;
|
||||
OnInitialized();
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Artemis.Core.SkiaSharp;
|
||||
using RGB.NET.Core;
|
||||
|
||||
namespace Artemis.Core.Services
|
||||
@@ -50,6 +51,16 @@ namespace Artemis.Core.Services
|
||||
/// </summary>
|
||||
void CloseRender();
|
||||
|
||||
/// <summary>
|
||||
/// Updates the graphics context to the provided <paramref name="managedGraphicsContext"></paramref>.
|
||||
/// <para>Note: The old graphics context will be used until the next frame starts rendering and is disposed afterwards.</para>
|
||||
/// </summary>
|
||||
/// <param name="managedGraphicsContext">
|
||||
/// The new managed graphics context. If <see langword="null" />, software rendering
|
||||
/// is used.
|
||||
/// </param>
|
||||
void UpdateGraphicsContext(IManagedGraphicsContext? managedGraphicsContext);
|
||||
|
||||
/// <summary>
|
||||
/// Adds the given device provider to the <see cref="Surface" />
|
||||
/// </summary>
|
||||
|
||||
@@ -4,6 +4,7 @@ using System.Collections.ObjectModel;
|
||||
using System.Linq;
|
||||
using Artemis.Core.DeviceProviders;
|
||||
using Artemis.Core.Services.Models;
|
||||
using Artemis.Core.SkiaSharp;
|
||||
using Artemis.Storage.Entities.Surface;
|
||||
using Artemis.Storage.Repositories.Interfaces;
|
||||
using RGB.NET.Core;
|
||||
@@ -51,7 +52,7 @@ namespace Artemis.Core.Services
|
||||
UpdateTrigger = new TimerUpdateTrigger {UpdateFrequency = 1.0 / _targetFrameRateSetting.Value};
|
||||
Surface.RegisterUpdateTrigger(UpdateTrigger);
|
||||
}
|
||||
|
||||
|
||||
public TimerUpdateTrigger UpdateTrigger { get; }
|
||||
|
||||
protected virtual void OnDeviceRemoved(DeviceEventArgs e)
|
||||
@@ -118,9 +119,7 @@ namespace Artemis.Core.Services
|
||||
public IReadOnlyCollection<ArtemisDevice> Devices => _devices.AsReadOnly();
|
||||
public IReadOnlyDictionary<Led, ArtemisLed> LedMap => new ReadOnlyDictionary<Led, ArtemisLed>(_ledMap);
|
||||
|
||||
/// <inheritdoc />
|
||||
public RGBSurface Surface { get; set; }
|
||||
|
||||
public bool IsRenderPaused { get; set; }
|
||||
public bool RenderOpen { get; private set; }
|
||||
|
||||
@@ -215,6 +214,8 @@ namespace Artemis.Core.Services
|
||||
|
||||
#region Rendering
|
||||
|
||||
private IManagedGraphicsContext? _newGraphicsContext;
|
||||
|
||||
public SKTexture OpenRender()
|
||||
{
|
||||
if (RenderOpen)
|
||||
@@ -231,7 +232,7 @@ namespace Artemis.Core.Services
|
||||
{
|
||||
if (!RenderOpen)
|
||||
throw new ArtemisCoreException("Render pipeline is already closed");
|
||||
|
||||
|
||||
RenderOpen = false;
|
||||
_texture?.CopyPixelData();
|
||||
}
|
||||
@@ -241,15 +242,38 @@ namespace Artemis.Core.Services
|
||||
if (RenderOpen)
|
||||
throw new ArtemisCoreException("Cannot update the texture while rendering");
|
||||
|
||||
SKTexture? oldTexture = _texture;
|
||||
IManagedGraphicsContext? graphicsContext = Constants.ManagedGraphicsContext = _newGraphicsContext;
|
||||
if (!ReferenceEquals(graphicsContext, _newGraphicsContext))
|
||||
graphicsContext = _newGraphicsContext;
|
||||
|
||||
if (graphicsContext != null)
|
||||
_logger.Debug("Creating SKTexture with graphics context {graphicsContext}", graphicsContext.GetType().Name);
|
||||
else
|
||||
_logger.Debug("Creating SKTexture with software-based graphics context");
|
||||
|
||||
float renderScale = (float) _renderScaleSetting.Value;
|
||||
int width = Math.Max(1, MathF.Min(Surface.Boundary.Size.Width * renderScale, 4096).RoundToInt());
|
||||
int height = Math.Max(1, MathF.Min(Surface.Boundary.Size.Height * renderScale, 4096).RoundToInt());
|
||||
_texture = new SKTexture(width, height, renderScale);
|
||||
_texture?.Dispose();
|
||||
_texture = new SKTexture(graphicsContext, width, height, renderScale);
|
||||
_textureBrush.Texture = _texture;
|
||||
|
||||
oldTexture?.Dispose();
|
||||
|
||||
if (!ReferenceEquals(_newGraphicsContext, Constants.ManagedGraphicsContext = _newGraphicsContext))
|
||||
{
|
||||
Constants.ManagedGraphicsContext?.Dispose();
|
||||
Constants.ManagedGraphicsContext = _newGraphicsContext;
|
||||
_newGraphicsContext = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateGraphicsContext(IManagedGraphicsContext? managedGraphicsContext)
|
||||
{
|
||||
if (ReferenceEquals(managedGraphicsContext, Constants.ManagedGraphicsContext))
|
||||
return;
|
||||
|
||||
_newGraphicsContext = managedGraphicsContext;
|
||||
_texture?.Invalidate();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
using System;
|
||||
using SkiaSharp;
|
||||
|
||||
namespace Artemis.Core.SkiaSharp
|
||||
{
|
||||
/// <summary>
|
||||
/// Represents a managed wrapper around a SkiaSharp context
|
||||
/// </summary>
|
||||
public interface IManagedGraphicsContext : IDisposable
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the graphics context created by this wrapper
|
||||
/// </summary>
|
||||
GRContext GraphicsContext { get; }
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user