Răsfoiți Sursa

PixiEngine early wip

flabbet 1 an în urmă
părinte
comite
725c63c24b
29 a modificat fișierele cu 406 adăugiri și 568 ștergeri
  1. 1 1
      src/Directory.Build.props
  2. 0 22
      src/DrawingApi.Benchmarks/DrawingApi.Benchmarks.csproj
  3. 0 7
      src/DrawingApi.Benchmarks/GraphicsContext.cs
  4. 0 109
      src/DrawingApi.Benchmarks/Program.cs
  5. 0 61
      src/DrawingApi.Benchmarks/SurfaceBenchmarks.cs
  6. 0 21
      src/DrawingApi.MinimalGpuSetup/DrawingApi.MinimalGpuSetup.csproj
  7. 0 65
      src/PixiEditor.AvaloniaHeadless/AppWindow.cs
  8. 0 22
      src/PixiEditor.AvaloniaHeadless/PixiEditor.AvaloniaHeadless.csproj
  9. 0 117
      src/PixiEditor.AvaloniaHeadless/Program.cs
  10. 0 2
      src/PixiEditor.AvaloniaUI/PixiEditor.AvaloniaUI.csproj
  11. 1 0
      src/PixiEditor.DrawingApi.Core/Bridge/IDrawingBackend.cs
  12. 0 1
      src/PixiEditor.DrawingApi.Core/Bridge/Operations/ISurfaceImplementation.cs
  13. 0 5
      src/PixiEditor.DrawingApi.Core/Surface/DrawingSurface.cs
  14. 10 0
      src/PixiEditor.DrawingApi.Skia/Exceptions/GrContextAlreadyInitializedException.cs
  15. 10 9
      src/PixiEditor.DrawingApi.Skia/Implementations/SkiaSurfaceImplementation.cs
  16. 1 0
      src/PixiEditor.DrawingApi.Skia/PixiEditor.DrawingApi.Skia.csproj
  17. 26 9
      src/PixiEditor.DrawingApi.Skia/SkiaDrawingBackend.cs
  18. 15 0
      src/PixiEditor.Engine.AvaloniaPlatform/PixiEditor.Engine.AvaloniaPlatform.csproj
  19. 11 0
      src/PixiEditor.Engine.AvaloniaPlatform/PixiEnginePlatform.cs
  20. 71 0
      src/PixiEditor.Engine.AvaloniaPlatform/PixiEngineTopLevelImpl.cs
  21. 8 0
      src/PixiEditor.Engine/Exceptions/PixiEngineException.cs
  22. 17 0
      src/PixiEditor.Engine/Helpers/VectorExtensions.cs
  23. 26 0
      src/PixiEditor.Engine/PixiEditor.Engine.csproj
  24. 20 0
      src/PixiEditor.Engine/PixiEngine.cs
  25. 40 0
      src/PixiEditor.Engine/SkiaPixiEngine.cs
  26. 29 13
      src/PixiEditor.Engine/Window.cs
  27. 92 90
      src/PixiEditor.sln
  28. 14 0
      src/PixiEngineSampleApp/PixiEngineSampleApp.csproj
  29. 14 14
      src/PixiEngineSampleApp/Program.cs

+ 1 - 1
src/Directory.Build.props

@@ -1,7 +1,7 @@
 <Project>
     <PropertyGroup>
         <CodeAnalysisRuleSet>../Custom.ruleset</CodeAnalysisRuleSet>
-		    <AvaloniaVersion>[11.0.11]</AvaloniaVersion>
+		    <AvaloniaVersion>11.0.11</AvaloniaVersion>
     </PropertyGroup>
     <ItemGroup>
         <PackageReference Include="StyleCop.Analyzers" Version="1.1.118" />

+ 0 - 22
src/DrawingApi.Benchmarks/DrawingApi.Benchmarks.csproj

@@ -1,22 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-    <PropertyGroup>
-        <OutputType>Exe</OutputType>
-        <TargetFramework>net8.0</TargetFramework>
-        <ImplicitUsings>enable</ImplicitUsings>
-        <Nullable>enable</Nullable>
-      <Optimize>true</Optimize>
-    </PropertyGroup>
-
-    <ItemGroup>
-      <ProjectReference Include="..\PixiEditor.DrawingApi.Core\PixiEditor.DrawingApi.Core.csproj" />
-      <ProjectReference Include="..\PixiEditor.DrawingApi.Skia\PixiEditor.DrawingApi.Skia.csproj" />
-    </ItemGroup>
-
-    <ItemGroup>
-      <PackageReference Include="BenchmarkDotNet" Version="0.13.12" />
-      <PackageReference Include="Silk.NET.OpenGL" Version="2.21.0" />
-      <PackageReference Include="Silk.NET.Windowing" Version="2.21.0" />
-    </ItemGroup>
-
-</Project>

+ 0 - 7
src/DrawingApi.Benchmarks/GraphicsContext.cs

@@ -1,7 +0,0 @@
-namespace DrawingApi.Benchmarks;
-
-public enum GraphicsContext
-{
-    CPU,
-    OpenGL
-}

+ 0 - 109
src/DrawingApi.Benchmarks/Program.cs

@@ -1,109 +0,0 @@
-using System.Diagnostics;
-using BenchmarkDotNet.Configs;
-using BenchmarkDotNet.Running;
-using DrawingApi.Benchmarks;
-using PixiEditor.DrawingApi.Core.Bridge;
-using PixiEditor.DrawingApi.Core.ColorsImpl;
-using PixiEditor.DrawingApi.Core.Surface;
-using PixiEditor.DrawingApi.Core.Surface.ImageData;
-using PixiEditor.DrawingApi.Core.Surface.PaintImpl;
-using PixiEditor.DrawingApi.Skia;
-using PixiEditor.Numerics;
-using Silk.NET.OpenGL;
-using Silk.NET.Windowing;
-using SkiaSharp;
-
-public static class Program
-{
-    public static IWindow window;
-    public static void Main()
-    {
-        WindowOptions options = WindowOptions.Default with { IsVisible = false };
-
-        window = Window.Create(options);
-
-        GRContext GrContext;
-        GL gl;
-
-        window.Load += () =>
-        {
-            gl = GL.GetApi(window);
-            GrContext = GRContext.CreateGl();
-
-            DrawingBackendApi.SetupBackend(new SkiaDrawingBackend(GrContext));
-
-            Stopwatch stopwatch = new Stopwatch();
-            
-            SurfaceBenchmarks cpuBenchmarks = new SurfaceBenchmarks();
-            cpuBenchmarks.GraphicsContext = GraphicsContext.CPU;
-            
-            stopwatch.Start();
-            var cpuResult = cpuBenchmarks.MergeTwoSurfaces();
-            stopwatch.Stop();
-            
-            Console.WriteLine($"Merge CPU: {stopwatch.Elapsed.TotalMicroseconds} micro seconds");
-            
-            SurfaceBenchmarks glBenchmarks = new SurfaceBenchmarks();
-            glBenchmarks.GraphicsContext = GraphicsContext.OpenGL;
-            
-            stopwatch.Restart();
-            var result = glBenchmarks.MergeTwoSurfaces();
-            stopwatch.Stop();
-            
-            Console.WriteLine($"Merge OpenGL: {stopwatch.Elapsed.TotalMicroseconds} micro seconds");
-            
-            var toSnapshotCpu = cpuBenchmarks.CreateDrawingSurface(new VecI(10000, 10000));
-            toSnapshotCpu.Canvas.DrawRect(0, 0, 10000, 10000, new Paint() { Color = new Color(255, 0, 0) });
-
-            stopwatch.Restart();
-            var cpuSnapshot = cpuBenchmarks.Snapshot(toSnapshotCpu);
-            stopwatch.Stop();
-            
-            Console.WriteLine($"CPU Snapshot: {stopwatch.Elapsed.TotalMicroseconds} micro seconds");
-            
-            var toSnapshotGl = glBenchmarks.CreateDrawingSurface(new VecI(10000, 10000));
-            toSnapshotGl.Canvas.DrawRect(0, 0, 10000, 10000, new Paint() { Color = new Color(255, 0, 0) });
-            
-            stopwatch.Restart();
-            var glSnapshot = glBenchmarks.Snapshot(toSnapshotGl);
-            stopwatch.Stop();
-            
-            Console.WriteLine($"OpenGL Snapshot: {stopwatch.Elapsed.TotalMicroseconds} micro seconds");
-            
-            stopwatch.Restart();
-            var cpuPixmap = cpuSnapshot.PeekPixels();
-            stopwatch.Stop();
-            
-            Console.WriteLine($"CPU Peek Pixels: {stopwatch.Elapsed.TotalMicroseconds} micro seconds");
-            
-            stopwatch.Restart();
-            var glPixmap = glSnapshot.PeekPixels();
-            stopwatch.Stop();
-            
-            Console.WriteLine($"OpenGL Peek Pixels: {stopwatch.Elapsed.TotalMicroseconds} micro seconds");
-            
-            stopwatch.Restart();
-            cpuBenchmarks.PickColor(cpuPixmap, 5000, 5000);
-            stopwatch.Stop();
-            
-            Console.WriteLine($"CPU Pick Color: {stopwatch.Elapsed.TotalMicroseconds} micro seconds");
-            
-            stopwatch.Restart();
-            glBenchmarks.PickColor(glPixmap, 5000, 5000);
-            stopwatch.Stop();
-            
-            Console.WriteLine($"OpenGL Pick Color: {stopwatch.Elapsed.TotalMicroseconds} micro seconds");
-            
-            window.Close();
-        };
-
-        window.Run();
-    }
-    
-    public static void SaveToDesktop(DrawingSurface surface, string fileName)
-    {
-        using Image img = surface.Snapshot();
-        using var data = img.Encode();
-        System.IO.File.WriteAllBytes(System.IO.Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Desktop), fileName), data.AsSpan().ToArray());
-    }
-}

+ 0 - 61
src/DrawingApi.Benchmarks/SurfaceBenchmarks.cs

@@ -1,61 +0,0 @@
-using System.Diagnostics;
-using BenchmarkDotNet.Attributes;
-using PixiEditor.DrawingApi.Core.Bridge;
-using PixiEditor.DrawingApi.Core.ColorsImpl;
-using PixiEditor.DrawingApi.Core.Surface;
-using PixiEditor.DrawingApi.Core.Surface.ImageData;
-using PixiEditor.DrawingApi.Core.Surface.PaintImpl;
-using PixiEditor.DrawingApi.Skia;
-using PixiEditor.Numerics;
-using Silk.NET.OpenGL;
-using Silk.NET.Windowing;
-using SkiaSharp;
-
-namespace DrawingApi.Benchmarks;
-
-public class SurfaceBenchmarks
-{
-    public GraphicsContext GraphicsContext { get; set; }
-
-    public DrawingSurface CreateDrawingSurface(VecI size)
-    {
-        ImageInfo info = new(size.X, size.Y);
-        if (GraphicsContext == GraphicsContext.CPU)
-        {
-            return DrawingSurface.Create(info);
-        }
-
-        if (GraphicsContext == GraphicsContext.OpenGL)
-        {
-            return DrawingSurface.Create(info, true);
-        }
-
-        return null;
-    }
-    
-    public DrawingSurface MergeTwoSurfaces()
-    {
-        DrawingSurface surface1 = CreateDrawingSurface(new VecI(10000, 10000));
-        DrawingSurface surface2 = CreateDrawingSurface(new VecI(10000, 10000));
-        surface2.Canvas.DrawRect(0, 0, 10000, 10000, new Paint() { Color = new Color(255, 0, 0) });
-
-        surface1.Canvas.DrawSurface(surface2, 0, 0, new Paint());
-        
-        return surface1;
-    }
-
-    public Image Snapshot(DrawingSurface surface)
-    {
-        return surface.Snapshot();
-    }
-    
-    public void PeekPixels(Image image)
-    { 
-        image.PeekPixels();
-    }
-
-    public void PickColor(Pixmap pixmap, int x, int y)
-    {
-        pixmap.GetColor(x, y);
-    }
-}

+ 0 - 21
src/DrawingApi.MinimalGpuSetup/DrawingApi.MinimalGpuSetup.csproj

@@ -1,21 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-    <PropertyGroup>
-        <OutputType>Exe</OutputType>
-        <TargetFramework>net8.0</TargetFramework>
-        <ImplicitUsings>enable</ImplicitUsings>
-        <Nullable>enable</Nullable>
-    </PropertyGroup>
-
-    <ItemGroup>
-      <PackageReference Include="Avalonia" Version="11.0.11" />
-      <PackageReference Include="Silk.NET.OpenGL" Version="2.21.0" />
-      <PackageReference Include="Silk.NET.Windowing" Version="2.21.0" />
-    </ItemGroup>
-
-    <ItemGroup>
-      <ProjectReference Include="..\PixiEditor.DrawingApi.Core\PixiEditor.DrawingApi.Core.csproj" />
-      <ProjectReference Include="..\PixiEditor.DrawingApi.Skia\PixiEditor.DrawingApi.Skia.csproj" />
-    </ItemGroup>
-
-</Project>

+ 0 - 65
src/PixiEditor.AvaloniaHeadless/AppWindow.cs

@@ -1,65 +0,0 @@
-using Silk.NET.GLFW;
-using Silk.NET.Maths;
-using Silk.NET.OpenGL;
-using Silk.NET.Windowing;
-using SkiaSharp;
-
-namespace PixiEditor.AvaloniaHeadless;
-
-public class AppWindow
-{
-    private GL gl;
-    private IWindow _window;
-    private GRContext _grContext;
-
-    private SKSurface frontBufferSurface;
-    
-    public event Action<SKSurface, double> Render;
-    public event Action<GRContext> Init;
-    
-    public Func<Delegate, string[], object> Dispatcher => _window.Invoke;
-
-    public AppWindow()
-    {
-        WindowOptions options = WindowOptions.Default with
-        {
-            Title = "OpenGL Window", Size = new Vector2D<int>(1200, 600)
-        };
-
-        _window = Window.Create(options);
-
-        _window.Load += () =>
-        {
-            gl = GL.GetApi(_window);
-            frontBufferSurface = SKSurface.Create(new SKImageInfo(1200, 600));
-            
-            _window.GLContext.MakeCurrent();
-
-            InitSkiaSurface();
-            
-            Init?.Invoke(_grContext);
-        };
-        
-        _window.Render += OnRender;
-    }
-
-    public void Run()
-    {
-        _window.Run();
-    }
-    
-    private void OnRender(double deltaTime)
-    {
-        frontBufferSurface.Canvas.Clear(SKColors.White);
-        Render?.Invoke(frontBufferSurface, deltaTime); 
-        frontBufferSurface.Canvas.Flush();
-    }
-
-    private void InitSkiaSurface()
-    {
-        _grContext = GRContext.CreateGl(GRGlInterface.Create(Glfw.GetApi().GetProcAddress));
-        var frameBuffer = new GRGlFramebufferInfo(0, SKColorType.RgbaF16.ToGlSizedFormat());
-        GRBackendRenderTarget target = new GRBackendRenderTarget(_window.Size.X, _window.Size.Y, 4, 0, frameBuffer);
-        frontBufferSurface = SKSurface.Create(_grContext, target, GRSurfaceOrigin.BottomLeft, SKColorType.RgbaF16);
-    }
-}

+ 0 - 22
src/PixiEditor.AvaloniaHeadless/PixiEditor.AvaloniaHeadless.csproj

@@ -1,22 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-    <PropertyGroup>
-        <OutputType>Exe</OutputType>
-        <TargetFramework>net8.0</TargetFramework>
-        <ImplicitUsings>enable</ImplicitUsings>
-        <Nullable>enable</Nullable>
-    </PropertyGroup>
-
-    <ItemGroup>
-      <PackageReference Include="Avalonia" Version="11.0.11" />
-      <PackageReference Include="Avalonia.Headless" Version="11.0.11" />
-      <PackageReference Include="Silk.NET.OpenGL" Version="2.21.0" />
-      <PackageReference Include="Silk.NET.Windowing" Version="2.21.0" />
-      <PackageReference Include="SkiaSharp" Version="2.88.8" />
-    </ItemGroup>
-
-    <ItemGroup>
-      <ProjectReference Include="..\PixiEditor.AvaloniaUI\PixiEditor.AvaloniaUI.csproj" />
-    </ItemGroup>
-
-</Project>

+ 0 - 117
src/PixiEditor.AvaloniaHeadless/Program.cs

@@ -1,117 +0,0 @@
-using Avalonia;
-using Avalonia.Controls;
-using Avalonia.Headless;
-using Avalonia.Platform;
-using Avalonia.Threading;
-using PixiEditor.AvaloniaHeadless;
-using PixiEditor.AvaloniaUI;
-using PixiEditor.AvaloniaUI.Models.IO;
-using PixiEditor.DrawingApi.Core.Bridge;
-using PixiEditor.DrawingApi.Skia;
-using PixiEditor.Extensions.Runtime;
-using PixiEditor.OperatingSystem;
-using PixiEditor.Platform;
-using Silk.NET.GLFW;
-using SkiaSharp;
-using Window = Avalonia.Controls.Window;
-
-public static class Program
-{
-    public static void Main(string[] args)
-    {
-        AppWindow window = new AppWindow();
-        window.Init += (gr) =>
-        {
-            WindowOnInit(window.Dispatcher, gr, args);
-        };
-
-        window.Render += WindowOnRender;
-
-        window.Run();
-    }
-
-    private static void WindowOnRender(SKSurface arg1, double arg2)
-    {
-    }
-
-    private static void WindowOnInit(Func<Delegate, string[], object> dispatcher, GRContext grContext, string[] args)
-    
-    {
-        SkiaDrawingBackend skiaDrawingBackend = new SkiaDrawingBackend(grContext);
-        DrawingBackendApi.SetupBackend(skiaDrawingBackend);
-
-        SynchronizationContext.SetSynchronizationContext(new SynchronizationContext());
-        DrawingBackendApi.Current.Dispatcher = dispatcher;
-
-        var appBuilder = AppBuilder.Configure<App>()
-            .UseSkia()
-            .UseHeadless(new AvaloniaHeadlessPlatformOptions() { UseHeadlessDrawing = false });
-        
-
-        appBuilder.StartWithClassicDesktopLifetime(args);
-        
-        //appBuilder.Start(AppMain, args);
-    }
-
-    private static void AppMain(Application app, string[] args)
-    {
-        Type type = App.MainWindowType;
-        ExtensionLoader loader = InitApp();
-
-        var mainWindow = (Window)Activator.CreateInstance(type, loader);
-        
-        mainWindow.Show();
-    }
-
-    private static ExtensionLoader InitApp()
-    {
-        //LoadingWindow.ShowInNewThread();
-
-        InitPlatform();
-
-        ExtensionLoader extensionLoader = new ExtensionLoader(Paths.ExtensionPackagesPath, Paths.UserExtensionsPath);
-        //TODO: fetch from extension store
-        extensionLoader.AddOfficialExtension("pixieditor.supporterpack",
-            new OfficialExtensionData("supporter-pack.snk", AdditionalContentProduct.SupporterPack));
-        extensionLoader.LoadExtensions();
-
-        return extensionLoader;
-    }
-
-
-    private static void InitPlatform()
-    {
-        var platform = GetActivePlatform();
-        IPlatform.RegisterPlatform(platform);
-        platform.PerformHandshake();
-    }
-
-    private static IPlatform GetActivePlatform()
-    {
-#if STEAM
-            return new PixiEditor.Platform.Steam.SteamPlatform();
-#elif MSIX || MSIX_DEBUG
-            return new PixiEditor.Platform.MSStore.MicrosoftStorePlatform();
-#else
-        return new PixiEditor.Platform.Standalone.StandalonePlatform();
-#endif
-    }
-
-    private static void InitOperatingSystem()
-    {
-        IOperatingSystem.RegisterOS(GetActiveOperatingSystem());
-    }
-
-    private static IOperatingSystem GetActiveOperatingSystem()
-    {
-#if WINDOWS
-        return new PixiEditor.Windows.WindowsOperatingSystem();
-#elif LINUX
-            return new PixiEditor.Linux.LinuxOperatingSystem();
-#elif MACOS
-            return new PixiEditor.MacOs.MacOperatingSystem();
-#else
-            throw new PlatformNotSupportedException("This platform is not supported");
-#endif
-    }
-}

+ 0 - 2
src/PixiEditor.AvaloniaUI/PixiEditor.AvaloniaUI.csproj

@@ -19,8 +19,6 @@
     <ImplicitUsings>true</ImplicitUsings>
     <LangVersion>latest</LangVersion>
     <AllowUnsafeBlocks>True</AllowUnsafeBlocks>
-    <AvaloniaAccessUnstablePrivateApis>true</AvaloniaAccessUnstablePrivateApis>
-    <Avalonia_I_Want_To_Use_Private_Apis_In_Nuget_Package_And_Promise_To_Pin_The_Exact_Avalonia_Version_In_Package_Dependency>true</Avalonia_I_Want_To_Use_Private_Apis_In_Nuget_Package_And_Promise_To_Pin_The_Exact_Avalonia_Version_In_Package_Dependency>
   </PropertyGroup>
 
   <ItemGroup Condition="'$(RuntimeIdentifier)'=='win-x64'">

+ 1 - 0
src/PixiEditor.DrawingApi.Core/Bridge/IDrawingBackend.cs

@@ -19,5 +19,6 @@ namespace PixiEditor.DrawingApi.Core.Bridge
         public IBitmapImplementation BitmapImplementation { get; }
         public IColorFilterImplementation ColorFilterImplementation { get; set; }
         public IShaderImplementation ShaderImplementation { get; set; }
+        public bool IsGpuAccelerated { get; }
     }
 }

+ 0 - 1
src/PixiEditor.DrawingApi.Core/Bridge/Operations/ISurfaceImplementation.cs

@@ -15,7 +15,6 @@ public interface ISurfaceImplementation
     public DrawingSurface Create(ImageInfo imageInfo, IntPtr pixelBuffer);
     public DrawingSurface Create(Pixmap pixmap);
     public DrawingSurface Create(ImageInfo imageInfo);
-    public DrawingSurface Create(ImageInfo imageInfo, bool isGpuBacked);
     public void Dispose(DrawingSurface drawingSurface);
     public object GetNativeSurface(IntPtr objectPointer);
 }

+ 0 - 5
src/PixiEditor.DrawingApi.Core/Surface/DrawingSurface.cs

@@ -65,11 +65,6 @@ namespace PixiEditor.DrawingApi.Core.Surface
             return DrawingBackendApi.Current.SurfaceImplementation.Create(imageInfo, pixelBuffer);
         }
 
-        public static DrawingSurface Create(ImageInfo info, bool isGpuBacked)
-        {
-            return DrawingBackendApi.Current.SurfaceImplementation.Create(info, isGpuBacked);
-        }
-
         public override void Dispose()
         {
             Canvas.Changed -= OnCanvasChanged;

+ 10 - 0
src/PixiEditor.DrawingApi.Skia/Exceptions/GrContextAlreadyInitializedException.cs

@@ -0,0 +1,10 @@
+using System;
+
+namespace PixiEditor.DrawingApi.Skia.Exceptions;
+
+public class GrContextAlreadyInitializedException : Exception
+{
+    public GrContextAlreadyInitializedException() : base("GRContext is already initialized")
+    {
+    }
+}

+ 10 - 9
src/PixiEditor.DrawingApi.Skia/Implementations/SkiaSurfaceImplementation.cs

@@ -4,6 +4,7 @@ using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.DrawingApi.Core.Surface;
 using PixiEditor.DrawingApi.Core.Surface.ImageData;
 using PixiEditor.DrawingApi.Core.Surface.PaintImpl;
+using PixiEditor.Numerics;
 using SkiaSharp;
 
 namespace PixiEditor.DrawingApi.Skia.Implementations
@@ -13,14 +14,15 @@ namespace PixiEditor.DrawingApi.Skia.Implementations
         private readonly SkiaPixmapImplementation _pixmapImplementation;
         private readonly SkiaCanvasImplementation _canvasImplementation;
         private readonly SkiaPaintImplementation _paintImplementation;
-        private GRContext grContext;
+
+        public GRContext GraphicsContext { get; set; }
 
         public SkiaSurfaceImplementation(GRContext context, SkiaPixmapImplementation pixmapImplementation, SkiaCanvasImplementation canvasImplementation, SkiaPaintImplementation paintImplementation)
         {
             _pixmapImplementation = pixmapImplementation;
             _canvasImplementation = canvasImplementation;
             _paintImplementation = paintImplementation;
-            grContext = context;
+            GraphicsContext = context;
         }
         
         public Pixmap PeekPixels(DrawingSurface drawingSurface)
@@ -51,7 +53,7 @@ namespace PixiEditor.DrawingApi.Skia.Implementations
         
         public DrawingSurface Create(ImageInfo imageInfo, IntPtr pixels, int rowBytes)
         {
-            SKSurface skSurface = SKSurface.Create(grContext, false, imageInfo.ToSkImageInfo());
+            SKSurface skSurface = CreateSkiaSurface(imageInfo.Size);
             
             var canvas = skSurface.Canvas;
             canvas.DrawImage(SKImage.FromPixelCopy(imageInfo.ToSkImageInfo(), pixels, rowBytes), new SKPoint(0, 0));
@@ -61,7 +63,7 @@ namespace PixiEditor.DrawingApi.Skia.Implementations
 
         public DrawingSurface Create(ImageInfo imageInfo, IntPtr pixelBuffer)
         {
-            SKSurface skSurface = SKSurface.Create(grContext, false, imageInfo.ToSkImageInfo());
+            SKSurface skSurface = CreateSkiaSurface(imageInfo.Size);
             
             var canvas = skSurface.Canvas;
             canvas.DrawImage(SKImage.FromPixelCopy(imageInfo.ToSkImageInfo(), pixelBuffer), new SKPoint(0, 0));
@@ -73,7 +75,7 @@ namespace PixiEditor.DrawingApi.Skia.Implementations
         {
             SKPixmap skPixmap = _pixmapImplementation[pixmap.ObjectPointer];
             SKImageInfo info = skPixmap.Info;
-            SKSurface skSurface = SKSurface.Create(grContext, false, info);
+            SKSurface skSurface = CreateSkiaSurface(new VecI(info.Width, info.Height));
             
             var canvas = skSurface.Canvas;
             canvas.DrawImage(SKImage.FromPixels(skPixmap), new SKPoint(0, 0));
@@ -83,14 +85,13 @@ namespace PixiEditor.DrawingApi.Skia.Implementations
 
         public DrawingSurface Create(ImageInfo imageInfo)
         {
-            SKSurface skSurface = SKSurface.Create(imageInfo.ToSkImageInfo());
+            SKSurface skSurface = CreateSkiaSurface(imageInfo.Size);
             return CreateDrawingSurface(skSurface);
         }
 
-        public DrawingSurface Create(ImageInfo imageInfo, bool isGpuBacked)
+        private SKSurface CreateSkiaSurface(VecI size)
         {
-            SKSurface skSurface = SKSurface.Create(grContext, isGpuBacked, imageInfo.ToSkImageInfo());
-            return CreateDrawingSurface(skSurface);
+            return SKSurface.Create(GraphicsContext, false, new SKImageInfo(size.X, size.Y));
         }
 
         public void Dispose(DrawingSurface drawingSurface)

+ 1 - 0
src/PixiEditor.DrawingApi.Skia/PixiEditor.DrawingApi.Skia.csproj

@@ -4,6 +4,7 @@
         <TargetFramework>netstandard2.1</TargetFramework>
         <Nullable>enable</Nullable>
         <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
+        <LangVersion>default</LangVersion>
     </PropertyGroup>
 
     <ItemGroup>

+ 26 - 9
src/PixiEditor.DrawingApi.Skia/SkiaDrawingBackend.cs

@@ -1,6 +1,7 @@
 using PixiEditor.DrawingApi.Core.Bridge;
 using PixiEditor.DrawingApi.Core.Bridge.NativeObjectsImpl;
 using PixiEditor.DrawingApi.Core.Bridge.Operations;
+using PixiEditor.DrawingApi.Skia.Exceptions;
 using PixiEditor.DrawingApi.Skia.Implementations;
 using SkiaSharp;
 
@@ -8,6 +9,22 @@ namespace PixiEditor.DrawingApi.Skia
 {
     public class SkiaDrawingBackend : IDrawingBackend
     {
+        public GRContext? GraphicsContext
+        {
+            get => _grContext;
+            set
+            {
+                if (_grContext != null)
+                {
+                    throw new GrContextAlreadyInitializedException();
+                }
+                
+                _grContext = value;
+            }
+        }
+        
+        public bool IsGpuAccelerated => GraphicsContext != null;
+        
         public IColorImplementation ColorImplementation { get; }
         public IImageImplementation ImageImplementation { get; }
         public IImgDataImplementation ImgDataImplementation { get; }
@@ -16,13 +33,16 @@ namespace PixiEditor.DrawingApi.Skia
         public IVectorPathImplementation PathImplementation { get; }
         public IMatrix3X3Implementation MatrixImplementation { get; }
         public IPixmapImplementation PixmapImplementation { get; }
-        public ISurfaceImplementation SurfaceImplementation { get; }
+        public ISurfaceImplementation SurfaceImplementation => _surfaceImplementation;
         public IColorSpaceImplementation ColorSpaceImplementation { get; }
         public IBitmapImplementation BitmapImplementation { get; }
         public IColorFilterImplementation ColorFilterImplementation { get; set; }
         public IShaderImplementation ShaderImplementation { get; set; }
+        
+        private SkiaSurfaceImplementation _surfaceImplementation;
+        private GRContext _grContext;
 
-        public SkiaDrawingBackend(GRContext graphicsContext)
+        public SkiaDrawingBackend()
         {
             ColorImplementation = new SkiaColorImplementation();
             
@@ -57,20 +77,17 @@ namespace PixiEditor.DrawingApi.Skia
             
             SkiaCanvasImplementation canvasImpl = new SkiaCanvasImplementation(paintImpl, imgImpl, bitmapImpl, pathImpl);
             
-            var surfaceImpl = new SkiaSurfaceImplementation(graphicsContext, pixmapImpl, canvasImpl, paintImpl);
+            _surfaceImplementation = new SkiaSurfaceImplementation(GraphicsContext, pixmapImpl, canvasImpl, paintImpl);
 
-            canvasImpl.SetSurfaceImplementation(surfaceImpl);
-            imgImpl.SetSurfaceImplementation(surfaceImpl);
+            canvasImpl.SetSurfaceImplementation(_surfaceImplementation);
+            imgImpl.SetSurfaceImplementation(_surfaceImplementation);
 
             CanvasImplementation = canvasImpl;
-
-            SurfaceImplementation = surfaceImpl;
-
         }
         
         public void Setup()
         {
-            
+            _surfaceImplementation.GraphicsContext = GraphicsContext;
         }
     }
 }

+ 15 - 0
src/PixiEditor.Engine.AvaloniaPlatform/PixiEditor.Engine.AvaloniaPlatform.csproj

@@ -0,0 +1,15 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net8.0</TargetFramework>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <Nullable>enable</Nullable>
+    <Avalonia_I_Want_To_Use_Private_Apis_In_Nuget_Package_And_Promise_To_Pin_The_Exact_Avalonia_Version_In_Package_Dependency>true</Avalonia_I_Want_To_Use_Private_Apis_In_Nuget_Package_And_Promise_To_Pin_The_Exact_Avalonia_Version_In_Package_Dependency>
+    <AvaloniaAccessUnstablePrivateApis>true</AvaloniaAccessUnstablePrivateApis>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Avalonia.Skia" Version="$(AvaloniaVersion)"/>
+  </ItemGroup>
+
+</Project>

+ 11 - 0
src/PixiEditor.Engine.AvaloniaPlatform/PixiEnginePlatform.cs

@@ -0,0 +1,11 @@
+using Avalonia;
+
+namespace PixiEditor.Engine.AvaloniaPlatform;
+
+internal class PixiEnginePlatform
+{
+    public static void Initialize()
+    {
+        //AvaloniaLocator.CurrentMutable
+    }
+}

+ 71 - 0
src/PixiEditor.Engine.AvaloniaPlatform/PixiEngineTopLevelImpl.cs

@@ -0,0 +1,71 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Input;
+using Avalonia.Input.Raw;
+using Avalonia.Platform;
+using Avalonia.Rendering.Composition;
+
+namespace PixiEditor.Engine.AvaloniaPlatform;
+
+internal sealed class PixiEngineTopLevelImpl : ITopLevelImpl
+{
+    public Size ClientSize { get; }
+    public Size? FrameSize { get; }
+    public double RenderScaling { get; }
+    public IEnumerable<object> Surfaces { get; }
+    public Action<RawInputEventArgs>? Input { get; set; }
+    public Action<Rect>? Paint { get; set;  }
+    public Action<Size, WindowResizeReason>? Resized { get; set; }
+    public Action<double>? ScalingChanged { get; set; }
+    public Action<WindowTransparencyLevel>? TransparencyLevelChanged { get; set; }
+    public Compositor Compositor { get; }
+    public Action? Closed { get; set; }
+    public Action? LostFocus { get; set; }
+    public WindowTransparencyLevel TransparencyLevel { get; }
+    public AcrylicPlatformCompensationLevels AcrylicCompensationLevels { get; }
+
+    public object? TryGetFeature(Type featureType)
+    {
+        throw new NotImplementedException();
+    }
+
+    public void SetInputRoot(IInputRoot inputRoot)
+    {
+        throw new NotImplementedException();
+    }
+
+    public Point PointToClient(PixelPoint point)
+    {
+        throw new NotImplementedException();
+    }
+
+    public PixelPoint PointToScreen(Point point)
+    {
+        throw new NotImplementedException();
+    }
+
+    public void SetCursor(ICursorImpl? cursor)
+    {
+        throw new NotImplementedException();
+    }
+
+    public IPopupImpl? CreatePopup()
+    {
+        throw new NotImplementedException();
+    }
+
+    public void SetTransparencyLevelHint(IReadOnlyList<WindowTransparencyLevel> transparencyLevels)
+    {
+        throw new NotImplementedException();
+    }
+
+    public void SetFrameThemeVariant(PlatformThemeVariant themeVariant)
+    {
+        throw new NotImplementedException();
+    }
+
+    public void Dispose()
+    {
+        throw new NotImplementedException();
+    }
+}

+ 8 - 0
src/PixiEditor.Engine/Exceptions/PixiEngineException.cs

@@ -0,0 +1,8 @@
+namespace PixiEditor.Engine.Exceptions;
+
+public abstract class PixiEngineException : Exception
+{
+    public PixiEngineException(string message) : base(message)
+    {
+    }
+}

+ 17 - 0
src/PixiEditor.Engine/Helpers/VectorExtensions.cs

@@ -0,0 +1,17 @@
+using PixiEditor.Numerics;
+using Silk.NET.Maths;
+
+namespace PixiEditor.Engine.Helpers;
+
+public static class VectorExtensions
+{
+    public static VecI ToVecI(this Vector2D<int> vector)
+    {
+        return new VecI(vector.X, vector.Y);
+    }
+    
+    public static Vector2D<int> ToVector2D(this VecI vector)
+    {
+        return new Vector2D<int>(vector.X, vector.Y);
+    }
+}

+ 26 - 0
src/PixiEditor.Engine/PixiEditor.Engine.csproj

@@ -0,0 +1,26 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net8.0</TargetFramework>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <Nullable>enable</Nullable>
+    <RootNamespace>PixiEditor.Engine</RootNamespace>
+  </PropertyGroup> 
+
+  <ItemGroup>
+    <PackageReference Include="Silk.NET.OpenGL" Version="2.21.0" />
+    <PackageReference Include="Silk.NET.Windowing" Version="2.21.0" />
+    <PackageReference Include="SkiaSharp" Version="2.88.8" />
+  </ItemGroup> 
+
+  <ItemGroup>
+    <ProjectReference Include="..\PixiEditor.DrawingApi.Core\PixiEditor.DrawingApi.Core.csproj" />
+    <ProjectReference Include="..\PixiEditor.DrawingApi.Skia\PixiEditor.DrawingApi.Skia.csproj" />
+    <ProjectReference Include="..\PixiEditor.Numerics\PixiEditor.Numerics.csproj" />
+  </ItemGroup> 
+
+  <ItemGroup>
+    <ProjectReference Include="..\PixiEditor.Numerics\PixiEditor.Numerics.csproj" />
+  </ItemGroup> 
+
+</Project>

+ 20 - 0
src/PixiEditor.Engine/PixiEngine.cs

@@ -0,0 +1,20 @@
+using PixiEditor.DrawingApi.Core.Bridge;
+using PixiEditor.DrawingApi.Skia;
+using SkiaSharp;
+
+namespace PixiEditor.Engine;
+
+public abstract class PixiEngine
+{
+    private IDrawingBackend _drawingBackend;
+    
+    internal PixiEngine(IDrawingBackend drawingBackend)
+    {
+        _drawingBackend = drawingBackend;
+    }
+
+    protected virtual void Setup()
+    {
+        DrawingBackendApi.SetupBackend(_drawingBackend);
+    }
+}

+ 40 - 0
src/PixiEditor.Engine/SkiaPixiEngine.cs

@@ -0,0 +1,40 @@
+using PixiEditor.DrawingApi.Core.Bridge;
+using PixiEditor.DrawingApi.Skia;
+using PixiEditor.DrawingApi.Skia.Exceptions;
+using SkiaSharp;
+
+namespace PixiEditor.Engine;
+
+public sealed class SkiaPixiEngine : PixiEngine
+{
+    private SkiaDrawingBackend _drawingBackend;
+    private SkiaPixiEngine(IDrawingBackend drawingBackend) : base(drawingBackend)
+    {
+        _drawingBackend = (SkiaDrawingBackend)drawingBackend;
+    }
+
+    public static SkiaPixiEngine Create()
+    {
+        return new SkiaPixiEngine(new SkiaDrawingBackend());
+    }
+
+    public void Setup(GRContext context)
+    {
+        Setup();
+        _drawingBackend.GraphicsContext = context;
+        _drawingBackend.Setup();
+    }
+    
+    public void RunWithWindow(Window window)
+    {
+        window.InitWithGrContext += Setup;
+        window.Run();
+    }
+    
+    public static SkiaPixiEngine CreateAndRun(Window window)
+    {
+        SkiaPixiEngine engine = Create();
+        engine.RunWithWindow(window);
+        return engine;
+    }
+}

+ 29 - 13
src/DrawingApi.MinimalGpuSetup/OpenGlSkiaWindow.cs → src/PixiEditor.Engine/Window.cs

@@ -1,12 +1,14 @@
-using Silk.NET.GLFW;
+using PixiEditor.Engine.Helpers;
+using PixiEditor.Numerics;
+using Silk.NET.GLFW;
 using Silk.NET.Maths;
 using Silk.NET.OpenGL;
 using Silk.NET.Windowing;
 using SkiaSharp;
 
-namespace DrawingApi.MinimalGpuSetup;
+namespace PixiEditor.Engine;
 
-public class OpenGlSkiaWindow
+public class Window
 {
     private GL gl;
     private IWindow _window;
@@ -14,30 +16,44 @@ public class OpenGlSkiaWindow
 
     private SKSurface frontBufferSurface;
     
+    public string Title
+    {
+        get => _window.Title;
+        set => _window.Title = value;
+    }
+    
+    public VecI Size
+    {
+        get => _window.Size.ToVecI();
+        set => _window.Size = value.ToVector2D();
+    }
+
     public event Action<SKSurface, double> Render;
-    public event Action<GRContext> Init;
+    public event Action Init;
+    internal event Action<GRContext> InitWithGrContext;
 
-    public OpenGlSkiaWindow()
+    public Window(string title, VecI size)
     {
         WindowOptions options = WindowOptions.Default with
         {
-            Title = "OpenGL Window", Size = new Vector2D<int>(1200, 600)
+            Title = title, Size = size.ToVector2D()
         };
 
-        _window = Window.Create(options);
+        _window = Silk.NET.Windowing.Window.Create(options);
 
         _window.Load += () =>
         {
             gl = GL.GetApi(_window);
             frontBufferSurface = SKSurface.Create(new SKImageInfo(1200, 600));
-            
+
             _window.GLContext.MakeCurrent();
 
             InitSkiaSurface();
-            
-            Init?.Invoke(_grContext);
+
+            InitWithGrContext?.Invoke(_grContext);
+            Init?.Invoke();
         };
-        
+
         _window.Render += OnRender;
     }
 
@@ -45,11 +61,11 @@ public class OpenGlSkiaWindow
     {
         _window.Run();
     }
-    
+
     private void OnRender(double deltaTime)
     {
         frontBufferSurface.Canvas.Clear(SKColors.White);
-        Render?.Invoke(frontBufferSurface, deltaTime); 
+        Render?.Invoke(frontBufferSurface, deltaTime);
         frontBufferSurface.Canvas.Flush();
     }
 

+ 92 - 90
src/PixiEditor.sln

@@ -102,11 +102,13 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PixiEditor.AnimationRendere
 EndProject
 Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "AnimationRendering", "AnimationRendering", "{2BA72059-FFD7-4887-AE88-269017198933}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DrawingApi.Benchmarks", "DrawingApi.Benchmarks\DrawingApi.Benchmarks.csproj", "{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PixiEditor.Engine", "PixiEditor.Engine\PixiEditor.Engine.csproj", "{4B1436E5-F586-4165-946D-CE2AE653561A}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DrawingApi.MinimalGpuSetup", "DrawingApi.MinimalGpuSetup\DrawingApi.MinimalGpuSetup.csproj", "{BAF15725-9536-4D8B-9E46-0EB2C9866C86}"
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Engine", "Engine", "{55A3BEC1-C848-4BA9-BB16-028467CC46C8}"
 EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PixiEditor.AvaloniaHeadless", "PixiEditor.AvaloniaHeadless\PixiEditor.AvaloniaHeadless.csproj", "{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}"
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PixiEditor.Engine.AvaloniaPlatform", "PixiEditor.Engine.AvaloniaPlatform\PixiEditor.Engine.AvaloniaPlatform.csproj", "{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PixiEngineSampleApp", "PixiEngineSampleApp\PixiEngineSampleApp.csproj", "{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}"
 EndProject
 Global
 	GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -1506,90 +1508,90 @@ Global
 		{CD863C88-72E3-40F4-9AAE-5696BBB4460C}.Steam|x64.Build.0 = Debug|Any CPU
 		{CD863C88-72E3-40F4-9AAE-5696BBB4460C}.Steam|ARM64.ActiveCfg = Debug|Any CPU
 		{CD863C88-72E3-40F4-9AAE-5696BBB4460C}.Steam|ARM64.Build.0 = Debug|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.Debug|x64.ActiveCfg = Debug|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.Debug|x64.Build.0 = Debug|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.Debug|ARM64.ActiveCfg = Debug|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.Debug|ARM64.Build.0 = Debug|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.DevRelease|x64.ActiveCfg = Debug|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.DevRelease|x64.Build.0 = Debug|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.DevRelease|ARM64.ActiveCfg = Debug|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.DevRelease|ARM64.Build.0 = Debug|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.DevSteam|x64.ActiveCfg = Debug|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.DevSteam|x64.Build.0 = Debug|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.DevSteam|ARM64.ActiveCfg = Debug|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.DevSteam|ARM64.Build.0 = Debug|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.MSIX Debug|x64.ActiveCfg = Debug|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.MSIX Debug|x64.Build.0 = Debug|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.MSIX Debug|ARM64.ActiveCfg = Debug|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.MSIX Debug|ARM64.Build.0 = Debug|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.MSIX|x64.ActiveCfg = Debug|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.MSIX|x64.Build.0 = Debug|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.MSIX|ARM64.ActiveCfg = Debug|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.MSIX|ARM64.Build.0 = Debug|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.Release|x64.ActiveCfg = Release|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.Release|x64.Build.0 = Release|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.Release|ARM64.ActiveCfg = Release|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.Release|ARM64.Build.0 = Release|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.Steam|x64.ActiveCfg = Debug|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.Steam|x64.Build.0 = Debug|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.Steam|ARM64.ActiveCfg = Debug|Any CPU
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A}.Steam|ARM64.Build.0 = Debug|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.Debug|x64.ActiveCfg = Debug|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.Debug|x64.Build.0 = Debug|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.Debug|ARM64.ActiveCfg = Debug|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.Debug|ARM64.Build.0 = Debug|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.DevRelease|x64.ActiveCfg = Debug|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.DevRelease|x64.Build.0 = Debug|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.DevRelease|ARM64.ActiveCfg = Debug|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.DevRelease|ARM64.Build.0 = Debug|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.DevSteam|x64.ActiveCfg = Debug|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.DevSteam|x64.Build.0 = Debug|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.DevSteam|ARM64.ActiveCfg = Debug|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.DevSteam|ARM64.Build.0 = Debug|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.MSIX Debug|x64.ActiveCfg = Debug|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.MSIX Debug|x64.Build.0 = Debug|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.MSIX Debug|ARM64.ActiveCfg = Debug|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.MSIX Debug|ARM64.Build.0 = Debug|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.MSIX|x64.ActiveCfg = Debug|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.MSIX|x64.Build.0 = Debug|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.MSIX|ARM64.ActiveCfg = Debug|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.MSIX|ARM64.Build.0 = Debug|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.Release|x64.ActiveCfg = Release|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.Release|x64.Build.0 = Release|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.Release|ARM64.ActiveCfg = Release|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.Release|ARM64.Build.0 = Release|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.Steam|x64.ActiveCfg = Debug|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.Steam|x64.Build.0 = Debug|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.Steam|ARM64.ActiveCfg = Debug|Any CPU
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86}.Steam|ARM64.Build.0 = Debug|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.Debug|x64.ActiveCfg = Debug|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.Debug|x64.Build.0 = Debug|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.Debug|ARM64.ActiveCfg = Debug|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.Debug|ARM64.Build.0 = Debug|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.DevRelease|x64.ActiveCfg = Debug|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.DevRelease|x64.Build.0 = Debug|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.DevRelease|ARM64.ActiveCfg = Debug|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.DevRelease|ARM64.Build.0 = Debug|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.DevSteam|x64.ActiveCfg = Debug|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.DevSteam|x64.Build.0 = Debug|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.DevSteam|ARM64.ActiveCfg = Debug|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.DevSteam|ARM64.Build.0 = Debug|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.MSIX Debug|x64.ActiveCfg = Debug|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.MSIX Debug|x64.Build.0 = Debug|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.MSIX Debug|ARM64.ActiveCfg = Debug|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.MSIX Debug|ARM64.Build.0 = Debug|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.MSIX|x64.ActiveCfg = Debug|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.MSIX|x64.Build.0 = Debug|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.MSIX|ARM64.ActiveCfg = Debug|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.MSIX|ARM64.Build.0 = Debug|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.Release|x64.ActiveCfg = Release|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.Release|x64.Build.0 = Release|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.Release|ARM64.ActiveCfg = Release|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.Release|ARM64.Build.0 = Release|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.Steam|x64.ActiveCfg = Debug|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.Steam|x64.Build.0 = Debug|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.Steam|ARM64.ActiveCfg = Debug|Any CPU
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562}.Steam|ARM64.Build.0 = Debug|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.Debug|x64.Build.0 = Debug|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.Debug|ARM64.ActiveCfg = Debug|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.Debug|ARM64.Build.0 = Debug|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.DevRelease|x64.ActiveCfg = Debug|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.DevRelease|x64.Build.0 = Debug|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.DevRelease|ARM64.ActiveCfg = Debug|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.DevRelease|ARM64.Build.0 = Debug|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.DevSteam|x64.ActiveCfg = Debug|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.DevSteam|x64.Build.0 = Debug|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.DevSteam|ARM64.ActiveCfg = Debug|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.DevSteam|ARM64.Build.0 = Debug|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.MSIX Debug|x64.ActiveCfg = Debug|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.MSIX Debug|x64.Build.0 = Debug|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.MSIX Debug|ARM64.ActiveCfg = Debug|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.MSIX Debug|ARM64.Build.0 = Debug|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.MSIX|x64.ActiveCfg = Debug|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.MSIX|x64.Build.0 = Debug|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.MSIX|ARM64.ActiveCfg = Debug|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.MSIX|ARM64.Build.0 = Debug|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.Release|x64.ActiveCfg = Release|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.Release|x64.Build.0 = Release|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.Release|ARM64.ActiveCfg = Release|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.Release|ARM64.Build.0 = Release|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.Steam|x64.ActiveCfg = Debug|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.Steam|x64.Build.0 = Debug|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.Steam|ARM64.ActiveCfg = Debug|Any CPU
+		{4B1436E5-F586-4165-946D-CE2AE653561A}.Steam|ARM64.Build.0 = Debug|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.Debug|x64.Build.0 = Debug|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.Debug|ARM64.ActiveCfg = Debug|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.Debug|ARM64.Build.0 = Debug|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.DevRelease|x64.ActiveCfg = Debug|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.DevRelease|x64.Build.0 = Debug|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.DevRelease|ARM64.ActiveCfg = Debug|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.DevRelease|ARM64.Build.0 = Debug|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.DevSteam|x64.ActiveCfg = Debug|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.DevSteam|x64.Build.0 = Debug|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.DevSteam|ARM64.ActiveCfg = Debug|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.DevSteam|ARM64.Build.0 = Debug|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.MSIX Debug|x64.ActiveCfg = Debug|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.MSIX Debug|x64.Build.0 = Debug|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.MSIX Debug|ARM64.ActiveCfg = Debug|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.MSIX Debug|ARM64.Build.0 = Debug|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.MSIX|x64.ActiveCfg = Debug|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.MSIX|x64.Build.0 = Debug|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.MSIX|ARM64.ActiveCfg = Debug|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.MSIX|ARM64.Build.0 = Debug|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.Release|x64.ActiveCfg = Release|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.Release|x64.Build.0 = Release|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.Release|ARM64.ActiveCfg = Release|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.Release|ARM64.Build.0 = Release|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.Steam|x64.ActiveCfg = Debug|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.Steam|x64.Build.0 = Debug|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.Steam|ARM64.ActiveCfg = Debug|Any CPU
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C}.Steam|ARM64.Build.0 = Debug|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.Debug|x64.ActiveCfg = Debug|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.Debug|x64.Build.0 = Debug|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.Debug|ARM64.ActiveCfg = Debug|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.Debug|ARM64.Build.0 = Debug|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.DevRelease|x64.ActiveCfg = Debug|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.DevRelease|x64.Build.0 = Debug|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.DevRelease|ARM64.ActiveCfg = Debug|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.DevRelease|ARM64.Build.0 = Debug|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.DevSteam|x64.ActiveCfg = Debug|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.DevSteam|x64.Build.0 = Debug|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.DevSteam|ARM64.ActiveCfg = Debug|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.DevSteam|ARM64.Build.0 = Debug|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.MSIX Debug|x64.ActiveCfg = Debug|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.MSIX Debug|x64.Build.0 = Debug|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.MSIX Debug|ARM64.ActiveCfg = Debug|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.MSIX Debug|ARM64.Build.0 = Debug|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.MSIX|x64.ActiveCfg = Debug|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.MSIX|x64.Build.0 = Debug|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.MSIX|ARM64.ActiveCfg = Debug|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.MSIX|ARM64.Build.0 = Debug|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.Release|x64.ActiveCfg = Release|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.Release|x64.Build.0 = Release|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.Release|ARM64.ActiveCfg = Release|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.Release|ARM64.Build.0 = Release|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.Steam|x64.ActiveCfg = Debug|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.Steam|x64.Build.0 = Debug|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.Steam|ARM64.ActiveCfg = Debug|Any CPU
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80}.Steam|ARM64.Build.0 = Debug|Any CPU
 	EndGlobalSection
 	GlobalSection(SolutionProperties) = preSolution
 		HideSolutionNode = FALSE
@@ -1636,9 +1638,9 @@ Global
 		{2BA72059-FFD7-4887-AE88-269017198933} = {1E816135-76C1-4255-BE3C-BF17895A65AA}
 		{9B552A44-9587-4410-8673-254B31E2E4F7} = {2BA72059-FFD7-4887-AE88-269017198933}
 		{CD863C88-72E3-40F4-9AAE-5696BBB4460C} = {2BA72059-FFD7-4887-AE88-269017198933}
-		{34B1472E-EE1B-46C7-B5ED-29CD13457C7A} = {5AFBF881-C054-4CE4-8159-8D4017FFD27A}
-		{BAF15725-9536-4D8B-9E46-0EB2C9866C86} = {5AFBF881-C054-4CE4-8159-8D4017FFD27A}
-		{3DEC93A8-E35F-4A5D-BF7B-20C502A48562} = {5AFBF881-C054-4CE4-8159-8D4017FFD27A}
+		{4B1436E5-F586-4165-946D-CE2AE653561A} = {55A3BEC1-C848-4BA9-BB16-028467CC46C8}
+		{78D6EAAD-9660-4D96-A887-0D3D3D7D8F4C} = {55A3BEC1-C848-4BA9-BB16-028467CC46C8}
+		{AAC75D6D-AAD0-4144-9951-9EC58CF09C80} = {5AFBF881-C054-4CE4-8159-8D4017FFD27A}
 	EndGlobalSection
 	GlobalSection(ExtensibilityGlobals) = postSolution
 		SolutionGuid = {D04B4AB0-CA33-42FD-A909-79966F9255C5}

+ 14 - 0
src/PixiEngineSampleApp/PixiEngineSampleApp.csproj

@@ -0,0 +1,14 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+    <PropertyGroup>
+        <OutputType>Exe</OutputType>
+        <TargetFramework>net8.0</TargetFramework>
+        <ImplicitUsings>enable</ImplicitUsings>
+        <Nullable>enable</Nullable>
+    </PropertyGroup>
+
+    <ItemGroup>
+      <ProjectReference Include="..\PixiEditor.Engine\PixiEditor.Engine.csproj" />
+    </ItemGroup>
+
+</Project>

+ 14 - 14
src/DrawingApi.MinimalGpuSetup/Program.cs → src/PixiEngineSampleApp/Program.cs

@@ -1,10 +1,10 @@
-using DrawingApi.MinimalGpuSetup;
-using PixiEditor.DrawingApi.Core.Bridge;
+using PixiEditor.DrawingApi.Core.Bridge;
 using PixiEditor.DrawingApi.Core.Surface;
 using PixiEditor.DrawingApi.Core.Surface.ImageData;
 using PixiEditor.DrawingApi.Core.Surface.PaintImpl;
 using PixiEditor.DrawingApi.Skia;
-using Silk.NET.GLFW;
+using PixiEditor.Engine;
+using PixiEditor.Numerics;
 using SkiaSharp;
 
 public static class Program
@@ -12,28 +12,28 @@ public static class Program
     private static DrawingSurface _drawingSurface;
     private static Paint _paint = new Paint();
     private static SKPaint _screenPaint = new SKPaint();
-    
+
     private static int _time = 0;
     private static double _lastTime = 0;
-    
+
     public static void Main()
     {
-       OpenGlSkiaWindow window = new OpenGlSkiaWindow();
-       window.Render += WindowOnRender;
-       window.Init += Init;
-       window.Run();
+        Window mainWindow = new Window("PixiEngineSampleApp", new VecI(1200, 600));
+        mainWindow.Render += WindowOnRender;
+        mainWindow.Init += Init;
+        
+        SkiaPixiEngine.CreateAndRun(mainWindow);
     }
-    
-    private static void Init(GRContext context)
+
+    private static void Init()
     {
-        DrawingBackendApi.SetupBackend(new SkiaDrawingBackend(context));
-        _drawingSurface = DrawingSurface.Create(new ImageInfo(100, 100), true);
+        _drawingSurface = DrawingSurface.Create(new ImageInfo(100, 100));
     }
 
     private static void WindowOnRender(SKSurface surface, double deltaTime)
     {
         surface.Canvas.DrawSurface((SKSurface)_drawingSurface.Native, 0, 0, _screenPaint);
-        
+
         _lastTime += deltaTime;
         if (_lastTime > 1)
         {