mirror of
https://github.com/Artemis-RGB/Artemis
synced 2025-12-12 21:38:38 +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 TimerUpdateTrigger _updateTrigger;
|
||||
private readonly object _renderLock = new();
|
||||
private readonly List<ArtemisDevice> _devices = new();
|
||||
private readonly SKTextureBrush _textureBrush = new(null) {CalculationMode = RenderMode.Absolute};
|
||||
private readonly object _renderLock = new();
|
||||
|
||||
private ListLedGroup? _surfaceLedGroup;
|
||||
private SKTexture? _texture;
|
||||
@ -36,13 +36,142 @@ internal sealed class SurfaceManager : IDisposable
|
||||
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)
|
||||
{
|
||||
lock (_renderLock)
|
||||
{
|
||||
SKTexture? texture = _texture;
|
||||
if (texture == null || texture.IsInvalid)
|
||||
{
|
||||
texture = CreateTexture();
|
||||
UpdateLedGroup();
|
||||
}
|
||||
|
||||
// Prepare a 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)
|
||||
{
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateGraphicsContext(IManagedGraphicsContext? graphicsContext)
|
||||
{
|
||||
lock (_renderLock)
|
||||
{
|
||||
GraphicsContext = graphicsContext;
|
||||
_texture?.Dispose();
|
||||
_texture = null;
|
||||
}
|
||||
_texture?.Invalidate();
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user