Optimize VMulti-based plugins

- Allocate to POH
- Directly manipulate buffer through pointer access
This commit is contained in:
X9VoiD 2021-06-17 02:07:50 +08:00
parent aba845f297
commit 744fe3f780
14 changed files with 168 additions and 138 deletions

View file

@ -1,3 +1,4 @@
using System.Numerics;
using OpenTabletDriver.Plugin.Platform.Display;
using OpenTabletDriver.Plugin.Platform.Pointer;
using VoiDPlugins.Library.VMulti;
@ -5,11 +6,22 @@ using VoiDPlugins.Library.VMulti.Device;
namespace VoiDPlugins.OutputMode
{
public class VMultiAbsolutePointer : BasePointer<AbsoluteInputReport>, IAbsolutePointer
public unsafe class VMultiAbsolutePointer : BasePointer<AbsoluteInputReport>, IAbsolutePointer
{
public VMultiAbsolutePointer(IVirtualScreen screen) : base(screen, 0x09, "VMultiAbs")
public VMultiAbsolutePointer(IVirtualScreen screen) : base(screen, "VMultiAbs")
{
ButtonHandler.SetReport(Report);
ButtonHandler.SetReport((VMultiReportHeader*)ReportPointer, ReportBuffer);
}
protected override AbsoluteInputReport CreateReport()
{
return new AbsoluteInputReport(0x09);
}
protected override void SetCoordinates(Vector2 pos)
{
ReportPointer->X = (ushort)pos.X;
ReportPointer->Y = (ushort)pos.Y;
}
}
}

View file

@ -1,3 +1,4 @@
using System.Numerics;
using OpenTabletDriver.Plugin.Platform.Display;
using OpenTabletDriver.Plugin.Platform.Pointer;
using VoiDPlugins.Library.VMulti;
@ -5,11 +6,28 @@ using VoiDPlugins.Library.VMulti.Device;
namespace VoiDPlugins.OutputMode
{
public class VMultiRelativePointer : BasePointer<RelativeInputReport>, IRelativePointer
public unsafe class VMultiRelativePointer : BasePointer<RelativeInputReport>, IRelativePointer
{
public VMultiRelativePointer(IVirtualScreen screen) : base(screen, 0x04, "VMultiRel")
public VMultiRelativePointer(IVirtualScreen screen) : base(screen, "VMultiRel")
{
ButtonHandler.SetReport(Report);
ButtonHandler.SetReport((VMultiReportHeader*)ReportPointer, ReportBuffer);
}
protected override RelativeInputReport CreateReport()
{
return new RelativeInputReport(0x04);
}
public override void SetPosition(Vector2 pos)
{
SetCoordinates(pos);
Device.Write(ReportBuffer);
}
protected override void SetCoordinates(Vector2 pos)
{
ReportPointer->X = (byte)pos.X;
ReportPointer->Y = (byte)pos.Y;
}
}
}

View file

@ -17,9 +17,10 @@ namespace VoiDPlugins.OutputMode
{ "Middle", 4 }
};
public static string[] ValidButtons { get; } = Bindings.Keys.ToArray();
[Property("Button"), PropertyValidated(nameof(ValidButtons))]
public string Button { get; set; }
public static string[] ValidButtons => Bindings.Keys.ToArray();
public void Press(IDeviceReport report)
{

View file

@ -1,3 +1,4 @@
using System.Numerics;
using OpenTabletDriver.Plugin.Platform.Display;
using OpenTabletDriver.Plugin.Platform.Pointer;
using VoiDPlugins.Library.VMulti;
@ -5,17 +6,28 @@ using VoiDPlugins.Library.VMulti.Device;
namespace VoiDPlugins.OutputMode
{
public class WinInkAbsolutePointer : BasePointer<DigitizerInputReport>, IVirtualTablet
public unsafe class WinInkAbsolutePointer : BasePointer<DigitizerInputReport>, IVirtualTablet
{
public WinInkAbsolutePointer(IVirtualScreen screen) : base(screen, 0x05, "WindowsInk")
public WinInkAbsolutePointer(IVirtualScreen screen) : base(screen, "WindowsInk")
{
WinInkButtonHandler.SetReport(Report);
WinInkButtonHandler.SetReport(ReportPointer, ReportBuffer);
WinInkButtonHandler.SetDevice(Device);
}
public void SetPressure(float percentage)
{
Report.Pressure = (ushort)(percentage * 8191);
ReportPointer->Pressure = (ushort)(percentage * 8191);
}
protected override DigitizerInputReport CreateReport()
{
return new DigitizerInputReport(0x05);
}
protected override void SetCoordinates(Vector2 pos)
{
ReportPointer->X = (ushort)pos.X;
ReportPointer->Y = (ushort)pos.Y;
}
}
}

View file

@ -6,14 +6,14 @@ using VoiDPlugins.Library.VMulti.Device;
namespace VoiDPlugins.OutputMode
{
public class WinInkRelativePointer : BasePointer<DigitizerInputReport>, IVirtualTablet
public unsafe class WinInkRelativePointer : BasePointer<DigitizerInputReport>, IVirtualTablet
{
private Vector2 maxPoint;
private Vector2 currentPoint;
public WinInkRelativePointer(IVirtualScreen screen) : base(screen, 0x05, "WindowsInk")
public WinInkRelativePointer(IVirtualScreen screen) : base(screen, "WindowsInk")
{
WinInkButtonHandler.SetReport(Report);
WinInkButtonHandler.SetReport(ReportPointer, ReportBuffer);
WinInkButtonHandler.SetDevice(Device);
maxPoint = new Vector2(VirtualScreen.Width, VirtualScreen.Height);
currentPoint = maxPoint / 2;
@ -21,7 +21,7 @@ namespace VoiDPlugins.OutputMode
public void SetPressure(float percentage)
{
Report.Pressure = (ushort)(percentage * 8191);
ReportPointer->Pressure = (ushort)(percentage * 8191);
}
public override void Translate(Vector2 delta)
@ -29,5 +29,16 @@ namespace VoiDPlugins.OutputMode
currentPoint = Vector2.Clamp(currentPoint + delta, Vector2.Zero, maxPoint);
base.SetPosition(currentPoint);
}
protected override DigitizerInputReport CreateReport()
{
return new DigitizerInputReport(0x05);
}
protected override void SetCoordinates(Vector2 pos)
{
ReportPointer->X = (ushort)pos.X;
ReportPointer->Y = (ushort)pos.Y;
}
}
}

View file

@ -8,7 +8,7 @@ using VoiDPlugins.Library.VMulti.Device;
namespace VoiDPlugins.OutputMode
{
[PluginName("Windows Ink")]
public class WinInkButtonHandler : ButtonHandler, IBinding
public unsafe class WinInkButtonHandler : ButtonHandler, IBinding
{
public static string[] ValidButtons { get; } = new string[]
{
@ -32,7 +32,6 @@ namespace VoiDPlugins.OutputMode
private bool EraserState;
private static HidStream Device;
private static new DigitizerInputReport Report;
public void Press(IDeviceReport report)
{
@ -95,35 +94,35 @@ namespace VoiDPlugins.OutputMode
private void EraserStateTransition()
{
var buttons = Report.Buttons;
var pressure = Report.Pressure;
var Report = (DigitizerInputReport*)ReportPointer;
var buttons = Report->Header.Buttons;
var pressure = Report->Pressure;
// Send In-Range but no tips
DisableBit((int)ButtonBits.Press);
DisableBit((int)ButtonBits.Eraser);
Report.Pressure = 0;
Device.Write(Report.ToBytes());
Report->Pressure = 0;
Device.Write(ReportBuffer);
// Send Out-Of-Range
Report.Buttons = 0;
Device.Write(Report.ToBytes());
Report->Header.Buttons = 0;
Device.Write(ReportBuffer);
// Send In-Range but no tips
EnableBit((int)ButtonBits.InRange);
if (EraserState)
EnableBit((int)ButtonBits.Invert);
Device.Write(Report.ToBytes());
Device.Write(ReportBuffer);
// Send Proper Report
Report.Buttons = buttons;
Report.Pressure = pressure;
Report->Header.Buttons = buttons;
Report->Pressure = pressure;
}
public static void SetReport(DigitizerInputReport Report)
public static void SetReport(DigitizerInputReport* report, byte[] reportBuffer)
{
ButtonHandler.SetReport(Report);
WinInkButtonHandler.Report = Report;
ButtonHandler.SetReport((VMultiReportHeader*)report, reportBuffer);
EnableBit((int)ButtonBits.InRange);
}

View file

@ -1,29 +1,31 @@
using System;
using System.Numerics;
using System.Runtime.CompilerServices;
using HidSharp;
using OpenTabletDriver.Plugin.Attributes;
using OpenTabletDriver.Plugin.DependencyInjection;
using OpenTabletDriver.Plugin.Platform.Display;
using OpenTabletDriver.Plugin.Platform.Pointer;
using VoiDPlugins.Library.VMulti.Device;
namespace VoiDPlugins.Library.VMulti
{
[PluginIgnore]
public abstract class BasePointer<T> : IAbsolutePointer, IRelativePointer where T : Report, new()
public abstract unsafe class BasePointer<T> : IAbsolutePointer, IRelativePointer where T : unmanaged
{
public T Report;
protected readonly byte[] ReportBuffer;
protected readonly T* ReportPointer;
protected readonly HidStream Device;
protected IVirtualScreen VirtualScreen;
private Vector2 ScreenToVMulti;
private Vector2 error;
public BasePointer(IVirtualScreen screen, byte ReportID, string Name)
public BasePointer(IVirtualScreen screen, string Name)
{
Report = new T
{
ReportID = ReportID
};
ReportBuffer = GC.AllocateArray<byte>(Unsafe.SizeOf<T>(), pinned: true);
ReportPointer = (T*)Unsafe.AsPointer(ref ReportBuffer[0]);
T report = CreateReport();
*ReportPointer = report;
VirtualScreen = screen;
Device = VMultiDevice.Retrieve(Name);
@ -36,10 +38,13 @@ namespace VoiDPlugins.Library.VMulti
return pos / ScreenToVMulti;
}
protected abstract T CreateReport();
protected abstract void SetCoordinates(Vector2 pos);
public virtual void SetPosition(Vector2 pos)
{
Report.SetCoordinates(Convert(pos));
Device.Write(Report.ToBytes());
SetCoordinates(Convert(pos));
Device.Write(ReportBuffer);
}
public virtual void Translate(Vector2 delta)
@ -47,8 +52,8 @@ namespace VoiDPlugins.Library.VMulti
delta += error;
error = new Vector2(delta.X % 1, delta.Y % 1);
Report.SetCoordinates(delta);
Device.Write(Report.ToBytes());
SetCoordinates(delta);
Device.Write(ReportBuffer);
}
}
}

View file

@ -4,23 +4,25 @@ using VoiDPlugins.Library.VMulti.Device;
namespace VoiDPlugins.Library.VMulti
{
[PluginIgnore]
public class ButtonHandler
public unsafe class ButtonHandler
{
protected static Report Report;
protected static byte[] ReportBuffer;
protected static VMultiReportHeader* ReportPointer;
public static void SetReport(Report report)
public static void SetReport(VMultiReportHeader* report, byte[] reportBuffer)
{
Report = report;
ReportBuffer = reportBuffer;
ReportPointer = report;
}
public static void EnableBit(int bit)
{
Report.Buttons = (byte)(Report.Buttons | bit);
ReportPointer->Buttons = (byte)(ReportPointer->Buttons | bit);
}
public static void DisableBit(int bit)
{
Report.Buttons = (byte)(Report.Buttons & ~bit);
ReportPointer->Buttons = (byte)(ReportPointer->Buttons & ~bit);
}
}
}

View file

@ -1,35 +1,22 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace VoiDPlugins.Library.VMulti.Device
{
public class AbsoluteInputReport : Report
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct AbsoluteInputReport
{
public AbsoluteInputReport(byte reportID)
{
Header = new VMultiReportHeader(Unsafe.SizeOf<AbsoluteInputReport>(), reportID);
X = 0;
Y = 0;
Pressure = 0;
}
public VMultiReportHeader Header;
public ushort X; // X position of the mouse from 0 to 32767
public ushort Y; // Y position of the mouse from 0 to 32767
public ushort Pressure; // Pressure of the mouse? from 0 to 8191
public override byte[] ToBytes()
{
var bytes = new byte[Size];
bytes[0] = VMultiID;
bytes[1] = ReportLength;
bytes[2] = ReportID;
bytes[3] = Buttons;
bytes[4] = (byte)(X & 0xFF);
bytes[5] = (byte)((X & 0xFF00) >> 8);
bytes[6] = (byte)(Y & 0xFF);
bytes[7] = (byte)((Y & 0xFF00) >> 8);
bytes[8] = (byte)(Pressure & 0xFF);
bytes[9] = (byte)((Pressure & 0xFF00) >> 8);
return bytes;
}
public override void SetCoordinates(Vector2 coordinates)
{
X = (ushort)coordinates.X;
Y = (ushort)coordinates.Y;
}
public override byte Size => 10;
}
}

View file

@ -1,38 +1,26 @@
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace VoiDPlugins.Library.VMulti.Device
{
public sealed class DigitizerInputReport : Report
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct DigitizerInputReport
{
public DigitizerInputReport(byte reportID)
{
Header = new VMultiReportHeader(Unsafe.SizeOf<DigitizerInputReport>(), reportID);
X = 0;
Y = 0;
Pressure = 0;
XTilt = 0;
YTilt = 0;
}
public VMultiReportHeader Header;
public ushort X; // X position of the pen from 0 to 32767
public ushort Y; // Y position of the pen from 0 to 32767
public ushort Pressure; // Pressure level from 0 to 8191
public byte XTilt; // X tilt of the pen from -127 to 127
public byte YTilt; // Y tilt of the pen from -127 to 127
private byte[] bytes = new byte[12];
public override byte[] ToBytes()
{
Unsafe.WriteUnaligned(ref bytes[0], VMultiID);
Unsafe.WriteUnaligned(ref bytes[1], ReportLength);
Unsafe.WriteUnaligned(ref bytes[2], ReportID);
Unsafe.WriteUnaligned(ref bytes[3], Buttons);
Unsafe.WriteUnaligned(ref bytes[4], X);
Unsafe.WriteUnaligned(ref bytes[6], Y);
Unsafe.WriteUnaligned(ref bytes[8], Pressure);
Unsafe.WriteUnaligned(ref bytes[10], XTilt);
Unsafe.WriteUnaligned(ref bytes[11], YTilt);
return bytes;
}
public override void SetCoordinates(Vector2 coordinates)
{
X = (ushort)coordinates.X;
Y = (ushort)coordinates.Y;
}
public override byte Size => 12;
}
}

View file

@ -1,32 +1,20 @@
using System.Numerics;
using System.Runtime.CompilerServices;
namespace VoiDPlugins.Library.VMulti.Device
{
public class RelativeInputReport : Report
public struct RelativeInputReport
{
public RelativeInputReport(byte reportID)
{
Header = new VMultiReportHeader(Unsafe.SizeOf<RelativeInputReport>(), reportID);
X = 0;
Y = 0;
WheelPos = 0;
}
public VMultiReportHeader Header;
public byte X; // X position of the mouse from -127 to 127
public byte Y; // Y position of the mouse from -127 to 127
public byte WheelPos; // Wheel position of the mouse from -127 to 127
public override byte[] ToBytes()
{
var bytes = new byte[Size];
bytes[0] = VMultiID;
bytes[1] = ReportLength;
bytes[2] = ReportID;
bytes[3] = Buttons;
bytes[4] = X;
bytes[5] = Y;
bytes[6] = WheelPos;
return bytes;
}
public override void SetCoordinates(Vector2 coordinates)
{
X = (byte)coordinates.X;
Y = (byte)coordinates.Y;
}
public override byte Size => 7;
}
}

View file

@ -1,15 +0,0 @@
using System.Numerics;
namespace VoiDPlugins.Library.VMulti.Device
{
public abstract class Report
{
public byte VMultiID = 0x40;
public byte ReportID;
public byte Buttons;
public byte ReportLength => (byte)(Size - 1);
public abstract byte Size { get; }
public abstract byte[] ToBytes();
public abstract void SetCoordinates(Vector2 coordinates);
}
}

View file

@ -0,0 +1,21 @@
using System.Runtime.InteropServices;
namespace VoiDPlugins.Library.VMulti.Device
{
[StructLayout(LayoutKind.Sequential, Pack = 1)]
public struct VMultiReportHeader
{
public VMultiReportHeader(int size, byte reportID)
{
VMultiID = 0x40;
ReportLength = (byte)(size - 1);
ReportID = reportID;
Buttons = 0;
}
public byte VMultiID;
public byte ReportLength;
public byte ReportID;
public byte Buttons;
}
}

View file

@ -2,6 +2,7 @@
<PropertyGroup>
<TargetFrameworks>net5</TargetFrameworks>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Release'">