Browse Source

Made scene work with gpu

flabbet 11 months ago
parent
commit
fcdaeac067

+ 3 - 2
src/PixiEditor.DrawingApi.Core/Texture.cs

@@ -13,6 +13,7 @@ public class Texture : IDisposable
     public VecI Size { get; }
     public VecI Size { get; }
     public DrawingSurface Surface { get; }
     public DrawingSurface Surface { get; }
 
 
+    
     public bool IsDisposed { get; private set; }
     public bool IsDisposed { get; private set; }
 
 
     public Texture(VecI size)
     public Texture(VecI size)
@@ -24,9 +25,9 @@ public class Texture : IDisposable
                 {
                 {
                     GpuBacked = true
                     GpuBacked = true
                 });
                 });
+        
     }
     }
 
 
-
     public static Texture Load(string path)
     public static Texture Load(string path)
     {
     {
         if (!File.Exists(path))
         if (!File.Exists(path))
@@ -96,7 +97,7 @@ public class Texture : IDisposable
     {
     {
         if (IsDisposed)
         if (IsDisposed)
             return;
             return;
-        
+
         IsDisposed = true;
         IsDisposed = true;
         Surface.Dispose();
         Surface.Dispose();
     }
     }

+ 1 - 1
src/PixiEditor.DrawingApi.Skia/Implementations/SkiaSurfaceImplementation.cs

@@ -152,7 +152,7 @@ namespace PixiEditor.DrawingApi.Skia.Implementations
 
 
         public void Flush(DrawingSurface drawingSurface)
         public void Flush(DrawingSurface drawingSurface)
         {
         {
-            ManagedInstances[drawingSurface.ObjectPointer].Flush(true, true);
+            ManagedInstances[drawingSurface.ObjectPointer].Flush(true, false);
         }
         }
     }
     }
 }
 }

+ 2 - 2
src/PixiEditor/Models/DocumentModels/ActionAccumulator.cs

@@ -139,7 +139,7 @@ internal class ActionAccumulator
                         RectI finalRect = new RectI(VecI.Zero, new(bitmap.Size.X, bitmap.Size.Y));
                         RectI finalRect = new RectI(VecI.Zero, new(bitmap.Size.X, bitmap.Size.Y));
 
 
                         RectI dirtyRect = new RectI(info.Pos, info.Size).Intersect(finalRect);
                         RectI dirtyRect = new RectI(info.Pos, info.Size).Intersect(finalRect);
-                        bitmap.AddDirtyRect(dirtyRect);
+                        // bitmap.AddDirtyRect(dirtyRect);
                     }
                     }
                     break;
                     break;
                 case PreviewDirty_RenderInfo info:
                 case PreviewDirty_RenderInfo info:
@@ -161,7 +161,7 @@ internal class ActionAccumulator
                     break;
                     break;
                 case CanvasPreviewDirty_RenderInfo:
                 case CanvasPreviewDirty_RenderInfo:
                     {
                     {
-                        document.PreviewSurface.AddDirtyRect(new RectI(0, 0, document.PreviewSurface.Size.X, document.PreviewSurface.Size.Y));
+                        //document.PreviewSurface.AddDirtyRect(new RectI(0, 0, document.PreviewSurface.Size.X, document.PreviewSurface.Size.Y));
                     }
                     }
                     break;
                     break;
                 case NodePreviewDirty_RenderInfo info:
                 case NodePreviewDirty_RenderInfo info:

+ 3 - 3
src/PixiEditor/Models/DocumentModels/DocumentUpdater.cs

@@ -345,11 +345,11 @@ internal class DocumentUpdater
     {
     {
         VecI oldSize = doc.SizeBindable;
         VecI oldSize = doc.SizeBindable;
 
 
-        foreach ((ChunkResolution res, Surface surf) in doc.Surfaces)
+        foreach ((ChunkResolution res, Texture surf) in doc.Surfaces)
         {
         {
             surf.Dispose();
             surf.Dispose();
             VecI size = (VecI)(info.Size * res.Multiplier());
             VecI size = (VecI)(info.Size * res.Multiplier());
-            doc.Surfaces[res] = new Surface(new VecI(Math.Max(size.X, 1), Math.Max(size.Y, 1))); //TODO: Bgra8888 was here
+            doc.Surfaces[res] = new Texture(new VecI(Math.Max(size.X, 1), Math.Max(size.Y, 1))); //TODO: Bgra8888 was here
         }
         }
 
 
         doc.SetSize(info.Size);
         doc.SetSize(info.Size);
@@ -358,7 +358,7 @@ internal class DocumentUpdater
 
 
         VecI documentPreviewSize = StructureHelpers.CalculatePreviewSize(info.Size);
         VecI documentPreviewSize = StructureHelpers.CalculatePreviewSize(info.Size);
         doc.PreviewSurface.Dispose();
         doc.PreviewSurface.Dispose();
-        doc.PreviewSurface = new Surface(documentPreviewSize); //TODO: Bgra8888 was here
+        doc.PreviewSurface = new Texture(documentPreviewSize); //TODO: Bgra8888 was here
 
 
         // TODO: Make sure property changed events are raised internally
         // TODO: Make sure property changed events are raised internally
         // UPDATE: I think I did, but I'll leave it commented out for now
         // UPDATE: I think I did, but I'll leave it commented out for now

+ 2 - 2
src/PixiEditor/Models/Handlers/IDocument.cs

@@ -25,9 +25,9 @@ internal interface IDocument : IHandler
     public IAnimationHandler AnimationHandler { get; }
     public IAnimationHandler AnimationHandler { get; }
     public VectorPath SelectionPathBindable { get; }
     public VectorPath SelectionPathBindable { get; }
     public INodeGraphHandler NodeGraphHandler { get; }
     public INodeGraphHandler NodeGraphHandler { get; }
-    public Dictionary<ChunkResolution, Surface> Surfaces { get; set; }
+    public Dictionary<ChunkResolution, Texture> Surfaces { get; set; }
     public DocumentStructureModule StructureHelper { get; }
     public DocumentStructureModule StructureHelper { get; }
-    public Surface PreviewSurface { get; set; }
+    public Texture PreviewSurface { get; set; }
     public bool AllChangesSaved { get; }
     public bool AllChangesSaved { get; }
     public string CoordinatesString { get; set; }
     public string CoordinatesString { get; set; }
     public IReadOnlyCollection<IStructureMemberHandler> SoftSelectedStructureMembers { get; }
     public IReadOnlyCollection<IStructureMemberHandler> SoftSelectedStructureMembers { get; }

+ 39 - 20
src/PixiEditor/Models/Rendering/CanvasUpdater.cs

@@ -1,5 +1,6 @@
 using System.Collections.Generic;
 using System.Collections.Generic;
 using System.Threading.Tasks;
 using System.Threading.Tasks;
+using Avalonia.Threading;
 using ChunkyImageLib;
 using ChunkyImageLib;
 using ChunkyImageLib.DataHolders;
 using ChunkyImageLib.DataHolders;
 using ChunkyImageLib.Operations;
 using ChunkyImageLib.Operations;
@@ -196,7 +197,7 @@ internal class CanvasUpdater
                 globalScaledClippingRectangle =
                 globalScaledClippingRectangle =
                     (RectI?)((RectI)globalClippingRectangle).Scale(resolution.Multiplier()).RoundOutwards();
                     (RectI?)((RectI)globalClippingRectangle).Scale(resolution.Multiplier()).RoundOutwards();
 
 
-            Surface screenSurface = doc.Surfaces[resolution];
+            Texture screenSurface = doc.Surfaces[resolution];
             foreach (var chunkPos in chunks)
             foreach (var chunkPos in chunks)
             {
             {
                 RenderChunk(chunkPos, screenSurface, resolution, globalClippingRectangle,
                 RenderChunk(chunkPos, screenSurface, resolution, globalClippingRectangle,
@@ -214,38 +215,56 @@ internal class CanvasUpdater
         }
         }
     }
     }
 
 
-    private void RenderChunk(VecI chunkPos, Surface screenSurface, ChunkResolution resolution,
+    private void RenderChunk(VecI chunkPos, Texture screenSurface, ChunkResolution resolution,
         RectI? globalClippingRectangle, RectI? globalScaledClippingRectangle)
         RectI? globalClippingRectangle, RectI? globalScaledClippingRectangle)
     {
     {
         if (screenSurface is null || screenSurface.IsDisposed)
         if (screenSurface is null || screenSurface.IsDisposed)
             return;
             return;
 
 
-        if (globalScaledClippingRectangle is not null)
-        {
-            screenSurface.DrawingSurface.Canvas.Save();
-            screenSurface.DrawingSurface.Canvas.ClipRect((RectD)globalScaledClippingRectangle);
-        }
 
 
         doc.Renderer.RenderChunk(chunkPos, resolution, doc.AnimationHandler.ActiveFrameTime, globalClippingRectangle)
         doc.Renderer.RenderChunk(chunkPos, resolution, doc.AnimationHandler.ActiveFrameTime, globalClippingRectangle)
             .Switch(
             .Switch(
                 (Chunk chunk) =>
                 (Chunk chunk) =>
                 {
                 {
-                    if (screenSurface.IsDisposed) return;
-                    
-                    screenSurface.DrawingSurface.Canvas.DrawSurface(chunk.Surface.DrawingSurface,
-                        chunkPos.Multiply(chunk.PixelSize), ReplacingPaint);
-                    chunk.Dispose();
+                    Dispatcher.UIThread.Post(() =>
+                    {
+                        if (screenSurface.IsDisposed) return;
+
+                        if (globalScaledClippingRectangle is not null)
+                        {
+                            screenSurface.Surface.Canvas.Save();
+                            screenSurface.Surface.Canvas.ClipRect((RectD)globalScaledClippingRectangle);
+                        }
+
+                        screenSurface.Surface.Canvas.DrawSurface(
+                            chunk.Surface.DrawingSurface,
+                            chunkPos.Multiply(chunk.PixelSize), ReplacingPaint);
+                        chunk.Dispose();
+
+
+                        if (globalScaledClippingRectangle is not null)
+                            screenSurface.Surface.Canvas.Restore();
+                    });
                 },
                 },
                 (EmptyChunk _) =>
                 (EmptyChunk _) =>
                 {
                 {
-                    if (screenSurface.IsDisposed) return;
-                    
-                    var pos = chunkPos * resolution.PixelSize();
-                    screenSurface.DrawingSurface.Canvas.DrawRect(pos.X, pos.Y, resolution.PixelSize(),
-                        resolution.PixelSize(), ClearPaint);
-                });
+                    Dispatcher.UIThread.Post(() =>
+                    {
+                        if (screenSurface.IsDisposed) return;
 
 
-        if (globalScaledClippingRectangle is not null)
-            screenSurface.DrawingSurface.Canvas.Restore();
+                        if (globalScaledClippingRectangle is not null)
+                        {
+                            screenSurface.Surface.Canvas.Save();
+                            screenSurface.Surface.Canvas.ClipRect((RectD)globalScaledClippingRectangle);
+                        }
+
+                        var pos = chunkPos * resolution.PixelSize();
+                        screenSurface.Surface.Canvas.DrawRect(pos.X, pos.Y, resolution.PixelSize(),
+                            resolution.PixelSize(), ClearPaint);
+                        
+                        if (globalScaledClippingRectangle is not null)
+                            screenSurface.Surface.Canvas.Restore();
+                    });
+                });
     }
     }
 }
 }

+ 7 - 7
src/PixiEditor/Models/Rendering/MemberPreviewUpdater.cs

@@ -436,22 +436,22 @@ internal class MemberPreviewUpdater
             };
             };
             var pos = chunkPos * resolution.PixelSize();
             var pos = chunkPos * resolution.PixelSize();
             var rendered = doc.Renderer.RenderChunk(chunkPos, resolution, doc.AnimationHandler.ActiveFrameTime);
             var rendered = doc.Renderer.RenderChunk(chunkPos, resolution, doc.AnimationHandler.ActiveFrameTime);
-            doc.PreviewSurface.DrawingSurface.Canvas.Save();
-            doc.PreviewSurface.DrawingSurface.Canvas.Scale(scaling);
-            doc.PreviewSurface.DrawingSurface.Canvas.ClipRect((RectD)cumulative.GlobalArea);
-            doc.PreviewSurface.DrawingSurface.Canvas.Scale(1 / (float)resolution.Multiplier());
+            doc.PreviewSurface.Surface.Canvas.Save();
+            doc.PreviewSurface.Surface.Canvas.Scale(scaling);
+            doc.PreviewSurface.Surface.Canvas.ClipRect((RectD)cumulative.GlobalArea);
+            doc.PreviewSurface.Surface.Canvas.Scale(1 / (float)resolution.Multiplier());
             if (rendered.IsT1)
             if (rendered.IsT1)
             {
             {
-                doc.PreviewSurface.DrawingSurface.Canvas.DrawRect(pos.X, pos.Y, resolution.PixelSize(),
+                doc.PreviewSurface.Surface.Canvas.DrawRect(pos.X, pos.Y, resolution.PixelSize(),
                     resolution.PixelSize(), ClearPaint);
                     resolution.PixelSize(), ClearPaint);
             }
             }
             else if (rendered.IsT0)
             else if (rendered.IsT0)
             {
             {
                 using var renderedChunk = rendered.AsT0;
                 using var renderedChunk = rendered.AsT0;
-                renderedChunk.DrawChunkOn(doc.PreviewSurface.DrawingSurface, pos, SmoothReplacingPaint);
+                renderedChunk.DrawChunkOn(doc.PreviewSurface.Surface, pos, SmoothReplacingPaint);
             }
             }
 
 
-            doc.PreviewSurface.DrawingSurface.Canvas.Restore();
+            doc.PreviewSurface.Surface.Canvas.Restore();
         }
         }
 
 
         if (somethingChanged)
         if (somethingChanged)

+ 8 - 8
src/PixiEditor/ViewModels/Document/DocumentViewModel.cs

@@ -168,17 +168,17 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
     public IStructureMemberHandler? SelectedStructureMember { get; private set; } = null;
     public IStructureMemberHandler? SelectedStructureMember { get; private set; } = null;
 
 
     //TODO: It was DrawingSurface before, check if it's correct
     //TODO: It was DrawingSurface before, check if it's correct
-    public Dictionary<ChunkResolution, Surface> Surfaces { get; set; } = new()
+    public Dictionary<ChunkResolution, Texture> Surfaces { get; set; } = new()
     {
     {
-        [ChunkResolution.Full] = new Surface(new VecI(64, 64)),
-        [ChunkResolution.Half] = new Surface(new VecI(32, 32)),
-        [ChunkResolution.Quarter] = new Surface(new VecI(16, 16)),
-        [ChunkResolution.Eighth] = new Surface(new VecI(8, 8))
+        [ChunkResolution.Full] = new Texture(new VecI(64, 64)),
+        [ChunkResolution.Half] = new Texture(new VecI(32, 32)),
+        [ChunkResolution.Quarter] = new Texture(new VecI(16, 16)),
+        [ChunkResolution.Eighth] = new Texture(new VecI(8, 8))
     };
     };
 
 
-    private Surface previewSurface;
+    private Texture previewSurface;
 
 
-    public Surface PreviewSurface
+    public Texture PreviewSurface
     {
     {
         get => previewSurface;
         get => previewSurface;
         set
         set
@@ -237,7 +237,7 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
             Internals.ChangeController.LineOverlayMovedInlet(args.Item1, args.Item2);
             Internals.ChangeController.LineOverlayMovedInlet(args.Item1, args.Item2);
 
 
         VecI previewSize = StructureMemberViewModel.CalculatePreviewSize(SizeBindable);
         VecI previewSize = StructureMemberViewModel.CalculatePreviewSize(SizeBindable);
-        PreviewSurface = new Surface(new VecI(previewSize.X, previewSize.Y));
+        PreviewSurface = new Texture(new VecI(previewSize.X, previewSize.Y));
 
 
         ReferenceLayerViewModel = new(this, Internals);
         ReferenceLayerViewModel = new(this, Internals);
 
 

+ 3 - 3
src/PixiEditor/ViewModels/SubViewModels/ViewportWindowViewModel.cs

@@ -80,7 +80,7 @@ internal class ViewportWindowViewModel : SubViewModel<WindowViewModel>, IDockabl
         Document = document;
         Document = document;
         Document.SizeChanged += DocumentOnSizeChanged;
         Document.SizeChanged += DocumentOnSizeChanged;
         Document.PropertyChanged += DocumentOnPropertyChanged;
         Document.PropertyChanged += DocumentOnPropertyChanged;
-        TabCustomizationSettings.Icon = new SurfaceImage(Document.PreviewSurface);
+        TabCustomizationSettings.Icon = new TextureImage(Document.PreviewSurface);
     }
     }
 
 
     private void DocumentOnPropertyChanged(object? sender, PropertyChangedEventArgs e)
     private void DocumentOnPropertyChanged(object? sender, PropertyChangedEventArgs e)
@@ -91,7 +91,7 @@ internal class ViewportWindowViewModel : SubViewModel<WindowViewModel>, IDockabl
         }
         }
         else if (e.PropertyName == nameof(DocumentViewModel.PreviewSurface))
         else if (e.PropertyName == nameof(DocumentViewModel.PreviewSurface))
         {
         {
-            TabCustomizationSettings.Icon = new SurfaceImage(Document.PreviewSurface);
+            TabCustomizationSettings.Icon = new TextureImage(Document.PreviewSurface);
         }
         }
         else if (e.PropertyName == nameof(DocumentViewModel.AllChangesSaved))
         else if (e.PropertyName == nameof(DocumentViewModel.AllChangesSaved))
         {
         {
@@ -107,7 +107,7 @@ internal class ViewportWindowViewModel : SubViewModel<WindowViewModel>, IDockabl
 
 
     private void DocumentOnSizeChanged(object? sender, DocumentSizeChangedEventArgs e)
     private void DocumentOnSizeChanged(object? sender, DocumentSizeChangedEventArgs e)
     {
     {
-        TabCustomizationSettings.Icon = new SurfaceImage(Document.PreviewSurface);
+        TabCustomizationSettings.Icon = new TextureImage(Document.PreviewSurface);
         OnPropertyChanged(nameof(TabCustomizationSettings));
         OnPropertyChanged(nameof(TabCustomizationSettings));
     }
     }
 
 

+ 3 - 3
src/PixiEditor/Views/Main/ViewportControls/FixedViewport.axaml

@@ -14,10 +14,10 @@
              VerticalAlignment="Center"
              VerticalAlignment="Center"
              d:DesignHeight="450" d:DesignWidth="800">
              d:DesignHeight="450" d:DesignWidth="800">
 
 
-    <visuals:SurfaceControl
+    <visuals:TextureControl
         x:Name="mainImage"
         x:Name="mainImage"
         Focusable="True"
         Focusable="True"
-        Surface="{Binding TargetBitmap, ElementName=uc}"
+        Texture="{Binding TargetBitmap, ElementName=uc}"
         Stretch="Uniform"
         Stretch="Uniform"
         SizeChanged="OnImageSizeChanged">
         SizeChanged="OnImageSizeChanged">
         <ui1:RenderOptionsBindable.BitmapInterpolationMode>
         <ui1:RenderOptionsBindable.BitmapInterpolationMode>
@@ -26,5 +26,5 @@
                 <Binding ElementName="mainImage" Path="Bounds.Width"/>
                 <Binding ElementName="mainImage" Path="Bounds.Width"/>
             </MultiBinding>
             </MultiBinding>
         </ui1:RenderOptionsBindable.BitmapInterpolationMode>
         </ui1:RenderOptionsBindable.BitmapInterpolationMode>
-    </visuals:SurfaceControl>
+    </visuals:TextureControl>
 </UserControl>
 </UserControl>

+ 9 - 11
src/PixiEditor/Views/Main/ViewportControls/FixedViewport.axaml.cs

@@ -1,14 +1,12 @@
-using System.Collections.Generic;
-using System.ComponentModel;
+using System.ComponentModel;
 using Avalonia;
 using Avalonia;
 using Avalonia.Controls;
 using Avalonia.Controls;
 using Avalonia.Data;
 using Avalonia.Data;
 using Avalonia.Interactivity;
 using Avalonia.Interactivity;
-using Avalonia.Media.Imaging;
-using ChunkyImageLib;
+using Avalonia.Media;
+using Avalonia.Threading;
 using ChunkyImageLib.DataHolders;
 using ChunkyImageLib.DataHolders;
 using PixiEditor.DrawingApi.Core;
 using PixiEditor.DrawingApi.Core;
-using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.Models.DocumentModels;
 using PixiEditor.Models.DocumentModels;
 using PixiEditor.Models.Position;
 using PixiEditor.Models.Position;
 using PixiEditor.Numerics;
 using PixiEditor.Numerics;
@@ -21,8 +19,8 @@ internal partial class FixedViewport : UserControl, INotifyPropertyChanged
     public static readonly StyledProperty<DocumentViewModel> DocumentProperty =
     public static readonly StyledProperty<DocumentViewModel> DocumentProperty =
         AvaloniaProperty.Register<FixedViewport, DocumentViewModel>(nameof(Document), null);
         AvaloniaProperty.Register<FixedViewport, DocumentViewModel>(nameof(Document), null);
 
 
-    private static readonly StyledProperty<Dictionary<ChunkResolution, WriteableBitmap>> BitmapsProperty =
-        AvaloniaProperty.Register<FixedViewport, Dictionary<ChunkResolution, WriteableBitmap>>(nameof(Bitmaps), null);
+    private static readonly StyledProperty<Dictionary<ChunkResolution, Texture>> BitmapsProperty =
+        AvaloniaProperty.Register<FixedViewport, Dictionary<ChunkResolution, Texture>>(nameof(Bitmaps), null);
 
 
     public static readonly StyledProperty<bool> DelayedProperty =
     public static readonly StyledProperty<bool> DelayedProperty =
         AvaloniaProperty.Register<FixedViewport, bool>(nameof(Delayed), false);
         AvaloniaProperty.Register<FixedViewport, bool>(nameof(Delayed), false);
@@ -35,7 +33,7 @@ internal partial class FixedViewport : UserControl, INotifyPropertyChanged
         set => SetValue(DelayedProperty, value);
         set => SetValue(DelayedProperty, value);
     }
     }
 
 
-    public Dictionary<ChunkResolution, WriteableBitmap>? Bitmaps
+    public Dictionary<ChunkResolution, Texture>? Bitmaps
     {
     {
         get => GetValue(BitmapsProperty);
         get => GetValue(BitmapsProperty);
         set => SetValue(BitmapsProperty, value);
         set => SetValue(BitmapsProperty, value);
@@ -47,11 +45,11 @@ internal partial class FixedViewport : UserControl, INotifyPropertyChanged
         set => SetValue(DocumentProperty, value);
         set => SetValue(DocumentProperty, value);
     }
     }
 
 
-    public Surface? TargetBitmap
+    public Texture? TargetBitmap
     {
     {
         get
         get
         {
         {
-            if (Document?.Surfaces.TryGetValue(CalculateResolution(), out Surface? value) == true)
+            if (Document?.Surfaces.TryGetValue(CalculateResolution(), out Texture? value) == true)
                 return value;
                 return value;
             return null;
             return null;
         }
         }
@@ -146,7 +144,7 @@ internal partial class FixedViewport : UserControl, INotifyPropertyChanged
         Document?.Operations.AddOrUpdateViewport(GetLocation());
         Document?.Operations.AddOrUpdateViewport(GetLocation());
     }
     }
 
 
-    private static void OnBitmapsChange(AvaloniaPropertyChangedEventArgs<Dictionary<ChunkResolution, WriteableBitmap>> args)
+    private static void OnBitmapsChange(AvaloniaPropertyChangedEventArgs<Dictionary<ChunkResolution, Texture>> args)
     {
     {
         FixedViewport? viewport = (FixedViewport)args.Sender;
         FixedViewport? viewport = (FixedViewport)args.Sender;
         viewport.PropertyChanged?.Invoke(viewport, new(nameof(TargetBitmap)));
         viewport.PropertyChanged?.Invoke(viewport, new(nameof(TargetBitmap)));

+ 2 - 2
src/PixiEditor/Views/Main/ViewportControls/Viewport.axaml.cs

@@ -267,11 +267,11 @@ internal partial class Viewport : UserControl, INotifyPropertyChanged
         }
         }
     }
     }
 
 
-    public Surface? TargetBitmap
+    public Texture? TargetBitmap
     {
     {
         get
         get
         {
         {
-            return Document?.Surfaces.TryGetValue(CalculateResolution(), out Surface? value) == true ? value : null;
+            return Document?.Surfaces.TryGetValue(CalculateResolution(), out Texture? value) == true ? value : null;
         }
         }
     }
     }
 
 

+ 27 - 10
src/PixiEditor/Views/Rendering/Scene.cs

@@ -13,8 +13,10 @@ using Avalonia.Threading;
 using ChunkyImageLib;
 using ChunkyImageLib;
 using ChunkyImageLib.DataHolders;
 using ChunkyImageLib.DataHolders;
 using PixiEditor.DrawingApi.Core;
 using PixiEditor.DrawingApi.Core;
+using PixiEditor.DrawingApi.Core.Bridge;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.DrawingApi.Skia;
 using PixiEditor.DrawingApi.Skia;
+using PixiEditor.DrawingApi.Skia.Extensions;
 using PixiEditor.Extensions.UI.Overlays;
 using PixiEditor.Extensions.UI.Overlays;
 using PixiEditor.Helpers;
 using PixiEditor.Helpers;
 using PixiEditor.Helpers.Converters;
 using PixiEditor.Helpers.Converters;
@@ -32,7 +34,7 @@ namespace PixiEditor.Views.Rendering;
 
 
 internal class Scene : Zoombox.Zoombox, ICustomHitTest
 internal class Scene : Zoombox.Zoombox, ICustomHitTest
 {
 {
-    public static readonly StyledProperty<Surface> SurfaceProperty = AvaloniaProperty.Register<SurfaceControl, Surface>(
+    public static readonly StyledProperty<Texture> SurfaceProperty = AvaloniaProperty.Register<SurfaceControl, Texture>(
         nameof(Surface));
         nameof(Surface));
 
 
     public static readonly StyledProperty<DocumentViewModel> DocumentProperty =
     public static readonly StyledProperty<DocumentViewModel> DocumentProperty =
@@ -86,7 +88,7 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
         set => SetValue(DocumentProperty, value);
         set => SetValue(DocumentProperty, value);
     }
     }
 
 
-    public Surface Surface
+    public Texture Surface
     {
     {
         get => GetValue(SurfaceProperty);
         get => GetValue(SurfaceProperty);
         set => SetValue(SurfaceProperty, value);
         set => SetValue(SurfaceProperty, value);
@@ -145,6 +147,7 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
         RectD dirtyBounds = new RectD(0, 0, Document.Width / resolutionScale, Document.Height / resolutionScale);
         RectD dirtyBounds = new RectD(0, 0, Document.Width / resolutionScale, Document.Height / resolutionScale);
         Rect dirtyRect = new Rect(0, 0, Document.Width / resolutionScale, Document.Height / resolutionScale);
         Rect dirtyRect = new Rect(0, 0, Document.Width / resolutionScale, Document.Height / resolutionScale);
 
 
+        Surface.Surface.Flush();
         using var operation = new DrawSceneOperation(Surface, Document, CanvasPos, Scale * resolutionScale, angle,
         using var operation = new DrawSceneOperation(Surface, Document, CanvasPos, Scale * resolutionScale, angle,
             FlipX, FlipY,
             FlipX, FlipY,
             dirtyRect,
             dirtyRect,
@@ -185,9 +188,9 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
                 }
                 }
 
 
                 overlay.ZoomScale = Scale;
                 overlay.ZoomScale = Scale;
-                
-                if(!overlay.CanRender()) continue;
-                
+
+                if (!overlay.CanRender()) continue;
+
                 overlay.RenderOverlay(context, dirtyBounds);
                 overlay.RenderOverlay(context, dirtyBounds);
                 Cursor = overlay.Cursor ?? DefaultCursor;
                 Cursor = overlay.Cursor ?? DefaultCursor;
             }
             }
@@ -453,7 +456,7 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
 
 
     private static void SurfaceChanged(Scene scene, AvaloniaPropertyChangedEventArgs e)
     private static void SurfaceChanged(Scene scene, AvaloniaPropertyChangedEventArgs e)
     {
     {
-        if (e.NewValue is Surface surface)
+        if (e.NewValue is Texture surface)
         {
         {
             scene.ContentDimensions = surface.Size;
             scene.ContentDimensions = surface.Size;
         }
         }
@@ -475,7 +478,7 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
 
 
 internal class DrawSceneOperation : SkiaDrawOperation
 internal class DrawSceneOperation : SkiaDrawOperation
 {
 {
-    public Surface Surface { get; set; }
+    public Texture Surface { get; set; }
     public DocumentViewModel Document { get; set; }
     public DocumentViewModel Document { get; set; }
     public VecD ContentPosition { get; set; }
     public VecD ContentPosition { get; set; }
     public double Scale { get; set; }
     public double Scale { get; set; }
@@ -489,7 +492,9 @@ internal class DrawSceneOperation : SkiaDrawOperation
 
 
     private SKPaint _paint = new SKPaint();
     private SKPaint _paint = new SKPaint();
 
 
-    public DrawSceneOperation(Surface surface, DocumentViewModel document, VecD contentPosition, double scale,
+    private bool hardwareAccelerationAvailable = DrawingBackendApi.Current.IsHardwareAccelerated;
+
+    public DrawSceneOperation(Texture surface, DocumentViewModel document, VecD contentPosition, double scale,
         double angle, bool flipX, bool flipY, Rect dirtyBounds, Rect viewportBounds, double opacity,
         double angle, bool flipX, bool flipY, Rect dirtyBounds, Rect viewportBounds, double opacity,
         ColorMatrix colorMatrix) : base(dirtyBounds)
         ColorMatrix colorMatrix) : base(dirtyBounds)
     {
     {
@@ -520,13 +525,25 @@ internal class DrawSceneOperation : SkiaDrawOperation
             return;
             return;
         }
         }
 
 
-        using Image snapshot = Surface.DrawingSurface.Snapshot(SurfaceRectToRender);
+        using var ctx = DrawingBackendApi.Current.RenderOnDifferentGrContext(lease.GrContext);
+
 
 
         var matrixValues = new float[ColorMatrix.Width * ColorMatrix.Height];
         var matrixValues = new float[ColorMatrix.Width * ColorMatrix.Height];
         ColorMatrix.TryGetMembers(matrixValues);
         ColorMatrix.TryGetMembers(matrixValues);
 
 
         _paint.ColorFilter = SKColorFilter.CreateColorMatrix(matrixValues);
         _paint.ColorFilter = SKColorFilter.CreateColorMatrix(matrixValues);
-        canvas.DrawImage((SKImage)snapshot.Native, SurfaceRectToRender.X, SurfaceRectToRender.Y, _paint);
+
+        if (!hardwareAccelerationAvailable)
+        {
+            // snapshotting wanted region on CPU is faster than rendering whole surface on CPU,
+            // but slower than rendering whole surface on GPU
+            using Image snapshot = Surface.Surface.Snapshot(SurfaceRectToRender);
+            canvas.DrawImage((SKImage)snapshot.Native, SurfaceRectToRender.X, SurfaceRectToRender.Y, _paint);
+        }
+        else
+        {
+            canvas.DrawSurface(Surface.Surface.Native as SKSurface, 0, 0, _paint);
+        }
 
 
         canvas.Restore();
         canvas.Restore();
     }
     }

+ 1 - 2
src/PixiEditor/Views/Visuals/TextureControl.cs

@@ -108,9 +108,8 @@ internal class DrawTextureOperation : SkiaDrawOperation
     public VecD TargetSize { get; }
     public VecD TargetSize { get; }
     public Texture? Texture { get; }
     public Texture? Texture { get; }
     public Paint? Paint { get; }
     public Paint? Paint { get; }
-    
 
 
-    public DrawTextureOperation(Rect dirtyBounds, Stretch stretch, Texture? texture, Paint paint = null) :
+    public DrawTextureOperation(Rect dirtyBounds, Stretch stretch, Texture texture, Paint paint = null) :
         base(dirtyBounds)
         base(dirtyBounds)
     {
     {
         Stretch = stretch;
         Stretch = stretch;

+ 25 - 0
src/PixiEditor/Views/Visuals/TextureImage.cs

@@ -0,0 +1,25 @@
+using Avalonia;
+using Avalonia.Media;
+using ChunkyImageLib;
+using PixiEditor.DrawingApi.Core;
+
+namespace PixiEditor.Views.Visuals;
+
+public class TextureImage : IImage
+{
+    public Texture Texture { get; set; }
+    public Stretch Stretch { get; set; } = Stretch.Uniform;
+
+    public Size Size { get; }
+
+    public TextureImage(Texture texture)
+    {
+        Texture = texture;
+        Size = new Size(texture.Size.X, texture.Size.Y);
+    }
+
+    public void Draw(DrawingContext context, Rect sourceRect, Rect destRect)
+    {
+        context.Custom(new DrawTextureOperation(destRect, Stretch, Texture));
+    }
+}