Krzysztof Krysiński 3 недель назад
Родитель
Сommit
0490853f58

+ 12 - 7
src/ChunkyImageLib/Chunk.cs

@@ -23,7 +23,7 @@ public class Chunk : IDisposable
     /// <summary>
     /// <summary>
     /// The surface of the chunk
     /// The surface of the chunk
     /// </summary>
     /// </summary>
-    public Surface Surface
+    public Texture Surface
     {
     {
         get
         get
         {
         {
@@ -50,7 +50,7 @@ public class Chunk : IDisposable
 
 
     public bool Disposed => returned;
     public bool Disposed => returned;
 
 
-    private Surface internalSurface;
+    private Texture internalSurface;
 
 
     private Chunk(ChunkResolution resolution, ColorSpace colorSpace)
     private Chunk(ChunkResolution resolution, ColorSpace colorSpace)
     {
     {
@@ -59,7 +59,7 @@ public class Chunk : IDisposable
         Resolution = resolution;
         Resolution = resolution;
         ColorSpace = colorSpace;
         ColorSpace = colorSpace;
         PixelSize = new(size, size);
         PixelSize = new(size, size);
-        internalSurface = new Surface(new ImageInfo(size, size, ColorType.RgbaF16, AlphaType.Premul, colorSpace));
+        internalSurface = new Texture(new ImageInfo(size, size, ColorType.RgbaF16, AlphaType.Premul, colorSpace) {GpuBacked = true});
     }
     }
 
 
     /// <summary>
     /// <summary>
@@ -67,6 +67,7 @@ public class Chunk : IDisposable
     /// </summary>
     /// </summary>
     public static Chunk Create(ColorSpace chunkCs, ChunkResolution resolution = ChunkResolution.Full)
     public static Chunk Create(ColorSpace chunkCs, ChunkResolution resolution = ChunkResolution.Full)
     {
     {
+        /*
         var chunk = ChunkPool.Instance.Get(resolution, chunkCs);
         var chunk = ChunkPool.Instance.Get(resolution, chunkCs);
         if (chunk == null || chunk.Disposed)
         if (chunk == null || chunk.Disposed)
         {
         {
@@ -75,7 +76,8 @@ public class Chunk : IDisposable
 
 
         chunk.returned = false;
         chunk.returned = false;
         Interlocked.Increment(ref chunkCounter);
         Interlocked.Increment(ref chunkCounter);
-        return chunk;
+        */
+        return new Chunk(resolution, chunkCs);
     }
     }
 
 
     /// <summary>
     /// <summary>
@@ -109,7 +111,8 @@ public class Chunk : IDisposable
 
 
         RectI searchRegion = passedSearchRegion ?? new RectI(VecI.Zero, Surface.Size);
         RectI searchRegion = passedSearchRegion ?? new RectI(VecI.Zero, Surface.Size);
 
 
-        ulong* ptr = (ulong*)Surface.PixelBuffer;
+        using var pixmap = Surface.PeekPixels();
+        ulong* ptr = (ulong*)pixmap.GetPixels();
         for (int y = searchRegion.Top; y < searchRegion.Bottom; y++)
         for (int y = searchRegion.Top; y < searchRegion.Bottom; y++)
         {
         {
             for (int x = searchRegion.Left; x < searchRegion.Right; x++)
             for (int x = searchRegion.Left; x < searchRegion.Right; x++)
@@ -133,11 +136,13 @@ public class Chunk : IDisposable
     /// </summary>
     /// </summary>
     public void Dispose()
     public void Dispose()
     {
     {
-        if (returned)
+        Surface.Dispose();
+        returned = true;
+        /*if (returned)
             return;
             return;
         Interlocked.Decrement(ref chunkCounter);
         Interlocked.Decrement(ref chunkCounter);
         Surface.DrawingSurface.Canvas.Clear();
         Surface.DrawingSurface.Canvas.Clear();
         ChunkPool.Instance.Push(this);
         ChunkPool.Instance.Push(this);
-        returned = true;
+        returned = true;*/
     }
     }
 }
 }

+ 62 - 2
src/ChunkyImageLib/ChunkyImage.cs

@@ -1,4 +1,5 @@
 using System.ComponentModel.DataAnnotations;
 using System.ComponentModel.DataAnnotations;
+using System.Diagnostics;
 using System.Runtime.CompilerServices;
 using System.Runtime.CompilerServices;
 using ChunkyImageLib.DataHolders;
 using ChunkyImageLib.DataHolders;
 using ChunkyImageLib.Operations;
 using ChunkyImageLib.Operations;
@@ -191,7 +192,8 @@ public class ChunkyImage : IReadOnlyChunkyImage, IDisposable, ICloneable, ICache
     /// Finds the precise bounds in <paramref name="suggestedResolution"/>. If there are no chunks rendered for that resolution, full res chunks are used instead.
     /// Finds the precise bounds in <paramref name="suggestedResolution"/>. If there are no chunks rendered for that resolution, full res chunks are used instead.
     /// </summary>
     /// </summary>
     /// <exception cref="ObjectDisposedException">This image is disposed</exception>
     /// <exception cref="ObjectDisposedException">This image is disposed</exception>
-    public RectI? FindTightCommittedBounds(ChunkResolution suggestedResolution = ChunkResolution.Full, bool fallbackToChunkAligned = false)
+    public RectI? FindTightCommittedBounds(ChunkResolution suggestedResolution = ChunkResolution.Full,
+        bool fallbackToChunkAligned = false)
     {
     {
         lock (lockObject)
         lock (lockObject)
         {
         {
@@ -267,7 +269,7 @@ public class ChunkyImage : IReadOnlyChunkyImage, IDisposable, ICloneable, ICache
                 var image = GetCommittedChunk(chunk, ChunkResolution.Full);
                 var image = GetCommittedChunk(chunk, ChunkResolution.Full);
                 if (image is null)
                 if (image is null)
                     continue;
                     continue;
-                output.EnqueueDrawImage(chunk * FullChunkSize, image.Surface);
+                output.EnqueueDrawTexture(chunk * FullChunkSize, image.Surface);
             }
             }
 
 
             output.CommitChanges();
             output.CommitChanges();
@@ -421,6 +423,64 @@ public class ChunkyImage : IReadOnlyChunkyImage, IDisposable, ICloneable, ICache
         }
         }
     }
     }
 
 
+    public bool DrawCachedMostUpToDateChunkOn(VecI chunkPos, ChunkResolution resolution, DrawingSurface surface,
+        VecD pos,
+        Paint? paint = null, SamplingOptions? sampling = null)
+    {
+        lock (lockObject)
+        {
+            ThrowIfDisposed();
+            OneOf<None, EmptyChunk, Chunk> latestChunk;
+            {
+                var chunk = MaybeGetLatestChunk(chunkPos, resolution);
+                if (latestChunksData[resolution].TryGetValue(chunkPos, out var chunkData) && chunkData.IsDeleted)
+                {
+                    latestChunk = new EmptyChunk();
+                }
+                else
+                {
+                    latestChunk = chunk is null ? new None() : chunk;
+                }
+            }
+
+            var committedChunk = GetCommittedChunk(chunkPos, resolution);
+
+            // draw committed directly
+            if (latestChunk.IsT0 || latestChunk.IsT1 && committedChunk is not null && blendMode != BlendMode.Src)
+            {
+                if (committedChunk is null)
+                    return false;
+                committedChunk.DrawChunkOn(surface, pos, paint, sampling);
+                return true;
+            }
+
+            // no need to combine with committed, draw directly
+            if (blendMode == BlendMode.Src || committedChunk is null)
+            {
+                if (latestChunk.IsT2)
+                {
+                    latestChunk.AsT2.DrawChunkOn(surface, pos, paint, sampling);
+                    return true;
+                }
+
+                return false;
+            }
+
+            // combine with committed and then draw
+            using var tempChunk = Chunk.Create(ProcessingColorSpace, resolution);
+            tempChunk.Surface.DrawingSurface.Canvas.DrawSurface(committedChunk.Surface.DrawingSurface, 0, 0,
+                ReplacingPaint);
+            blendModePaint.BlendMode = blendMode;
+            tempChunk.Surface.DrawingSurface.Canvas.DrawSurface(latestChunk.AsT2.Surface.DrawingSurface, 0, 0,
+                blendModePaint);
+            if (lockTransparency)
+                OperationHelper.ClampAlpha(tempChunk.Surface.DrawingSurface, committedChunk.Surface.DrawingSurface);
+            tempChunk.DrawChunkOn(surface, pos, paint, sampling);
+
+            return true;
+        }
+    }
+
     /// <exception cref="ObjectDisposedException">This image is disposed</exception>
     /// <exception cref="ObjectDisposedException">This image is disposed</exception>
     public bool LatestOrCommittedChunkExists(VecI chunkPos)
     public bool LatestOrCommittedChunkExists(VecI chunkPos)
     {
     {

+ 69 - 5
src/ChunkyImageLib/ChunkyImageEx.cs

@@ -1,4 +1,5 @@
-using ChunkyImageLib.DataHolders;
+using System.Diagnostics;
+using ChunkyImageLib.DataHolders;
 using ChunkyImageLib.Operations;
 using ChunkyImageLib.Operations;
 using Drawie.Backend.Core.Numerics;
 using Drawie.Backend.Core.Numerics;
 using Drawie.Backend.Core.Surfaces;
 using Drawie.Backend.Core.Surfaces;
@@ -6,6 +7,7 @@ using Drawie.Backend.Core.Surfaces.PaintImpl;
 using Drawie.Numerics;
 using Drawie.Numerics;
 
 
 namespace ChunkyImageLib;
 namespace ChunkyImageLib;
+
 public static class IReadOnlyChunkyImageEx
 public static class IReadOnlyChunkyImageEx
 {
 {
     /// <summary>
     /// <summary>
@@ -24,7 +26,25 @@ public static class IReadOnlyChunkyImageEx
     {
     {
         DrawRegionOn(fullResRegion, resolution, surface, pos, image.DrawMostUpToDateChunkOn, paint, sampling);
         DrawRegionOn(fullResRegion, resolution, surface, pos, image.DrawMostUpToDateChunkOn, paint, sampling);
     }
     }
-    
+
+    /// <summary>
+    /// Extracts a region from the <see cref="ChunkyImage"/> and draws it onto the passed <see cref="DrawingSurface"/>.
+    /// The region is taken from the most up to date version of the <see cref="ChunkyImage"/>
+    /// </summary>
+    /// <param name="image"><see cref="ChunkyImage"/> to extract the region from</param>
+    /// <param name="fullResRegion">The region to extract</param>
+    /// <param name="resolution">Chunk resolution</param>
+    /// <param name="surface">Surface to draw onto</param>
+    /// <param name="pos">Starting position on the surface</param>
+    /// <param name="paint">Paint to use for drawing</param>
+    public static void DrawMostUpToDateRegionOnWithAffected
+    (this IReadOnlyChunkyImage image, RectI fullResRegion, ChunkResolution resolution, DrawingSurface surface,
+        AffectedArea affectedArea, VecD pos, Paint? paint = null, SamplingOptions? sampling = null)
+    {
+        DrawRegionOn(fullResRegion, resolution, surface, pos, image.DrawMostUpToDateChunkOn,
+            image.DrawCachedMostUpToDateChunkOn, affectedArea, paint, sampling);
+    }
+
     /// <summary>
     /// <summary>
     /// Extracts a region from the <see cref="ChunkyImage"/> and draws it onto the passed <see cref="DrawingSurface"/>.
     /// Extracts a region from the <see cref="ChunkyImage"/> and draws it onto the passed <see cref="DrawingSurface"/>.
     /// The region is taken from the committed version of the <see cref="ChunkyImage"/>
     /// The region is taken from the committed version of the <see cref="ChunkyImage"/>
@@ -36,17 +56,50 @@ public static class IReadOnlyChunkyImageEx
     /// <param name="pos">Starting position on the surface</param>
     /// <param name="pos">Starting position on the surface</param>
     /// <param name="paint">Paint to use for drawing</param>
     /// <param name="paint">Paint to use for drawing</param>
     public static void DrawCommittedRegionOn
     public static void DrawCommittedRegionOn
-        (this IReadOnlyChunkyImage image, RectI fullResRegion, ChunkResolution resolution, DrawingSurface surface, VecI pos, Paint? paint = null, SamplingOptions? samplingOptions = null)
+    (this IReadOnlyChunkyImage image, RectI fullResRegion, ChunkResolution resolution, DrawingSurface surface,
+        VecI pos, Paint? paint = null, SamplingOptions? samplingOptions = null)
     {
     {
         DrawRegionOn(fullResRegion, resolution, surface, pos, image.DrawCommittedChunkOn, paint, samplingOptions);
         DrawRegionOn(fullResRegion, resolution, surface, pos, image.DrawCommittedChunkOn, paint, samplingOptions);
     }
     }
-    
+
+    private static void DrawRegionOn(
+        RectI fullResRegion,
+        ChunkResolution resolution,
+        DrawingSurface surface,
+        VecD pos,
+        Func<VecI, ChunkResolution, DrawingSurface, VecD, Paint?, SamplingOptions?, bool> drawingFunc,
+        Paint? paint = null, SamplingOptions? samplingOptions = null)
+    {
+        int count = surface.Canvas.Save();
+        surface.Canvas.ClipRect(new RectD(pos, fullResRegion.Size));
+
+        VecI chunkTopLeft = OperationHelper.GetChunkPos(fullResRegion.TopLeft, ChunkyImage.FullChunkSize);
+        VecI chunkBotRight = OperationHelper.GetChunkPos(fullResRegion.BottomRight, ChunkyImage.FullChunkSize);
+        VecI offsetFullRes = (chunkTopLeft * ChunkyImage.FullChunkSize) - fullResRegion.Pos;
+        VecI offsetTargetRes = (VecI)(offsetFullRes * resolution.Multiplier());
+
+        for (int j = chunkTopLeft.Y; j <= chunkBotRight.Y; j++)
+        {
+            for (int i = chunkTopLeft.X; i <= chunkBotRight.X; i++)
+            {
+                var chunkPos = new VecI(i, j);
+                drawingFunc(chunkPos, resolution, surface,
+                    offsetTargetRes + (chunkPos - chunkTopLeft) * resolution.PixelSize() + pos, paint,
+                    samplingOptions);
+            }
+        }
+
+        surface.Canvas.RestoreToCount(count);
+    }
+
     private static void DrawRegionOn(
     private static void DrawRegionOn(
         RectI fullResRegion,
         RectI fullResRegion,
         ChunkResolution resolution,
         ChunkResolution resolution,
         DrawingSurface surface,
         DrawingSurface surface,
         VecD pos,
         VecD pos,
         Func<VecI, ChunkResolution, DrawingSurface, VecD, Paint?, SamplingOptions?, bool> drawingFunc,
         Func<VecI, ChunkResolution, DrawingSurface, VecD, Paint?, SamplingOptions?, bool> drawingFunc,
+        Func<VecI, ChunkResolution, DrawingSurface, VecD, Paint?, SamplingOptions?, bool> quickDrawingFunc,
+        AffectedArea area,
         Paint? paint = null, SamplingOptions? samplingOptions = null)
         Paint? paint = null, SamplingOptions? samplingOptions = null)
     {
     {
         int count = surface.Canvas.Save();
         int count = surface.Canvas.Save();
@@ -62,7 +115,18 @@ public static class IReadOnlyChunkyImageEx
             for (int i = chunkTopLeft.X; i <= chunkBotRight.X; i++)
             for (int i = chunkTopLeft.X; i <= chunkBotRight.X; i++)
             {
             {
                 var chunkPos = new VecI(i, j);
                 var chunkPos = new VecI(i, j);
-                drawingFunc(chunkPos, resolution, surface, offsetTargetRes + (chunkPos - chunkTopLeft) * resolution.PixelSize() + pos, paint, samplingOptions);
+                if (area.Chunks.Contains(chunkPos))
+                {
+                    drawingFunc(chunkPos, resolution, surface,
+                        offsetTargetRes + (chunkPos - chunkTopLeft) * resolution.PixelSize() + pos, paint,
+                        samplingOptions);
+                }
+                else
+                {
+                    quickDrawingFunc(chunkPos, resolution, surface,
+                        offsetTargetRes + (chunkPos - chunkTopLeft) * resolution.PixelSize() + pos, paint,
+                        samplingOptions);
+                }
             }
             }
         }
         }
 
 

+ 1 - 1
src/ChunkyImageLib/CommittedChunkStorage.cs

@@ -36,7 +36,7 @@ public class CommittedChunkStorage : IDisposable
             if (chunk is null)
             if (chunk is null)
                 image.EnqueueClearRegion(new(pos * ChunkPool.FullChunkSize, new(ChunkPool.FullChunkSize, ChunkPool.FullChunkSize)));
                 image.EnqueueClearRegion(new(pos * ChunkPool.FullChunkSize, new(ChunkPool.FullChunkSize, ChunkPool.FullChunkSize)));
             else
             else
-                image.EnqueueDrawImage(pos * ChunkPool.FullChunkSize, chunk.Surface, ReplacingPaint);
+                image.EnqueueDrawTexture(pos * ChunkPool.FullChunkSize, chunk.Surface, ReplacingPaint);
         }
         }
     }
     }
 
 

+ 1 - 0
src/ChunkyImageLib/IReadOnlyChunkyImage.cs

@@ -11,6 +11,7 @@ namespace ChunkyImageLib;
 public interface IReadOnlyChunkyImage
 public interface IReadOnlyChunkyImage
 {
 {
     bool DrawMostUpToDateChunkOn(VecI chunkPos, ChunkResolution resolution, DrawingSurface surface, VecD pos, Paint? paint = null, SamplingOptions? sampling = null);
     bool DrawMostUpToDateChunkOn(VecI chunkPos, ChunkResolution resolution, DrawingSurface surface, VecD pos, Paint? paint = null, SamplingOptions? sampling = null);
+    bool DrawCachedMostUpToDateChunkOn(VecI chunkPos, ChunkResolution resolution, DrawingSurface surface, VecD pos, Paint? paint = null, SamplingOptions? sampling = null);
     bool DrawCommittedChunkOn(VecI chunkPos, ChunkResolution resolution, DrawingSurface surface, VecD pos, Paint? paint = null, SamplingOptions? sampling = null);
     bool DrawCommittedChunkOn(VecI chunkPos, ChunkResolution resolution, DrawingSurface surface, VecD pos, Paint? paint = null, SamplingOptions? sampling = null);
     RectI? FindChunkAlignedMostUpToDateBounds();
     RectI? FindChunkAlignedMostUpToDateBounds();
     RectI? FindChunkAlignedCommittedBounds();
     RectI? FindChunkAlignedCommittedBounds();

+ 1 - 1
src/Drawie

@@ -1 +1 @@
-Subproject commit b6c34c96ac5b01abad69604465445270270270d2
+Subproject commit de00c15348702e8188bc3962bfc9a2a2612388a8

+ 1 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Interfaces/SceneObjectRenderContext.cs

@@ -11,6 +11,7 @@ public class SceneObjectRenderContext : RenderContext
     public RectD LocalBounds { get; }
     public RectD LocalBounds { get; }
     public bool RenderSurfaceIsScene { get; }
     public bool RenderSurfaceIsScene { get; }
     public RenderOutputProperty TargetPropertyOutput { get; }
     public RenderOutputProperty TargetPropertyOutput { get; }
+    public AffectedArea AffectedArea { get; set; }
 
 
     public SceneObjectRenderContext(RenderOutputProperty targetPropertyOutput, DrawingSurface surface, RectD localBounds, KeyFrameTime frameTime,
     public SceneObjectRenderContext(RenderOutputProperty targetPropertyOutput, DrawingSurface surface, RectD localBounds, KeyFrameTime frameTime,
         ChunkResolution chunkResolution, VecI renderOutputSize, VecI documentSize, bool renderSurfaceIsScene, ColorSpace processingColorSpace, SamplingOptions desiredSampling, double opacity) : base(surface, frameTime, chunkResolution, renderOutputSize, documentSize, processingColorSpace, desiredSampling, opacity)
         ChunkResolution chunkResolution, VecI renderOutputSize, VecI documentSize, bool renderSurfaceIsScene, ColorSpace processingColorSpace, SamplingOptions desiredSampling, double opacity) : base(surface, frameTime, chunkResolution, renderOutputSize, documentSize, processingColorSpace, desiredSampling, opacity)

+ 22 - 8
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/ImageLayerNode.cs

@@ -1,4 +1,5 @@
-using PixiEditor.ChangeableDocument.Changeables.Animations;
+using System.Diagnostics;
+using PixiEditor.ChangeableDocument.Changeables.Animations;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 using PixiEditor.ChangeableDocument.Changeables.Interfaces;
 using PixiEditor.ChangeableDocument.Changeables.Interfaces;
 using PixiEditor.ChangeableDocument.Helpers;
 using PixiEditor.ChangeableDocument.Helpers;
@@ -132,14 +133,26 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
         var sceneSize = GetSceneSize(ctx.FrameTime);
         var sceneSize = GetSceneSize(ctx.FrameTime);
         VecD topLeft = sceneSize / 2f;
         VecD topLeft = sceneSize / 2f;
 
 
-        if (renderedSurfaceFrame == null || ctx.FullRerender || ctx.FrameTime.Frame != renderedSurfaceFrame)
+        //if (renderedSurfaceFrame == null || ctx.FullRerender || ctx.FrameTime.Frame != renderedSurfaceFrame)
         {
         {
-            GetLayerImageAtFrame(ctx.FrameTime.Frame).DrawMostUpToDateRegionOn(
-                new RectI(0, 0, layerImage.LatestSize.X, layerImage.LatestSize.Y),
-                ChunkResolution.Full,
-                workingSurface, -topLeft, paint);
+            topLeft *= ctx.ChunkResolution.Multiplier();
+            workingSurface.Canvas.Scale((float)ctx.ChunkResolution.InvertedMultiplier());
+            if (ctx.AffectedArea.Chunks.Count > 0)
+            {
+                GetLayerImageAtFrame(ctx.FrameTime.Frame).DrawMostUpToDateRegionOnWithAffected(
+                    new RectI(0, 0, layerImage.LatestSize.X, layerImage.LatestSize.Y),
+                    ctx.ChunkResolution,
+                    workingSurface, ctx.AffectedArea, -topLeft, paint);
+            }
+            else
+            {
+                GetLayerImageAtFrame(ctx.FrameTime.Frame).DrawMostUpToDateRegionOn(
+                    new RectI(0, 0, layerImage.LatestSize.X, layerImage.LatestSize.Y),
+                    ctx.ChunkResolution,
+                    workingSurface, -topLeft, paint);
+            }
         }
         }
-        else
+        /*else
         {
         {
             if (ctx.DesiredSamplingOptions == SamplingOptions.Default)
             if (ctx.DesiredSamplingOptions == SamplingOptions.Default)
             {
             {
@@ -153,7 +166,7 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
                     ctx.DesiredSamplingOptions,
                     ctx.DesiredSamplingOptions,
                     paint);
                     paint);
             }
             }
-        }
+        }*/
 
 
         workingSurface.Canvas.RestoreToCount(saved);
         workingSurface.Canvas.RestoreToCount(saved);
     }
     }
@@ -349,6 +362,7 @@ public class ImageLayerNode : LayerNode, IReadOnlyImageNode
     public override void RenderChunk(VecI chunkPos, ChunkResolution resolution, KeyFrameTime frameTime,
     public override void RenderChunk(VecI chunkPos, ChunkResolution resolution, KeyFrameTime frameTime,
         ColorSpace processColorSpace)
         ColorSpace processColorSpace)
     {
     {
+        return;
         base.RenderChunk(chunkPos, resolution, frameTime, processColorSpace);
         base.RenderChunk(chunkPos, resolution, frameTime, processColorSpace);
 
 
         var img = GetLayerImageAtFrame(frameTime.Frame);
         var img = GetLayerImageAtFrame(frameTime.Frame);

+ 2 - 2
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/SampleImageNode.cs

@@ -58,11 +58,11 @@ public class SampleImageNode : Node
 
 
         if (SampleMode.Value == ColorSampleMode.ColorManaged)
         if (SampleMode.Value == ColorSampleMode.ColorManaged)
         {
         {
-            color = Image.Value.GetSRGBPixel(pixelCoordinate);
+            color = Image.Value.GetSrgbPixel(pixelCoordinate);
         }
         }
         else
         else
         {
         {
-            color = Image.Value.GetPixel(pixelCoordinate);
+            color = Image.Value.GetRawPixel(pixelCoordinate);
         }
         }
 
 
         return new Half4("") { ConstantValue = color };
         return new Half4("") { ConstantValue = color };

+ 1 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/StructureNode.cs

@@ -186,6 +186,7 @@ public abstract class StructureNode : RenderNode, IReadOnlyStructureNode, IRende
             context.FrameTime, context.ChunkResolution, context.RenderOutputSize, context.DocumentSize, renderTarget == context.RenderSurface,
             context.FrameTime, context.ChunkResolution, context.RenderOutputSize, context.DocumentSize, renderTarget == context.RenderSurface,
             context.ProcessingColorSpace, context.DesiredSamplingOptions, context.Opacity);
             context.ProcessingColorSpace, context.DesiredSamplingOptions, context.Opacity);
         renderObjectContext.FullRerender = context.FullRerender;
         renderObjectContext.FullRerender = context.FullRerender;
+        renderObjectContext.AffectedArea = context.AffectedArea;
         return renderObjectContext;
         return renderObjectContext;
     }
     }
 
 

+ 2 - 2
src/PixiEditor.ChangeableDocument/Changes/Drawing/FloodFill/FloodFillHelper.cs

@@ -209,10 +209,10 @@ public static class FloodFillHelper
         byte[] pixelStates = new byte[chunkSize * chunkSize];
         byte[] pixelStates = new byte[chunkSize * chunkSize];
         DrawSelection(pixelStates, selection, globalSelectionBounds, chunkPos, chunkSize);
         DrawSelection(pixelStates, selection, globalSelectionBounds, chunkPos, chunkSize);
 
 
-        using var refPixmap = referenceChunk.Surface.DrawingSurface.PeekPixels();
+        using var refPixmap = referenceChunk.Surface.PeekPixels();
         Half* refArray = (Half*)refPixmap.GetPixels();
         Half* refArray = (Half*)refPixmap.GetPixels();
 
 
-        using var drawPixmap = drawingChunk.Surface.DrawingSurface.PeekPixels();
+        using var drawPixmap = drawingChunk.Surface.PeekPixels();
         Half* drawArray = (Half*)drawPixmap.GetPixels();
         Half* drawArray = (Half*)drawPixmap.GetPixels();
 
 
         Stack<VecI> toVisit = new();
         Stack<VecI> toVisit = new();

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Drawing/FloodFill/FloodFill_Change.cs

@@ -57,7 +57,7 @@ internal class FloodFill_Change : Change
 
 
         foreach (var (chunkPos, chunk) in floodFilledChunks)
         foreach (var (chunkPos, chunk) in floodFilledChunks)
         {
         {
-            image.EnqueueDrawImage(chunkPos * ChunkyImage.FullChunkSize, chunk.Surface, null, false);
+            image.EnqueueDrawTexture(chunkPos * ChunkyImage.FullChunkSize, chunk.Surface, null, false);
         }
         }
         var affArea = image.FindAffectedArea();
         var affArea = image.FindAffectedArea();
         chunkStorage = new CommittedChunkStorage(image, affArea.Chunks);
         chunkStorage = new CommittedChunkStorage(image, affArea.Chunks);

+ 2 - 1
src/PixiEditor.ChangeableDocument/DocumentChangeTracker.cs

@@ -1,4 +1,5 @@
 using System.Diagnostics;
 using System.Diagnostics;
+using Drawie.Backend.Core.Bridge;
 using PixiEditor.ChangeableDocument.Actions;
 using PixiEditor.ChangeableDocument.Actions;
 using PixiEditor.ChangeableDocument.Actions.Undo;
 using PixiEditor.ChangeableDocument.Actions.Undo;
 using PixiEditor.ChangeableDocument.Changeables.Interfaces;
 using PixiEditor.ChangeableDocument.Changeables.Interfaces;
@@ -430,7 +431,7 @@ public class DocumentChangeTracker : IDisposable
         if (running)
         if (running)
             throw new InvalidOperationException("Already currently processing");
             throw new InvalidOperationException("Already currently processing");
         running = true;
         running = true;
-        var result = await Task.Run(() => ProcessActionList(actions)).ConfigureAwait(true);
+        var result = await DrawingBackendApi.Current.RenderingDispatcher.InvokeAsync(() => ProcessActionList(actions));
         running = false;
         running = false;
         return result;
         return result;
     }
     }

+ 2 - 1
src/PixiEditor.ChangeableDocument/Rendering/RenderContext.cs

@@ -21,7 +21,8 @@ public class RenderContext
     public bool FullRerender { get; set; } = false;
     public bool FullRerender { get; set; } = false;
     
     
     public ColorSpace ProcessingColorSpace { get; set; }
     public ColorSpace ProcessingColorSpace { get; set; }
-    public string? TargetOutput { get; set; }   
+    public string? TargetOutput { get; set; }
+    public AffectedArea AffectedArea { get; set; }
 
 
 
 
     public RenderContext(DrawingSurface renderSurface, KeyFrameTime frameTime, ChunkResolution chunkResolution,
     public RenderContext(DrawingSurface renderSurface, KeyFrameTime frameTime, ChunkResolution chunkResolution,

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

@@ -141,11 +141,11 @@ internal class ActionAccumulator
 
 
                 if (!allPassthrough)
                 if (!allPassthrough)
                 {
                 {
-                    await canvasUpdater.UpdateGatheredChunks(affectedAreas,
-                        undoBoundaryPassed || viewportRefreshRequest);
+                    /*await canvasUpdater.UpdateGatheredChunks(affectedAreas,
+                        undoBoundaryPassed || viewportRefreshRequest);*/
                 }
                 }
 
 
-                await document.SceneRenderer.RenderAsync(internals.State.Viewports);
+                await document.SceneRenderer.RenderAsync(internals.State.Viewports, affectedAreas.MainImageArea);
 
 
                 bool previewsDisabled = PixiEditorSettings.Performance.DisablePreviews.Value;
                 bool previewsDisabled = PixiEditorSettings.Performance.DisablePreviews.Value;
 
 

+ 9 - 3
src/PixiEditor/Models/Rendering/SceneRenderer.cs

@@ -1,4 +1,5 @@
-using Avalonia.Threading;
+using System.Diagnostics;
+using Avalonia.Threading;
 using ChunkyImageLib.DataHolders;
 using ChunkyImageLib.DataHolders;
 using Drawie.Backend.Core;
 using Drawie.Backend.Core;
 using Drawie.Backend.Core.ColorsImpl;
 using Drawie.Backend.Core.ColorsImpl;
@@ -42,7 +43,7 @@ internal class SceneRenderer : IDisposable
         this.previewRenderer = previewRenderer;
         this.previewRenderer = previewRenderer;
     }
     }
 
 
-    public async Task RenderAsync(Dictionary<Guid, ViewportInfo> stateViewports)
+    public async Task RenderAsync(Dictionary<Guid, ViewportInfo> stateViewports, AffectedArea affectedArea)
     {
     {
         await Dispatcher.UIThread.InvokeAsync(() =>
         await Dispatcher.UIThread.InvokeAsync(() =>
         {
         {
@@ -55,6 +56,7 @@ internal class SceneRenderer : IDisposable
                     (VecI)viewport.Value.RealDimensions,
                     (VecI)viewport.Value.RealDimensions,
                     viewport.Value.Transform,
                     viewport.Value.Transform,
                     viewport.Value.Resolution,
                     viewport.Value.Resolution,
+                    affectedArea,
                     viewport.Value.Sampling,
                     viewport.Value.Sampling,
                     viewport.Value.RenderOutput.Equals("DEFAULT", StringComparison.InvariantCultureIgnoreCase)
                     viewport.Value.RenderOutput.Equals("DEFAULT", StringComparison.InvariantCultureIgnoreCase)
                         ? null
                         ? null
@@ -71,6 +73,7 @@ internal class SceneRenderer : IDisposable
 
 
     public Texture? RenderScene(Guid viewportId, VecI renderTargetSize, Matrix3X3 targetMatrix,
     public Texture? RenderScene(Guid viewportId, VecI renderTargetSize, Matrix3X3 targetMatrix,
         ChunkResolution resolution,
         ChunkResolution resolution,
+        AffectedArea affectedArea,
         SamplingOptions samplingOptions,
         SamplingOptions samplingOptions,
         string? targetOutput = null)
         string? targetOutput = null)
     {
     {
@@ -89,7 +92,7 @@ internal class SceneRenderer : IDisposable
 
 
         if (shouldRerender)
         if (shouldRerender)
         {
         {
-            return RenderGraph(renderTargetSize, targetMatrix, resolution, samplingOptions, targetOutput, finalGraph);
+            return RenderGraph(renderTargetSize, targetMatrix, resolution, samplingOptions, affectedArea, targetOutput, finalGraph);
         }
         }
         //previewRenderer.RenderPreviews(DocumentViewModel.AnimationHandler.ActiveFrameTime);
         //previewRenderer.RenderPreviews(DocumentViewModel.AnimationHandler.ActiveFrameTime);
 
 
@@ -117,6 +120,7 @@ internal class SceneRenderer : IDisposable
 
 
     private Texture RenderGraph(VecI renderTargetSize, Matrix3X3 targetMatrix, ChunkResolution resolution,
     private Texture RenderGraph(VecI renderTargetSize, Matrix3X3 targetMatrix, ChunkResolution resolution,
         SamplingOptions samplingOptions,
         SamplingOptions samplingOptions,
+        AffectedArea area,
         string? targetOutput,
         string? targetOutput,
         IReadOnlyNodeGraph finalGraph)
         IReadOnlyNodeGraph finalGraph)
     {
     {
@@ -156,6 +160,8 @@ internal class SceneRenderer : IDisposable
         RenderContext context = new(renderTarget, DocumentViewModel.AnimationHandler.ActiveFrameTime,
         RenderContext context = new(renderTarget, DocumentViewModel.AnimationHandler.ActiveFrameTime,
             resolution, finalSize, Document.Size, Document.ProcessingColorSpace, samplingOptions);
             resolution, finalSize, Document.Size, Document.ProcessingColorSpace, samplingOptions);
         context.TargetOutput = targetOutput;
         context.TargetOutput = targetOutput;
+        context.AffectedArea = area;
+
         finalGraph.Execute(context);
         finalGraph.Execute(context);
 
 
         renderTarget.Canvas.Restore();
         renderTarget.Canvas.Restore();

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

@@ -958,7 +958,7 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
         if (transformed.X < 0 || transformed.Y < 0 || transformed.X >= bitmap.Size.X || transformed.Y >= bitmap.Size.Y)
         if (transformed.X < 0 || transformed.Y < 0 || transformed.X >= bitmap.Size.X || transformed.Y >= bitmap.Size.Y)
             return null;
             return null;
 
 
-        return bitmap.GetSRGBPixel(new VecI((int)transformed.X, (int)transformed.Y));
+        return bitmap.GetSrgbPixel(new VecI((int)transformed.X, (int)transformed.Y));
     }
     }
 
 
     public void SuppressAllOverlayEvents(string suppressor)
     public void SuppressAllOverlayEvents(string suppressor)