Browse Source

Basic scene painting works

flabbet 10 months ago
parent
commit
b3229dfee4

+ 1 - 1
src/Drawie

@@ -1 +1 @@
-Subproject commit 7c05ce2a02f0190d383e5a757d27ff47556ad71f
+Subproject commit 9dac8f6ce47df56f58e6e6e6d333200af38a4931

BIN
src/PixiEditor.Extensions.Sdk/build/PixiEditor.Api.CGlueMSBuild.dll


BIN
src/PixiEditor.Extensions.Sdk/build/PixiEditor.Extensions.MSPackageBuilder.dll


+ 4 - 3
src/PixiEditor/Views/Overlays/ReferenceLayerOverlay.cs

@@ -97,10 +97,11 @@ internal class ReferenceLayerOverlay : Overlay
             referenceBitmap.DrawingSurface.Flush();
             referenceBitmap.DrawingSurface.Flush();
             overlayPaint.Color = new Color(255, 255, 255, (byte)(opacity * 255)); 
             overlayPaint.Color = new Color(255, 255, 255, (byte)(opacity * 255)); 
             
             
-            DrawTextureOperation drawOperation =
-                new DrawTextureOperation(dirtyRect, Stretch.None, referenceBitmap, overlayPaint);
+            // TODO: Implement this
+            /*DrawTextureOperation drawOperation =
+                new DrawTextureOperation(dirtyRect, Stretch.None, referenceBitmap, overlayPaint);*/
 
 
-            context.Custom(drawOperation);
+            //context.Custom(drawOperation);
 
 
             matrix.Dispose();
             matrix.Dispose();
 
 

+ 199 - 26
src/PixiEditor/Views/Rendering/Scene.cs

@@ -3,12 +3,15 @@ using System.Collections.Specialized;
 using Avalonia;
 using Avalonia;
 using Avalonia.Animation;
 using Avalonia.Animation;
 using Avalonia.Input;
 using Avalonia.Input;
+using Avalonia.Interactivity;
 using Avalonia.Media;
 using Avalonia.Media;
 using Avalonia.Media.Imaging;
 using Avalonia.Media.Imaging;
 using Avalonia.Rendering;
 using Avalonia.Rendering;
+using Avalonia.Rendering.Composition;
 using Avalonia.Rendering.SceneGraph;
 using Avalonia.Rendering.SceneGraph;
 using Avalonia.Skia;
 using Avalonia.Skia;
 using Avalonia.Threading;
 using Avalonia.Threading;
+using Avalonia.VisualTree;
 using ChunkyImageLib.DataHolders;
 using ChunkyImageLib.DataHolders;
 using PixiEditor.ChangeableDocument.Rendering;
 using PixiEditor.ChangeableDocument.Rendering;
 using Drawie.Backend.Core;
 using Drawie.Backend.Core;
@@ -17,6 +20,8 @@ using Drawie.Backend.Core.Numerics;
 using Drawie.Backend.Core.Shaders;
 using Drawie.Backend.Core.Shaders;
 using Drawie.Backend.Core.Surfaces;
 using Drawie.Backend.Core.Surfaces;
 using Drawie.Backend.Core.Surfaces.PaintImpl;
 using Drawie.Backend.Core.Surfaces.PaintImpl;
+using Drawie.Interop.VulkanAvalonia;
+using Drawie.Interop.VulkanAvalonia.Vulkan;
 using PixiEditor.Extensions.UI.Overlays;
 using PixiEditor.Extensions.UI.Overlays;
 using PixiEditor.Helpers;
 using PixiEditor.Helpers;
 using PixiEditor.Helpers.Converters;
 using PixiEditor.Helpers.Converters;
@@ -111,9 +116,22 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
 
 
     private double sceneOpacity = 1;
     private double sceneOpacity = 1;
 
 
-    private Texture renderTexture;
     private Paint checkerPaint;
     private Paint checkerPaint;
 
 
+    private CompositionSurfaceVisual surfaceVisual;
+    private Compositor compositor;
+
+    private readonly Action update;
+    private bool updateQueued;
+
+    private CompositionDrawingSurface? surface;
+
+    private string info = string.Empty;
+    private bool initialized = false;
+    private VulkanResources resources;
+    private DrawingSurface renderSurface;
+    private PixelSize lastSize = PixelSize.Empty;
+
     static Scene()
     static Scene()
     {
     {
         AffectsRender<Scene>(BoundsProperty, WidthProperty, HeightProperty, ScaleProperty, AngleRadiansProperty,
         AffectsRender<Scene>(BoundsProperty, WidthProperty, HeightProperty, ScaleProperty, AngleRadiansProperty,
@@ -140,6 +158,9 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
         {
         {
             new DoubleTransition { Property = OpacityProperty, Duration = new TimeSpan(0, 0, 0, 0, 100) }
             new DoubleTransition { Property = OpacityProperty, Duration = new TimeSpan(0, 0, 0, 0, 100) }
         };
         };
+
+        update = UpdateFrame;
+        QueueNextFrame();
     }
     }
 
 
     private ChunkResolution CalculateResolution()
     private ChunkResolution CalculateResolution()
@@ -155,17 +176,75 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
         };
         };
     }
     }
 
 
+    protected override void OnLoaded(RoutedEventArgs e)
+    {
+        base.OnLoaded(e);
+        InitializeComposition();
+    }
+
+    protected override void OnDetachedFromVisualTree(VisualTreeAttachmentEventArgs e)
+    {
+        if (initialized)
+        {
+            FreeGraphicsResources();
+        }
+
+        initialized = false;
+        base.OnDetachedFromVisualTree(e);
+    }
+
+    private async void InitializeComposition()
+    {
+        try
+        {
+            var selfVisual = ElementComposition.GetElementVisual(this);
+            compositor = selfVisual.Compositor;
+
+            surface = compositor.CreateDrawingSurface();
+            surfaceVisual = compositor.CreateSurfaceVisual();
+
+            surfaceVisual.Size = new Vector(Bounds.Width, Bounds.Height);
+
+            surfaceVisual.Surface = surface;
+            ElementComposition.SetElementChildVisual(this, surfaceVisual);
+            var (result, initInfo) = await DoInitialize(compositor, surface);
+            info = initInfo;
+
+            initialized = result;
+            QueueNextFrame();
+        }
+        catch (Exception e)
+        {
+            info = e.Message;
+            throw;
+        }
+    }
+
+    public void Draw(DrawingSurface renderTexture)
+    {
+        renderTexture.Canvas.Save();
+        var matrix = CalculateTransformMatrix();
+
+        renderTexture.Canvas.SetMatrix(matrix.ToSKMatrix().ToMatrix3X3());
+
+        RectD dirtyBounds = new RectD(0, 0, Document.Width, Document.Height);
+        RenderScene(dirtyBounds);
+
+        renderTexture.Canvas.Restore();
+        QueueNextFrame();
+    }
+
     public override void Render(DrawingContext context)
     public override void Render(DrawingContext context)
     {
     {
         if (Document == null || SceneRenderer == null) return;
         if (Document == null || SceneRenderer == null) return;
 
 
         int width = (int)Math.Ceiling(Bounds.Width);
         int width = (int)Math.Ceiling(Bounds.Width);
         int height = (int)Math.Ceiling(Bounds.Height);
         int height = (int)Math.Ceiling(Bounds.Height);
-        if (renderTexture == null || renderTexture.Size.X != width || renderTexture.Size.Y != height)
+        /*if (renderTexture == null || renderTexture.Size.X != width || renderTexture.Size.Y != height)
         {
         {
             renderTexture?.Dispose();
             renderTexture?.Dispose();
             renderTexture = new Texture(new VecI(width, height));
             renderTexture = new Texture(new VecI(width, height));
-        }
+        }*/
 
 
         float angle = (float)MathUtil.RadiansToDegrees(AngleRadians);
         float angle = (float)MathUtil.RadiansToDegrees(AngleRadians);
 
 
@@ -175,7 +254,7 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
 
 
         SceneRenderer.Resolution = CalculateResolution();
         SceneRenderer.Resolution = CalculateResolution();
 
 
-        using var operation = new DrawSceneOperation(SceneRenderer.RenderScene, Document, CanvasPos,
+        /*using var operation = new DrawSceneOperation(SceneRenderer.RenderScene, Document, CanvasPos,
             Scale * resolutionScale,
             Scale * resolutionScale,
             resolutionScale,
             resolutionScale,
             sceneOpacity,
             sceneOpacity,
@@ -183,7 +262,7 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
             FlipX, FlipY,
             FlipX, FlipY,
             Bounds,
             Bounds,
             Bounds,
             Bounds,
-            renderTexture);
+            renderTexture);*/
 
 
         var matrix = CalculateTransformMatrix();
         var matrix = CalculateTransformMatrix();
         context.PushRenderOptions(new RenderOptions { BitmapInterpolationMode = BitmapInterpolationMode.None });
         context.PushRenderOptions(new RenderOptions { BitmapInterpolationMode = BitmapInterpolationMode.None });
@@ -195,28 +274,15 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
 
 
         pushedMatrix.Dispose();
         pushedMatrix.Dispose();
 
 
-        renderTexture.DrawingSurface.Canvas.Clear();
-        renderTexture.DrawingSurface.Canvas.Save();
-
-        renderTexture.DrawingSurface.Canvas.SetMatrix(matrix.ToSKMatrix().ToMatrix3X3());
-
-        RenderScene(dirtyBounds);
-
-        renderTexture.DrawingSurface.Flush();
-
-        context.Custom(operation);
-
-        renderTexture.DrawingSurface.Canvas.Restore();
-
         context.PushTransform(matrix);
         context.PushTransform(matrix);
 
 
         DrawOverlays(context, dirtyBounds, OverlayRenderSorting.Foreground);
         DrawOverlays(context, dirtyBounds, OverlayRenderSorting.Foreground);
     }
     }
 
 
-    private void RenderScene(RectD dirtyBounds)
+    private void RenderScene(RectD bounds)
     {
     {
-        DrawCheckerboard(dirtyBounds);
-        RenderGraph(renderTexture);
+        DrawCheckerboard(bounds);
+        RenderGraph(renderSurface);
     }
     }
 
 
     private void DrawCheckerboard(RectD dirtyBounds)
     private void DrawCheckerboard(RectD dirtyBounds)
@@ -234,14 +300,13 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
                 Matrix3X3.CreateScale(checkerScale, checkerScale)),
                 Matrix3X3.CreateScale(checkerScale, checkerScale)),
             FilterQuality = FilterQuality.None
             FilterQuality = FilterQuality.None
         };
         };
-        
-        renderTexture.DrawingSurface.Canvas.DrawRect(operationSurfaceRectToRender, checkerPaint);
+
+        renderSurface.Canvas.DrawRect(operationSurfaceRectToRender, checkerPaint);
     }
     }
 
 
-    private void RenderGraph(Texture targetTexture)
+    private void RenderGraph(DrawingSurface target)
     {
     {
-        DrawingSurface surface = targetTexture.DrawingSurface;
-        RenderContext context = new(surface, SceneRenderer.DocumentViewModel.AnimationHandler.ActiveFrameTime,
+        RenderContext context = new(target, SceneRenderer.DocumentViewModel.AnimationHandler.ActiveFrameTime,
             SceneRenderer.Resolution, SceneRenderer.Document.Size);
             SceneRenderer.Resolution, SceneRenderer.Document.Size);
         SceneRenderer.Document.NodeGraph.Execute(context);
         SceneRenderer.Document.NodeGraph.Execute(context);
     }
     }
@@ -489,9 +554,117 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
         }
         }
     }
     }
 
 
+    #region Interop
+
+    void UpdateFrame()
+    {
+        updateQueued = false;
+        var root = this.GetVisualRoot();
+        if (root == null)
+        {
+            return;
+        }
+
+        surfaceVisual.Size = new Vector(Bounds.Width, Bounds.Height);
+
+        if (double.IsNaN(surfaceVisual.Size.X) || double.IsNaN(surfaceVisual.Size.Y))
+        {
+            return;
+        }
+
+        var size = PixelSize.FromSize(Bounds.Size, root.RenderScaling);
+        RenderFrame(size);
+    }
+
+    public void QueueNextFrame()
+    {
+        if (initialized && !updateQueued && compositor != null)
+        {
+            updateQueued = true;
+            compositor.RequestCompositionUpdate(update);
+        }
+    }
+
+    protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
+    {
+        if (change.Property == BoundsProperty)
+        {
+            QueueNextFrame();
+        }
+
+        base.OnPropertyChanged(change);
+    }
+
+    private async Task<(bool success, string info)> DoInitialize(Compositor compositor,
+        CompositionDrawingSurface surface)
+    {
+        var interop = await compositor.TryGetCompositionGpuInterop();
+        if (interop == null)
+        {
+            return (false, "Composition interop not available");
+        }
+
+        return InitializeGraphicsResources(compositor, surface, interop);
+    }
+
+    protected (bool success, string info) InitializeGraphicsResources(Compositor targetCompositor,
+        CompositionDrawingSurface compositionDrawingSurface, ICompositionGpuInterop interop)
+    {
+        resources = new VulkanResources(
+            DrawieInterop.VulkanInteropContext,
+            new VulkanSwapchain(DrawieInterop.VulkanInteropContext, interop, compositionDrawingSurface),
+            new VulkanContent(DrawieInterop.VulkanInteropContext));
+
+        return (true, string.Empty);
+    }
+
+    protected void FreeGraphicsResources()
+    {
+        resources?.DisposeAsync();
+        resources = null;
+    }
+
+    protected void RenderFrame(PixelSize size)
+    {
+        if (resources != null)
+        {
+            if (size.Width == 0 || size.Height == 0)
+            {
+                return;
+            }
+
+            if (renderSurface == null || lastSize != size)
+            {
+                resources.Content.CreateTemporalObjects(size);
+
+                VecI sizeVec = new VecI(size.Width, size.Height);
+
+                renderSurface?.Dispose();
+
+                renderSurface =
+                    DrawingBackendApi.Current.CreateRenderSurface(sizeVec,
+                        resources.Content.texture, SurfaceOrigin.BottomLeft);
+
+                lastSize = size;
+            }
+
+            using (resources.Swapchain.BeginDraw(size, out var image))
+            {
+                renderSurface.Canvas.Clear();
+                Draw(renderSurface);
+                renderSurface.Flush();
+
+                resources.Content.Render(image);
+            }
+        }
+    }
+
+    #endregion
+
     private void QueueRender()
     private void QueueRender()
     {
     {
         Dispatcher.UIThread.Post(InvalidateVisual, DispatcherPriority.Render);
         Dispatcher.UIThread.Post(InvalidateVisual, DispatcherPriority.Render);
+        QueueNextFrame();
     }
     }
 
 
     private static void FadeOutChanged(Scene scene, AvaloniaPropertyChangedEventArgs e)
     private static void FadeOutChanged(Scene scene, AvaloniaPropertyChangedEventArgs e)

+ 12 - 41
src/PixiEditor/Views/Visuals/PreviewPainterControl.cs

@@ -5,12 +5,13 @@ using Avalonia.Rendering.SceneGraph;
 using Avalonia.Skia;
 using Avalonia.Skia;
 using ChunkyImageLib.DataHolders;
 using ChunkyImageLib.DataHolders;
 using Drawie.Backend.Core.Surfaces;
 using Drawie.Backend.Core.Surfaces;
+using Drawie.Interop.VulkanAvalonia.Controls;
 using PixiEditor.Models.Rendering;
 using PixiEditor.Models.Rendering;
 using Drawie.Numerics;
 using Drawie.Numerics;
 
 
 namespace PixiEditor.Views.Visuals;
 namespace PixiEditor.Views.Visuals;
 
 
-public class PreviewPainterControl : Control
+public class PreviewPainterControl : DrawieControl
 {
 {
     public static readonly StyledProperty<int> FrameToRenderProperty =
     public static readonly StyledProperty<int> FrameToRenderProperty =
         AvaloniaProperty.Register<PreviewPainterControl, int>("FrameToRender");
         AvaloniaProperty.Register<PreviewPainterControl, int>("FrameToRender");
@@ -36,16 +37,6 @@ public class PreviewPainterControl : Control
         PreviewPainterProperty.Changed.Subscribe(PainterChanged);
         PreviewPainterProperty.Changed.Subscribe(PainterChanged);
     }
     }
 
 
-    public override void Render(DrawingContext context)
-    {
-        if (PreviewPainter == null)
-        {
-            return;
-        }
-
-        using var renderOperation = new DrawPreviewOperation(Bounds, PreviewPainter, FrameToRender);
-        context.Custom(renderOperation);
-    }
 
 
     private void PainterChanged(AvaloniaPropertyChangedEventArgs<PreviewPainter> args)
     private void PainterChanged(AvaloniaPropertyChangedEventArgs<PreviewPainter> args)
     {
     {
@@ -62,47 +53,32 @@ public class PreviewPainterControl : Control
 
 
     private void OnPainterRenderRequest()
     private void OnPainterRenderRequest()
     {
     {
-        InvalidateVisual();
-    }
-}
-
-internal class DrawPreviewOperation : SkiaDrawOperation
-{
-    public PreviewPainter PreviewPainter { get; }
-    private int frame;
-
-    public DrawPreviewOperation(Rect dirtyBounds, PreviewPainter previewPainter, int frameToRender) : base(dirtyBounds)
-    {
-        PreviewPainter = previewPainter;
-        frame = frameToRender;
+        QueueNextFrame();
     }
     }
 
 
-    public override void Render(ISkiaSharpApiLease lease)
+    public override void Draw(DrawingSurface surface)
     {
     {
-        RectD? previewBounds = PreviewPainter.PreviewRenderable.GetPreviewBounds(frame, PreviewPainter.ElementToRenderName);
+        RectD? previewBounds =
+            PreviewPainter.PreviewRenderable.GetPreviewBounds(FrameToRender, PreviewPainter.ElementToRenderName);
         if (PreviewPainter == null)
         if (PreviewPainter == null)
         {
         {
             return;
             return;
         }
         }
 
 
-        DrawingSurface target = DrawingSurface.FromNative(lease.SkSurface);
-
-        float x = (float)(previewBounds?.Width ?? 0); 
+        float x = (float)(previewBounds?.Width ?? 0);
         float y = (float)(previewBounds?.Height ?? 0);
         float y = (float)(previewBounds?.Height ?? 0);
 
 
-        target.Canvas.Save();
+        surface.Canvas.Save();
 
 
         if (previewBounds != null)
         if (previewBounds != null)
         {
         {
-            UniformScale(x, y, target, previewBounds.Value);
+            UniformScale(x, y, surface, previewBounds.Value);
         }
         }
 
 
         // TODO: Implement ChunkResolution and frame
         // TODO: Implement ChunkResolution and frame
-        PreviewPainter.Paint(target, ChunkResolution.Full, frame);
+        PreviewPainter.Paint(surface, ChunkResolution.Full, FrameToRender);
 
 
-        target.Canvas.Restore();
-
-        DrawingSurface.Unmanage(target);
+        surface.Canvas.Restore();
     }
     }
 
 
     private void UniformScale(float x, float y, DrawingSurface target, RectD previewBounds)
     private void UniformScale(float x, float y, DrawingSurface target, RectD previewBounds)
@@ -111,15 +87,10 @@ internal class DrawPreviewOperation : SkiaDrawOperation
         float scaleY = (float)Bounds.Height / y;
         float scaleY = (float)Bounds.Height / y;
         var scale = Math.Min(scaleX, scaleY);
         var scale = Math.Min(scaleX, scaleY);
         float dX = (float)Bounds.Width / 2 / scale - x / 2;
         float dX = (float)Bounds.Width / 2 / scale - x / 2;
-        dX -= (float)previewBounds.X; 
+        dX -= (float)previewBounds.X;
         float dY = (float)Bounds.Height / 2 / scale - y / 2;
         float dY = (float)Bounds.Height / 2 / scale - y / 2;
         dY -= (float)previewBounds.Y;
         dY -= (float)previewBounds.Y;
         target.Canvas.Scale(scale, scale);
         target.Canvas.Scale(scale, scale);
         target.Canvas.Translate(dX, dY);
         target.Canvas.Translate(dX, dY);
     }
     }
-
-    public override bool Equals(ICustomDrawOperation? other)
-    {
-        return other is DrawPreviewOperation operation && operation.PreviewPainter == PreviewPainter;
-    }
 }
 }

+ 3 - 2
src/PixiEditor/Views/Visuals/PreviewPainterImage.cs

@@ -24,7 +24,8 @@ public class PreviewPainterImage : IImage
         if (PreviewPainter.PreviewRenderable.GetPreviewBounds(FrameToRender) == null) return;
         if (PreviewPainter.PreviewRenderable.GetPreviewBounds(FrameToRender) == null) return;
         
         
         context.PushClip(destRect);
         context.PushClip(destRect);
-        using DrawPreviewOperation drawPreviewOperation = new DrawPreviewOperation(destRect, PreviewPainter, FrameToRender); 
-        context.Custom(drawPreviewOperation);
+        //TODO: Implement this
+        //using DrawPreviewOperation drawPreviewOperation = new DrawPreviewOperation(destRect, PreviewPainter, FrameToRender); 
+        //context.Custom(drawPreviewOperation);
     }
     }
 }
 }

+ 4 - 150
src/PixiEditor/Views/Visuals/TextureControl.cs

@@ -6,33 +6,18 @@ using Avalonia.Skia;
 using Avalonia.Threading;
 using Avalonia.Threading;
 using Drawie.Backend.Core;
 using Drawie.Backend.Core;
 using Drawie.Backend.Core.Bridge;
 using Drawie.Backend.Core.Bridge;
+using Drawie.Backend.Core.Surfaces;
 using Drawie.Backend.Core.Surfaces.PaintImpl;
 using Drawie.Backend.Core.Surfaces.PaintImpl;
+using Drawie.Interop.VulkanAvalonia.Controls;
 using Drawie.Numerics;
 using Drawie.Numerics;
 
 
 namespace PixiEditor.Views.Visuals;
 namespace PixiEditor.Views.Visuals;
 
 
-public class TextureControl : Control
+public class TextureControl : DrawieTextureControl
 {
 {
-    public static readonly StyledProperty<Texture> TextureProperty = AvaloniaProperty.Register<TextureControl, Texture>(
-        nameof(Texture));
-
-    public static readonly StyledProperty<Stretch> StretchProperty = AvaloniaProperty.Register<TextureControl, Stretch>(
-        nameof(Stretch), Stretch.Uniform);
-
     public static readonly StyledProperty<IBrush> BackgroundProperty = AvaloniaProperty.Register<TextureControl, IBrush>
     public static readonly StyledProperty<IBrush> BackgroundProperty = AvaloniaProperty.Register<TextureControl, IBrush>
         (nameof(Background));
         (nameof(Background));
 
 
-    public Stretch Stretch
-    {
-        get => GetValue(StretchProperty);
-        set => SetValue(StretchProperty, value);
-    }
-
-    public Texture Texture
-    {
-        get => GetValue(TextureProperty);
-        set => SetValue(TextureProperty, value);
-    }
 
 
     public IBrush Background
     public IBrush Background
     {
     {
@@ -40,58 +25,12 @@ public class TextureControl : Control
         set { SetValue(BackgroundProperty, value); }
         set { SetValue(BackgroundProperty, value); }
     }
     }
 
 
-    static TextureControl()
-    {
-        AffectsRender<TextureControl>(TextureProperty, StretchProperty);
-    }
-
     public TextureControl()
     public TextureControl()
     {
     {
         ClipToBounds = true;
         ClipToBounds = true;
         TextureProperty.Changed.Subscribe(OnTextureChanged);
         TextureProperty.Changed.Subscribe(OnTextureChanged);
     }
     }
 
 
-    /// <summary>
-    /// Measures the control.
-    /// </summary>
-    /// <param name="availableSize">The available size.</param>
-    /// <returns>The desired size of the control.</returns>
-    protected override Size MeasureOverride(Size availableSize)
-    {
-        var source = Texture;
-        var result = new Size();
-
-        if (source != null)
-        {
-            result = Stretch.CalculateSize(availableSize, new Size(source.Size.X, source.Size.Y));
-        }
-        else if (Width > 0 && Height > 0)
-        {
-            result = Stretch.CalculateSize(availableSize, new Size(Width, Height));
-        }
-
-        return result;
-    }
-
-    /// <inheritdoc/>
-    protected override Size ArrangeOverride(Size finalSize)
-    {
-        var source = Texture;
-
-        if (source != null)
-        {
-            var sourceSize = source.Size;
-            var result = Stretch.CalculateSize(finalSize, new Size(sourceSize.X, sourceSize.Y));
-            return result;
-        }
-        else
-        {
-            return Stretch.CalculateSize(finalSize, new Size(Width, Height));
-        }
-
-        return new Size();
-    }
-
     public override void Render(DrawingContext context)
     public override void Render(DrawingContext context)
     {
     {
         if (Background != null)
         if (Background != null)
@@ -99,19 +38,7 @@ public class TextureControl : Control
             context.FillRectangle(Background, new Rect(Bounds.Size));
             context.FillRectangle(Background, new Rect(Bounds.Size));
         }
         }
 
 
-        if (Texture == null || Texture.IsDisposed)
-        {
-            return;
-        }
-
-        Texture texture = Texture;
-        texture.DrawingSurface.Flush();
-        ICustomDrawOperation drawOperation = new DrawTextureOperation(
-            new Rect(0, 0, Bounds.Width, Bounds.Height),
-            Stretch,
-            texture);
-
-        context.Custom(drawOperation);
+        base.Render(context);
     }
     }
 
 
     private void OnTextureChanged(AvaloniaPropertyChangedEventArgs<Texture> args)
     private void OnTextureChanged(AvaloniaPropertyChangedEventArgs<Texture> args)
@@ -132,76 +59,3 @@ public class TextureControl : Control
         Dispatcher.UIThread.Post(InvalidateVisual, DispatcherPriority.Render);
         Dispatcher.UIThread.Post(InvalidateVisual, DispatcherPriority.Render);
     }
     }
 }
 }
-
-internal class DrawTextureOperation : SkiaDrawOperation
-{
-    public Stretch Stretch { get; }
-    public VecD TargetSize { get; }
-    public Texture? Texture { get; }
-    public Paint? Paint { get; }
-
-    public DrawTextureOperation(Rect dirtyBounds, Stretch stretch, Texture texture, Paint paint = null) :
-        base(dirtyBounds)
-    {
-        Stretch = stretch;
-        Texture = texture;
-        TargetSize = new VecD(texture.Size.X, texture.Size.Y);
-        Paint = paint;
-    }
-
-    public override void Render(ISkiaSharpApiLease lease)
-    {
-        lock (Texture)
-        {
-            if (Texture == null || Texture.IsDisposed)
-            {
-                return;
-            }
-
-            SKCanvas canvas = lease.SkCanvas;
-
-            //using var ctx = DrawingBackendApi.Current.RenderOnDifferentGrContext(lease.GrContext);
-
-            canvas.Save();
-            ScaleCanvas(canvas);
-            canvas.DrawSurface(Texture.DrawingSurface.Native as SKSurface, 0, 0, Paint?.Native as SKPaint ?? null);
-            canvas.Restore();
-        }
-    }
-
-    private void ScaleCanvas(SKCanvas canvas)
-    {
-        float x = (float)TargetSize.X;
-        float y = (float)TargetSize.Y;
-
-        if (Stretch == Stretch.Fill)
-        {
-            canvas.Scale((float)Bounds.Width / x, (float)Bounds.Height / y);
-        }
-        else if (Stretch == Stretch.Uniform)
-        {
-            float scaleX = (float)Bounds.Width / x;
-            float scaleY = (float)Bounds.Height / y;
-            var scale = Math.Min(scaleX, scaleY);
-            float dX = (float)Bounds.Width / 2 / scale - x / 2;
-            float dY = (float)Bounds.Height / 2 / scale - y / 2;
-            canvas.Scale(scale, scale);
-            canvas.Translate(dX, dY);
-        }
-        else if (Stretch == Stretch.UniformToFill)
-        {
-            float scaleX = (float)Bounds.Width / x;
-            float scaleY = (float)Bounds.Height / y;
-            var scale = Math.Max(scaleX, scaleY);
-            float dX = (float)Bounds.Width / 2 / scale - x / 2;
-            float dY = (float)Bounds.Height / 2 / scale - y / 2;
-            canvas.Scale(scale, scale);
-            canvas.Translate(dX, dY);
-        }
-    }
-
-    public override bool Equals(ICustomDrawOperation? other)
-    {
-        return false;
-    }
-}

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

@@ -21,6 +21,7 @@ public class TextureImage : IImage
     public void Draw(DrawingContext context, Rect sourceRect, Rect destRect)
     public void Draw(DrawingContext context, Rect sourceRect, Rect destRect)
     {
     {
         if(Texture.IsDisposed) return; 
         if(Texture.IsDisposed) return; 
-        context.Custom(new DrawTextureOperation(destRect, Stretch, Texture));
+        // TODO: Implement this
+        //context.Custom(new DrawTextureOperation(destRect, Stretch, Texture));
     }
     }
 }
 }