Browse Source

Merge branch 'animation-improvements' into avalonia-rewrite

flabbet 1 year ago
parent
commit
cc2b2d2090
23 changed files with 99 additions and 48 deletions
  1. 13 0
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Context/FuncContext.cs
  2. 4 4
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/CombineColorNode.cs
  3. 3 3
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/LerpColorNode.cs
  4. 2 2
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/MergeNode.cs
  5. 1 4
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/ModifyImageRightNode.cs
  6. 7 1
      src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Node.cs
  7. 1 1
      src/PixiEditor.ChangeableDocument/Changes/Drawing/CombineStructureMembersOnto_Change.cs
  8. 0 2
      src/PixiEditor.ChangeableDocument/Rendering/DocumentRenderer.cs
  9. 2 2
      src/PixiEditor.DrawingApi.Core/Bridge/DrawingBackendApi.cs
  10. 3 1
      src/PixiEditor.DrawingApi.Core/Bridge/IDrawingBackend.cs
  11. 10 0
      src/PixiEditor.DrawingApi.Core/IRenderingServer.cs
  12. 2 1
      src/PixiEditor.DrawingApi.Core/Shaders/Generation/ShaderBuilder.cs
  13. 4 2
      src/PixiEditor.DrawingApi.Core/Shaders/Uniform.cs
  14. 5 1
      src/PixiEditor.DrawingApi.Skia/SkiaDrawingBackend.cs
  15. 2 1
      src/PixiEditor/Models/Files/ImageFileType.cs
  16. 1 3
      src/PixiEditor/Models/Rendering/MemberPreviewUpdater.cs
  17. 5 1
      src/PixiEditor/ViewModels/Dock/LayoutManager.cs
  18. 6 5
      src/PixiEditor/ViewModels/Document/DocumentViewModel.cs
  19. 0 1
      src/PixiEditor/Views/Main/ViewportControls/Viewport.axaml
  20. 1 1
      src/PixiEditor/Views/MainWindow.axaml
  21. 4 1
      src/PixiEditor/Views/MainWindow.axaml.cs
  22. 18 0
      src/PixiEditor/Views/Rendering/AvaloniaRenderingServer.cs
  23. 5 11
      src/PixiEditor/Views/Rendering/Scene.cs

+ 13 - 0
src/PixiEditor.ChangeableDocument/Changeables/Graph/Context/FuncContext.cs

@@ -102,4 +102,17 @@ public class FuncContext
     {
         return getFrom.Connection.ValueType.IsAssignableTo(typeof(Delegate));
     }
+
+    public ShaderExpressionVariable GetValue(FuncInputProperty<Half4> getFrom)
+    {
+        if (getFrom.Connection == null || !IsFuncType(getFrom))
+        {
+            Half4 color = getFrom.Value(this);
+            color.VariableName = $"color_{Builder.GetUniqueNameNumber()}";
+            Builder.AddUniform(color.VariableName, color.ConstantValue);
+            return color;
+        }
+
+        return getFrom.Value(this);
+    }
 }

+ 4 - 4
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/CombineSeparate/CombineColorNode.cs

@@ -34,10 +34,10 @@ public class CombineColorNode : Node
 
     private Half4 GetColor(FuncContext ctx)
     {
-        var r = R.Value(ctx);
-        var g = G.Value(ctx);
-        var b = B.Value(ctx);
-        var a = A.Value(ctx);
+        var r = ctx.GetValue(R);
+        var g = ctx.GetValue(G);
+        var b = ctx.GetValue(B);
+        var a = ctx.GetValue(A);
 
         return ctx.NewHalf4(r, g, b, a); 
     }

+ 3 - 3
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/LerpColorNode.cs

@@ -25,9 +25,9 @@ public class LerpColorNode : Node // TODO: ILerpable as inputs?
 
     private Half4 Lerp(FuncContext arg)
     {
-        var from = From.Value(arg);
-        var to = To.Value(arg);
-        var time = Time.Value(arg);
+        var from = arg.GetValue(From);
+        var to = arg.GetValue(To);
+        var time = arg.GetValue(Time);
         
         return arg.NewHalf4(ShaderMath.Lerp(from, to, time)); 
     }

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

@@ -40,8 +40,8 @@ public class MergeNode : Node, IBackgroundInput
             return null;
         }
         
-        int width = Math.Max(Top.Value?.Size.X ?? Bottom.Value.Size.X, Bottom.Value.Size.X);
-        int height = Math.Max(Top.Value?.Size.Y ?? Bottom.Value.Size.Y, Bottom.Value.Size.Y);
+        int width = Math.Max(Top.Value?.Size.X ?? Bottom.Value.Size.X, Bottom.Value?.Size.X ?? Top.Value.Size.X);
+        int height = Math.Max(Top.Value?.Size.Y ?? Bottom.Value.Size.Y, Bottom.Value?.Size.Y ?? Top.Value.Size.Y);
         
         Texture workingSurface = RequestTexture(0, new VecI(width, height), true);
         

+ 1 - 4
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/ModifyImageRightNode.cs

@@ -30,7 +30,6 @@ public class ModifyImageRightNode : Node, IPairNodeEnd
 
     private string _lastSksl;
     
-    private TextureCache _textureCache = new(); 
 
     public ModifyImageRightNode()
     {
@@ -59,7 +58,7 @@ public class ModifyImageRightNode : Node, IPairNodeEnd
         var width = size.X;
         var height = size.Y;
 
-        Texture surface = _textureCache.GetTexture(renderingContext.ChunkResolution, size); 
+        Texture surface = RequestTexture(0, size);
 
         if (!surface.IsHardwareAccelerated)
         {
@@ -125,7 +124,6 @@ public class ModifyImageRightNode : Node, IPairNodeEnd
         }
         
         Output.Value = surface;
-
         return Output.Value;
     }
 
@@ -170,7 +168,6 @@ public class ModifyImageRightNode : Node, IPairNodeEnd
     public override void Dispose()
     {
         base.Dispose();
-        _textureCache.Dispose(); 
         drawingPaint?.Dispose();
     }
 

+ 7 - 1
src/PixiEditor.ChangeableDocument/Changeables/Graph/Nodes/Node.cs

@@ -6,6 +6,7 @@ using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
 using PixiEditor.ChangeableDocument.Changeables.Interfaces;
 using PixiEditor.ChangeableDocument.Rendering;
 using PixiEditor.DrawingApi.Core;
+using PixiEditor.DrawingApi.Core.ColorsImpl;
 using PixiEditor.DrawingApi.Core.Shaders;
 using PixiEditor.Numerics;
 
@@ -130,7 +131,7 @@ public abstract class Node : IReadOnlyNode, IDisposable
             
             if (clear)
             {
-                texture.DrawingSurface.Canvas.Clear();
+                texture.DrawingSurface.Canvas.Clear(Colors.Transparent);
             }
             
             return texture;
@@ -309,6 +310,11 @@ public abstract class Node : IReadOnlyNode, IDisposable
                 keyFrame.Dispose();
             }
         }
+        
+        foreach (var texture in _managedTextures)
+        {
+            texture.Value.Dispose();
+        }
     }
 
     public void DisconnectAll()

+ 1 - 1
src/PixiEditor.ChangeableDocument/Changes/Drawing/CombineStructureMembersOnto_Change.cs

@@ -79,7 +79,7 @@ internal class CombineStructureMembersOnto_Change : Change
         DocumentRenderer renderer = new(target);
 
         AffectedArea affArea = new();
-        DrawingBackendApi.Current.RenderDispatch(() =>
+        DrawingBackendApi.Current.RenderingServer.Invoke(() =>
         {
             RectI? globalClippingRect = new RectI(0, 0, target.Size.X, target.Size.Y);
             foreach (var chunk in chunksToCombine)

+ 0 - 2
src/PixiEditor.ChangeableDocument/Rendering/DocumentRenderer.cs

@@ -24,9 +24,7 @@ public class DocumentRenderer
         RenderingContext context = new(frameTime, chunkPos, resolution, Document.Size);
         try
         {
-          
             return RenderChunkOnGraph(chunkPos, resolution, globalClippingRect, Document.NodeGraph, context);
-
         }
         catch (ObjectDisposedException)
         {

+ 2 - 2
src/PixiEditor.DrawingApi.Core/Bridge/DrawingBackendApi.cs

@@ -20,7 +20,7 @@ namespace PixiEditor.DrawingApi.Core.Bridge
         
         public static bool HasBackend => _current != null;
         
-        public static void SetupBackend(IDrawingBackend backend, Action<Action> dispatcher)
+        public static void SetupBackend(IDrawingBackend backend, IRenderingServer server)
         {
             if (_current != null)
             {
@@ -28,7 +28,7 @@ namespace PixiEditor.DrawingApi.Core.Bridge
             }
             
             _current = backend;
-            _current.RenderDispatch = dispatcher;
+            _current.RenderingServer = server;
             backend.Setup();
         }
     }

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

@@ -1,6 +1,8 @@
 using System;
+using System.Threading.Tasks;
 using PixiEditor.DrawingApi.Core.Bridge.NativeObjectsImpl;
 using PixiEditor.DrawingApi.Core.Bridge.Operations;
+using PixiEditor.DrawingApi.Core.Surfaces;
 
 namespace PixiEditor.DrawingApi.Core.Bridge
 {
@@ -22,6 +24,6 @@ namespace PixiEditor.DrawingApi.Core.Bridge
         public IImageFilterImplementation ImageFilterImplementation { get; }
         public IShaderImplementation ShaderImplementation { get; set; }
         public bool IsHardwareAccelerated { get; }
-        public Action<Action> RenderDispatch { get; set; }
+        public IRenderingServer RenderingServer { get; set; }
     }
 }

+ 10 - 0
src/PixiEditor.DrawingApi.Core/IRenderingServer.cs

@@ -0,0 +1,10 @@
+using System;
+using System.Threading.Tasks;
+using PixiEditor.DrawingApi.Core.Surfaces;
+
+namespace PixiEditor.DrawingApi.Core;
+
+public interface IRenderingServer
+{
+    public Action<Action> Invoke { get; }
+}

+ 2 - 1
src/PixiEditor.DrawingApi.Core/Shaders/Generation/ShaderBuilder.cs

@@ -38,7 +38,8 @@ public class ShaderBuilder
     {
         foreach (var uniform in Uniforms)
         {
-            sb.AppendLine($"uniform {uniform.Value.UniformName} {uniform.Value.Name};");
+            string layout = string.IsNullOrEmpty(uniform.Value.LayoutOf) ? string.Empty : $"layout({uniform.Value.LayoutOf}) ";
+            sb.AppendLine($"{layout}uniform {uniform.Value.UniformName} {uniform.Value.Name};");
         }
     }
 

+ 4 - 2
src/PixiEditor.DrawingApi.Core/Shaders/Uniform.cs

@@ -11,9 +11,10 @@ public struct Uniform
     public float FloatValue { get; }
     public float[] FloatArrayValue { get; }
     public Shader ShaderValue { get; }
-    
     public string UniformName { get; }
 
+    public string LayoutOf { get; } = string.Empty;
+
     public UniformValueType DataType { get; }
 
     public Uniform(string name, float value)
@@ -50,9 +51,10 @@ public struct Uniform
     {
         Name = name;
         FloatValue = default;
-        FloatArrayValue = new float[] { color.R, color.G, color.B, color.A };
+        FloatArrayValue = new float[] { color.R / 255f, color.G / 255f, color.B / 255f, color.A / 255f };
         ShaderValue = default;
         DataType = UniformValueType.FloatArray;
+        //LayoutOf = "color"; TODO: Doesn't work with SkiaSharp 2.8x, check with 3.0 when it releases
         UniformName = "half4";
     }
 

+ 5 - 1
src/PixiEditor.DrawingApi.Skia/SkiaDrawingBackend.cs

@@ -1,7 +1,10 @@
 using System;
+using System.Threading.Tasks;
+using PixiEditor.DrawingApi.Core;
 using PixiEditor.DrawingApi.Core.Bridge;
 using PixiEditor.DrawingApi.Core.Bridge.NativeObjectsImpl;
 using PixiEditor.DrawingApi.Core.Bridge.Operations;
+using PixiEditor.DrawingApi.Core.Surfaces;
 using PixiEditor.DrawingApi.Skia.Exceptions;
 using PixiEditor.DrawingApi.Skia.Implementations;
 using SkiaSharp;
@@ -25,7 +28,8 @@ namespace PixiEditor.DrawingApi.Skia
         }
         
         public bool IsHardwareAccelerated => GraphicsContext != null;
-        public Action<Action> RenderDispatch { get; set; }
+        
+        public IRenderingServer RenderingServer { get; set; }
 
         public IColorImplementation ColorImplementation { get; }
         public IImageImplementation ImageImplementation { get; }

+ 2 - 1
src/PixiEditor/Models/Files/ImageFileType.cs

@@ -2,6 +2,7 @@
 using ChunkyImageLib;
 using PixiEditor.Helpers;
 using PixiEditor.DrawingApi.Core;
+using PixiEditor.DrawingApi.Core.Bridge;
 using PixiEditor.DrawingApi.Core.ColorsImpl;
 using PixiEditor.DrawingApi.Core.Surfaces;
 using PixiEditor.Extensions.Common.Localization;
@@ -35,7 +36,7 @@ internal abstract class ImageFileType : IoFileType
             var maybeBitmap = document.TryRenderWholeImage(0);
             if (maybeBitmap.IsT0)
                 return SaveResult.ConcurrencyError;
-            
+
             finalSurface = maybeBitmap.AsT1;
             if (maybeBitmap.AsT1.Size != exportConfig.ExportSize)
             {

+ 1 - 3
src/PixiEditor/Models/Rendering/MemberPreviewUpdater.cs

@@ -539,7 +539,7 @@ internal class MemberPreviewUpdater
         IReadOnlyStructureNode member, [DisallowNull] AffectedArea? affArea, VecI position, float scaling)
     {
         bool isEditingRootImage = !member.KeyFrames.Any(x => x.IsInFrame(doc.AnimationHandler.ActiveFrameBindable));
-        if (!isEditingRootImage)
+        if (!isEditingRootImage && keyFrame.PreviewSurface is not null)
             return;
 
         if (keyFrame.PreviewSurface == null ||
@@ -759,8 +759,6 @@ internal class MemberPreviewUpdater
                 nodeVm.ResultPreview.DrawingSurface.Canvas.Save();
                 nodeVm.ResultPreview.DrawingSurface.Canvas.Scale(scalingX, scalingY);
 
-                RectI region = new RectI(0, 0, node.CachedResult.Size.X, node.CachedResult.Size.Y);
-
                 nodeVm.ResultPreview.DrawingSurface.Canvas.DrawSurface(node.CachedResult.DrawingSurface, 0, 0,
                     ReplacingPaint);
 

+ 5 - 1
src/PixiEditor/ViewModels/Dock/LayoutManager.cs

@@ -40,7 +40,9 @@ internal class LayoutManager
         TimelineDockViewModel timelineDockViewModel = new(mainViewModel.DocumentManagerSubViewModel);
         
         NodeGraphDockViewModel nodeGraphDockViewModel = new(mainViewModel.DocumentManagerSubViewModel);
+        /*
         ChannelsDockViewModel channelsDockDockViewModel = new(mainViewModel.WindowSubViewModel);
+        */
 
         RegisterDockable(layersDockViewModel);
         RegisterDockable(colorPickerDockViewModel);
@@ -50,7 +52,9 @@ internal class LayoutManager
         RegisterDockable(paletteViewerDockViewModel);
         RegisterDockable(timelineDockViewModel);
         RegisterDockable(nodeGraphDockViewModel);
+        /*
         RegisterDockable(channelsDockDockViewModel);
+        */
         
         DefaultLayout = new LayoutTree
         {
@@ -94,7 +98,7 @@ internal class LayoutManager
                         Second = new DockableArea
                         {
                             Id = "LayersArea",
-                            Dockables = [ DockContext.CreateDockable(layersDockViewModel), DockContext.CreateDockable(channelsDockDockViewModel) ]
+                            Dockables = [ DockContext.CreateDockable(layersDockViewModel) ]
                         },
                     },
                     FirstSize = 0.66,

+ 6 - 5
src/PixiEditor/ViewModels/Document/DocumentViewModel.cs

@@ -27,6 +27,7 @@ using PixiEditor.ChangeableDocument.Changes.NodeGraph;
 using PixiEditor.ChangeableDocument.Enums;
 using PixiEditor.ChangeableDocument.Rendering;
 using PixiEditor.DrawingApi.Core;
+using PixiEditor.DrawingApi.Core.Bridge;
 using PixiEditor.DrawingApi.Core.Numerics;
 using PixiEditor.DrawingApi.Core.Surfaces.ImageData;
 using PixiEditor.DrawingApi.Core.Surfaces.Vector;
@@ -503,11 +504,11 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
         {
             Surface finalSurface = new Surface(SizeBindable);
             VecI sizeInChunks = (VecI)((VecD)SizeBindable / ChunkyImage.FullChunkSize).Ceiling();
-            for (int i = 0; i < sizeInChunks.X; i++)
+            DrawingBackendApi.Current.RenderingServer.Invoke(() =>
             {
-                for (int j = 0; j < sizeInChunks.Y; j++)
+                for (int i = 0; i < sizeInChunks.X; i++)
                 {
-                    Dispatcher.UIThread.Invoke(() =>
+                    for (int j = 0; j < sizeInChunks.Y; j++)
                     {
                         var maybeChunk = Renderer.RenderChunk(new(i, j), ChunkResolution.Full, frameTime);
                         if (maybeChunk.IsT1)
@@ -516,9 +517,9 @@ internal partial class DocumentViewModel : PixiObservableObject, IDocument
                         finalSurface.DrawingSurface.Canvas.DrawSurface(
                             chunk.Surface.DrawingSurface,
                             i * ChunkyImage.FullChunkSize, j * ChunkyImage.FullChunkSize);
-                    });
+                    }
                 }
-            }
+            });
 
             return finalSurface;
         }

+ 0 - 1
src/PixiEditor/Views/Main/ViewportControls/Viewport.axaml

@@ -112,7 +112,6 @@
             ZoomOutOnClick="{Binding ZoomOutOnClick, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=viewportControls:Viewport}, Mode=TwoWay}"
             FlipX="{Binding FlipX, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=viewportControls:Viewport}, Mode=TwoWay}"
             FlipY="{Binding FlipY, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=viewportControls:Viewport}, Mode=TwoWay}"
-            Channels="{Binding Channels, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=viewportControls:Viewport}, Mode=TwoWay}"
             AllOverlays="{Binding ElementName=vpUc, Path=ActiveOverlays}"
             FadeOut="{Binding Source={viewModels:ToolVM ColorPickerToolViewModel}, Path=PickOnlyFromReferenceLayer, Mode=OneWay}"
             DefaultCursor="{Binding Source={viewModels:MainVM}, Path=ToolsSubViewModel.ToolCursor, Mode=OneWay}"

+ 1 - 1
src/PixiEditor/Views/MainWindow.axaml

@@ -18,4 +18,4 @@
         ui:Translator.UseLanguageFlowDirection="True"
         Title="PixiEditor">
     <views1:MainView />
-</Window>
+</Window>

+ 4 - 1
src/PixiEditor/Views/MainWindow.axaml.cs

@@ -22,6 +22,7 @@ using PixiEditor.Models.AnalyticsAPI;
 using PixiEditor.Models.ExceptionHandling;
 using PixiEditor.Platform;
 using PixiEditor.ViewModels.SubViewModels;
+using PixiEditor.Views.Rendering;
 using ViewModelMain = PixiEditor.ViewModels.ViewModelMain;
 using ViewModels_ViewModelMain = PixiEditor.ViewModels.ViewModelMain;
 
@@ -71,7 +72,9 @@ internal partial class MainWindow : Window
 
         SkiaDrawingBackend skiaDrawingBackend = new SkiaDrawingBackend();
         skiaDrawingBackend.GraphicsContext = GetOpenGlGrContext();
-        DrawingBackendApi.SetupBackend(skiaDrawingBackend, (a) => Dispatcher.UIThread.Invoke(a));
+        
+        AvaloniaRenderingServer renderingServer = new AvaloniaRenderingServer();
+        DrawingBackendApi.SetupBackend(skiaDrawingBackend, renderingServer);
 
         preferences = services.GetRequiredService<IPreferences>();
         platform = services.GetRequiredService<IPlatform>();

+ 18 - 0
src/PixiEditor/Views/Rendering/AvaloniaRenderingServer.cs

@@ -0,0 +1,18 @@
+using Avalonia;
+using Avalonia.Controls;
+using Avalonia.Media;
+using Avalonia.Rendering.SceneGraph;
+using Avalonia.Skia;
+using Avalonia.Threading;
+using PixiEditor.DrawingApi.Core;
+using PixiEditor.DrawingApi.Core.Bridge;
+using PixiEditor.DrawingApi.Core.Surfaces;
+using PixiEditor.DrawingApi.Skia.Extensions;
+using PixiEditor.Views.Visuals;
+
+namespace PixiEditor.Views.Rendering;
+
+public class AvaloniaRenderingServer : IRenderingServer
+{
+    public Action<Action> Invoke { get; } = action => Dispatcher.UIThread.Invoke(action);
+}

+ 5 - 11
src/PixiEditor/Views/Rendering/Scene.cs

@@ -151,8 +151,7 @@ internal class Scene : Zoombox.Zoombox, ICustomHitTest
             FlipX, FlipY,
             dirtyRect,
             Bounds,
-            sceneOpacity,
-            Channels.GetColorMatrix());
+            sceneOpacity);
 
         var matrix = CalculateTransformMatrix();
         context.PushTransform(matrix);
@@ -485,7 +484,6 @@ internal class DrawSceneOperation : SkiaDrawOperation
     public bool FlipX { get; set; }
     public bool FlipY { get; set; }
     public Rect ViewportBounds { get; }
-    public ColorMatrix ColorMatrix { get; }
 
     public RectI SurfaceRectToRender { get; }
 
@@ -494,8 +492,7 @@ internal class DrawSceneOperation : SkiaDrawOperation
     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,
-        ColorMatrix colorMatrix) : base(dirtyBounds)
+        double angle, bool flipX, bool flipY, Rect dirtyBounds, Rect viewportBounds, double opacity) : base(dirtyBounds)
     {
         Surface = surface;
         Document = document;
@@ -504,7 +501,6 @@ internal class DrawSceneOperation : SkiaDrawOperation
         Angle = angle;
         FlipX = flipX;
         FlipY = flipY;
-        ColorMatrix = colorMatrix;
         ViewportBounds = viewportBounds;
         _paint.Color = _paint.Color.WithAlpha((byte)(opacity * 255));
         SurfaceRectToRender = FindRectToRender((float)scale);
@@ -527,11 +523,9 @@ internal class DrawSceneOperation : SkiaDrawOperation
         using var ctx = DrawingBackendApi.Current.RenderOnDifferentGrContext(lease.GrContext);
 
 
-        var matrixValues = new float[ColorMatrix.Width * ColorMatrix.Height];
-        ColorMatrix.TryGetMembers(matrixValues);
-
-        _paint.ColorFilter = SKColorFilter.CreateColorMatrix(matrixValues);
-
+        /*var matrixValues = new float[ColorMatrix.Width * ColorMatrix.Height];
+        ColorMatrix.TryGetMembers(matrixValues);*/
+        
         if (!hardwareAccelerationAvailable)
         {
             // snapshotting wanted region on CPU is faster than rendering whole surface on CPU,