mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-13 05:48:35 +00:00
Change surface manager SKTexture handling
This commit is contained in:
parent
543b62a715
commit
3e88aa37ff
@ -14,9 +14,9 @@ internal sealed class SurfaceManager : IDisposable
|
|||||||
{
|
{
|
||||||
private readonly IRenderer _renderer;
|
private readonly IRenderer _renderer;
|
||||||
private readonly TimerUpdateTrigger _updateTrigger;
|
private readonly TimerUpdateTrigger _updateTrigger;
|
||||||
private readonly object _renderLock = new();
|
|
||||||
private readonly List<ArtemisDevice> _devices = new();
|
private readonly List<ArtemisDevice> _devices = new();
|
||||||
private readonly SKTextureBrush _textureBrush = new(null) {CalculationMode = RenderMode.Absolute};
|
private readonly SKTextureBrush _textureBrush = new(null) {CalculationMode = RenderMode.Absolute};
|
||||||
|
private readonly object _renderLock = new();
|
||||||
|
|
||||||
private ListLedGroup? _surfaceLedGroup;
|
private ListLedGroup? _surfaceLedGroup;
|
||||||
private SKTexture? _texture;
|
private SKTexture? _texture;
|
||||||
@ -36,13 +36,142 @@ internal sealed class SurfaceManager : IDisposable
|
|||||||
SetPaused(true);
|
SetPaused(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public IManagedGraphicsContext? GraphicsContext { get; private set; }
|
||||||
|
public int TargetFrameRate { get; private set; }
|
||||||
|
public float RenderScale { get; private set; }
|
||||||
|
public RGBSurface Surface { get; }
|
||||||
|
|
||||||
|
public bool IsPaused { get; private set; }
|
||||||
|
|
||||||
|
public void AddDevices(IEnumerable<ArtemisDevice> devices)
|
||||||
|
{
|
||||||
|
lock (_renderLock)
|
||||||
|
{
|
||||||
|
foreach (ArtemisDevice artemisDevice in devices)
|
||||||
|
{
|
||||||
|
if (_devices.Contains(artemisDevice))
|
||||||
|
continue;
|
||||||
|
_devices.Add(artemisDevice);
|
||||||
|
Surface.Attach(artemisDevice.RgbDevice);
|
||||||
|
artemisDevice.DeviceUpdated += ArtemisDeviceOnDeviceUpdated;
|
||||||
|
}
|
||||||
|
|
||||||
|
_texture?.Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void RemoveDevices(IEnumerable<ArtemisDevice> devices)
|
||||||
|
{
|
||||||
|
lock (_renderLock)
|
||||||
|
{
|
||||||
|
foreach (ArtemisDevice artemisDevice in devices)
|
||||||
|
{
|
||||||
|
artemisDevice.DeviceUpdated -= ArtemisDeviceOnDeviceUpdated;
|
||||||
|
Surface.Detach(artemisDevice.RgbDevice);
|
||||||
|
_devices.Remove(artemisDevice);
|
||||||
|
}
|
||||||
|
|
||||||
|
_texture?.Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool SetPaused(bool paused)
|
||||||
|
{
|
||||||
|
if (IsPaused == paused)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (paused)
|
||||||
|
_updateTrigger.Stop();
|
||||||
|
else
|
||||||
|
_updateTrigger.Start();
|
||||||
|
|
||||||
|
IsPaused = paused;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateTargetFrameRate(int targetFrameRate)
|
||||||
|
{
|
||||||
|
TargetFrameRate = targetFrameRate;
|
||||||
|
_updateTrigger.UpdateFrequency = 1.0 / TargetFrameRate;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateRenderScale(float renderScale)
|
||||||
|
{
|
||||||
|
lock (_renderLock)
|
||||||
|
{
|
||||||
|
RenderScale = renderScale;
|
||||||
|
_texture?.Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void UpdateGraphicsContext(IManagedGraphicsContext? graphicsContext)
|
||||||
|
{
|
||||||
|
lock (_renderLock)
|
||||||
|
{
|
||||||
|
GraphicsContext = graphicsContext;
|
||||||
|
_texture?.Invalidate();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void Dispose()
|
||||||
|
{
|
||||||
|
SetPaused(true);
|
||||||
|
Surface.UnregisterUpdateTrigger(_updateTrigger);
|
||||||
|
lock (_renderLock)
|
||||||
|
{
|
||||||
|
_updateTrigger.Dispose();
|
||||||
|
_texture?.Dispose();
|
||||||
|
Surface.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateLedGroup()
|
||||||
|
{
|
||||||
|
List<Led> leds = _devices.SelectMany(d => d.Leds).Select(l => l.RgbLed).ToList();
|
||||||
|
|
||||||
|
if (_surfaceLedGroup == null)
|
||||||
|
{
|
||||||
|
_surfaceLedGroup = new ListLedGroup(Surface, leds) {Brush = _textureBrush};
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clean up the old background
|
||||||
|
_surfaceLedGroup.Detach();
|
||||||
|
|
||||||
|
// Apply the application wide brush and decorator
|
||||||
|
_surfaceLedGroup = new ListLedGroup(Surface, leds) {Brush = _textureBrush};
|
||||||
|
}
|
||||||
|
|
||||||
|
private SKTexture CreateTexture()
|
||||||
|
{
|
||||||
|
float evenWidth = Surface.Boundary.Size.Width;
|
||||||
|
if (evenWidth % 2 != 0)
|
||||||
|
evenWidth++;
|
||||||
|
float evenHeight = Surface.Boundary.Size.Height;
|
||||||
|
if (evenHeight % 2 != 0)
|
||||||
|
evenHeight++;
|
||||||
|
|
||||||
|
int width = Math.Max(1, MathF.Min(evenWidth * RenderScale, 4096).RoundToInt());
|
||||||
|
int height = Math.Max(1, MathF.Min(evenHeight * RenderScale, 4096).RoundToInt());
|
||||||
|
|
||||||
|
_texture?.Dispose();
|
||||||
|
_texture = new SKTexture(GraphicsContext, width, height, RenderScale, _devices);
|
||||||
|
_textureBrush.Texture = _texture;
|
||||||
|
|
||||||
|
return _texture;
|
||||||
|
}
|
||||||
|
|
||||||
private void SurfaceOnUpdating(UpdatingEventArgs args)
|
private void SurfaceOnUpdating(UpdatingEventArgs args)
|
||||||
{
|
{
|
||||||
lock (_renderLock)
|
lock (_renderLock)
|
||||||
{
|
{
|
||||||
SKTexture? texture = _texture;
|
SKTexture? texture = _texture;
|
||||||
if (texture == null || texture.IsInvalid)
|
if (texture == null || texture.IsInvalid)
|
||||||
|
{
|
||||||
texture = CreateTexture();
|
texture = CreateTexture();
|
||||||
|
UpdateLedGroup();
|
||||||
|
}
|
||||||
|
|
||||||
// Prepare a canvas
|
// Prepare a canvas
|
||||||
SKCanvas canvas = texture.Surface.Canvas;
|
SKCanvas canvas = texture.Surface.Canvas;
|
||||||
@ -77,146 +206,8 @@ internal sealed class SurfaceManager : IDisposable
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public IManagedGraphicsContext? GraphicsContext { get; private set; }
|
|
||||||
public int TargetFrameRate { get; private set; }
|
|
||||||
public float RenderScale { get; private set; }
|
|
||||||
public RGBSurface Surface { get; }
|
|
||||||
|
|
||||||
public bool IsPaused { get; private set; }
|
|
||||||
|
|
||||||
public void AddDevices(IEnumerable<ArtemisDevice> devices)
|
|
||||||
{
|
|
||||||
lock (_renderLock)
|
|
||||||
{
|
|
||||||
foreach (ArtemisDevice artemisDevice in devices)
|
|
||||||
{
|
|
||||||
if (_devices.Contains(artemisDevice))
|
|
||||||
continue;
|
|
||||||
_devices.Add(artemisDevice);
|
|
||||||
Surface.Attach(artemisDevice.RgbDevice);
|
|
||||||
artemisDevice.DeviceUpdated += ArtemisDeviceOnDeviceUpdated;
|
|
||||||
}
|
|
||||||
|
|
||||||
Update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void RemoveDevices(IEnumerable<ArtemisDevice> devices)
|
|
||||||
{
|
|
||||||
lock (_renderLock)
|
|
||||||
{
|
|
||||||
foreach (ArtemisDevice artemisDevice in devices)
|
|
||||||
{
|
|
||||||
artemisDevice.DeviceUpdated -= ArtemisDeviceOnDeviceUpdated;
|
|
||||||
Surface.Detach(artemisDevice.RgbDevice);
|
|
||||||
_devices.Remove(artemisDevice);
|
|
||||||
}
|
|
||||||
|
|
||||||
Update();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool SetPaused(bool paused)
|
|
||||||
{
|
|
||||||
if (IsPaused == paused)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
if (paused)
|
|
||||||
_updateTrigger.Stop();
|
|
||||||
else
|
|
||||||
_updateTrigger.Start();
|
|
||||||
|
|
||||||
IsPaused = paused;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void Update()
|
|
||||||
{
|
|
||||||
lock (_renderLock)
|
|
||||||
{
|
|
||||||
UpdateLedGroup();
|
|
||||||
CreateTexture();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateLedGroup()
|
|
||||||
{
|
|
||||||
List<Led> leds = _devices.SelectMany(d => d.Leds).Select(l => l.RgbLed).ToList();
|
|
||||||
|
|
||||||
if (_surfaceLedGroup == null)
|
|
||||||
{
|
|
||||||
_surfaceLedGroup = new ListLedGroup(Surface, leds) {Brush = _textureBrush};
|
|
||||||
LedsChanged?.Invoke(this, EventArgs.Empty);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Clean up the old background
|
|
||||||
_surfaceLedGroup.Detach();
|
|
||||||
|
|
||||||
// Apply the application wide brush and decorator
|
|
||||||
_surfaceLedGroup = new ListLedGroup(Surface, leds) {Brush = _textureBrush};
|
|
||||||
LedsChanged?.Invoke(this, EventArgs.Empty);
|
|
||||||
}
|
|
||||||
|
|
||||||
private SKTexture CreateTexture()
|
|
||||||
{
|
|
||||||
float evenWidth = Surface.Boundary.Size.Width;
|
|
||||||
if (evenWidth % 2 != 0)
|
|
||||||
evenWidth++;
|
|
||||||
float evenHeight = Surface.Boundary.Size.Height;
|
|
||||||
if (evenHeight % 2 != 0)
|
|
||||||
evenHeight++;
|
|
||||||
|
|
||||||
int width = Math.Max(1, MathF.Min(evenWidth * RenderScale, 4096).RoundToInt());
|
|
||||||
int height = Math.Max(1, MathF.Min(evenHeight * RenderScale, 4096).RoundToInt());
|
|
||||||
|
|
||||||
_texture?.Dispose();
|
|
||||||
_texture = new SKTexture(GraphicsContext, width, height, RenderScale, _devices);
|
|
||||||
_textureBrush.Texture = _texture;
|
|
||||||
|
|
||||||
return _texture;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void ArtemisDeviceOnDeviceUpdated(object? sender, EventArgs e)
|
private void ArtemisDeviceOnDeviceUpdated(object? sender, EventArgs e)
|
||||||
{
|
{
|
||||||
Update();
|
|
||||||
}
|
|
||||||
|
|
||||||
public event EventHandler? LedsChanged;
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public void Dispose()
|
|
||||||
{
|
|
||||||
SetPaused(true);
|
|
||||||
|
|
||||||
Surface.UnregisterUpdateTrigger(_updateTrigger);
|
|
||||||
_updateTrigger.Dispose();
|
|
||||||
_texture?.Dispose();
|
|
||||||
Surface.Dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateTargetFrameRate(int targetFrameRate)
|
|
||||||
{
|
|
||||||
TargetFrameRate = targetFrameRate;
|
|
||||||
_updateTrigger.UpdateFrequency = 1.0 / TargetFrameRate;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateRenderScale(float renderScale)
|
|
||||||
{
|
|
||||||
lock (_renderLock)
|
|
||||||
{
|
|
||||||
RenderScale = renderScale;
|
|
||||||
_texture?.Invalidate();
|
_texture?.Invalidate();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public void UpdateGraphicsContext(IManagedGraphicsContext? graphicsContext)
|
|
||||||
{
|
|
||||||
lock (_renderLock)
|
|
||||||
{
|
|
||||||
GraphicsContext = graphicsContext;
|
|
||||||
_texture?.Dispose();
|
|
||||||
_texture = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user