Browse Source

replace IBuffer<T> with IMemoryOwner<T>

af/merge-core
Anton Firszov 8 years ago
parent
commit
12bcdbb49a
  1. 3
      src/ImageSharp.Drawing/Primitives/ShapeRegion.cs
  2. 6
      src/ImageSharp.Drawing/Processing/BrushApplicator.cs
  3. 5
      src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs
  4. 5
      src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs
  5. 3
      src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs
  6. 4
      src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs
  7. 6
      src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs
  8. 5
      src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs
  9. 5
      src/ImageSharp.Drawing/Processing/RecolorBrush{TPixel}.cs
  10. 6
      src/ImageSharp.Drawing/Processing/SolidBrush{TPixel}.cs
  11. 9
      src/ImageSharp/Common/Helpers/ParallelFor.cs
  12. 7
      src/ImageSharp/Formats/Gif/LzwDecoder.cs
  13. 5
      src/ImageSharp/Formats/Gif/LzwEncoder.cs
  14. 2
      src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs
  15. 3
      src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs
  16. 3
      src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTable.cs
  17. 3
      src/ImageSharp/Image.WrapMemory.cs
  18. 2
      src/ImageSharp/ImageFrameCollection.cs
  19. 7
      src/ImageSharp/ImageFrame{TPixel}.cs
  20. 4
      src/ImageSharp/Image{TPixel}.cs
  21. 1
      src/ImageSharp/Memory/ArrayPoolMemoryAllocator.Buffer{T}.cs
  22. 2
      src/ImageSharp/Memory/ArrayPoolMemoryAllocator.cs
  23. 2
      src/ImageSharp/Memory/BasicArrayBuffer.cs
  24. 54
      src/ImageSharp/Memory/Buffer2D{T}.cs
  25. 20
      src/ImageSharp/Memory/BufferExtensions.cs
  26. 9
      src/ImageSharp/Memory/BufferManager.cs
  27. 34
      src/ImageSharp/Memory/ConsumedBuffer.cs
  28. 38
      src/ImageSharp/Memory/IBuffer{T}.cs
  29. 4
      src/ImageSharp/Memory/IManagedByteBuffer.cs
  30. 4
      src/ImageSharp/Memory/ManagedBufferBase.cs
  31. 6
      src/ImageSharp/Memory/MemoryAllocator.cs
  32. 6
      src/ImageSharp/Memory/MemoryAllocatorExtensions.cs
  33. 6
      src/ImageSharp/Memory/SimpleGcMemoryAllocator.cs
  34. 52
      src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs
  35. 12
      src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.tt
  36. 5
      src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor.cs
  37. 5
      src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor.cs
  38. 5
      src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs
  39. 5
      src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs
  40. 4
      src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs
  41. 45
      src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs
  42. 3
      src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs
  43. 5
      src/ImageSharp/Processing/Processors/Transforms/WeightsWindow.cs
  44. 23
      tests/ImageSharp.Benchmarks/Color/Bulk/PackFromVector4.cs
  45. 18
      tests/ImageSharp.Benchmarks/Color/Bulk/PackFromXyzw.cs
  46. 20
      tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4.cs
  47. 19
      tests/ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs
  48. 18
      tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs
  49. 8
      tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsPixel.cs
  50. 4
      tests/ImageSharp.Benchmarks/Samplers/Glow.cs
  51. 7
      tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs
  52. 16
      tests/ImageSharp.Tests/Memory/ArrayPoolMemoryManagerTests.cs
  53. 101
      tests/ImageSharp.Tests/Memory/Buffer2DTests.cs
  54. 27
      tests/ImageSharp.Tests/Memory/BufferTestSuite.cs
  55. 9
      tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs
  56. 7
      tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingBridge.cs
  57. 3
      tests/ImageSharp.Tests/TestUtilities/TestMemoryAllocator.cs
  58. 3
      tests/ImageSharp.Tests/TestUtilities/TestMemoryManager.cs

3
src/ImageSharp.Drawing/Primitives/ShapeRegion.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using SixLabors.Memory;
using SixLabors.Primitives;
using SixLabors.Shapes;
@ -45,7 +46,7 @@ namespace SixLabors.ImageSharp.Primitives
var start = new PointF(this.Bounds.Left - 1, y);
var end = new PointF(this.Bounds.Right + 1, y);
using (IBuffer<PointF> tempBuffer = configuration.MemoryAllocator.Allocate<PointF>(buffer.Length))
using (IMemoryOwner<PointF> tempBuffer = configuration.MemoryAllocator.Allocate<PointF>(buffer.Length))
{
Span<PointF> innerBuffer = tempBuffer.GetSpan();
int count = this.Shape.FindIntersections(start, end, innerBuffer);

6
src/ImageSharp.Drawing/Processing/BrushApplicator.cs

@ -2,6 +2,8 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
@ -65,8 +67,8 @@ namespace SixLabors.ImageSharp.Processing
{
MemoryAllocator memoryAllocator = this.Target.MemoryAllocator;
using (IBuffer<float> amountBuffer = memoryAllocator.Allocate<float>(scanline.Length))
using (IBuffer<TPixel> overlay = memoryAllocator.Allocate<TPixel>(scanline.Length))
using (IMemoryOwner<float> amountBuffer = memoryAllocator.Allocate<float>(scanline.Length))
using (IMemoryOwner<TPixel> overlay = memoryAllocator.Allocate<TPixel>(scanline.Length))
{
Span<float> amountSpan = amountBuffer.GetSpan();
Span<TPixel> overlaySpan = overlay.GetSpan();

5
src/ImageSharp.Drawing/Processing/ImageBrush{TPixel}.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
@ -118,8 +119,8 @@ namespace SixLabors.ImageSharp.Processing
internal override void Apply(Span<float> scanline, int x, int y)
{
// Create a span for colors
using (IBuffer<float> amountBuffer = this.Target.MemoryAllocator.Allocate<float>(scanline.Length))
using (IBuffer<TPixel> overlay = this.Target.MemoryAllocator.Allocate<TPixel>(scanline.Length))
using (IMemoryOwner<float> amountBuffer = this.Target.MemoryAllocator.Allocate<float>(scanline.Length))
using (IMemoryOwner<TPixel> overlay = this.Target.MemoryAllocator.Allocate<TPixel>(scanline.Length))
{
Span<float> amountSpan = amountBuffer.GetSpan();
Span<TPixel> overlaySpan = overlay.GetSpan();

5
src/ImageSharp.Drawing/Processing/PatternBrush{TPixel}.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Numerics;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
@ -153,8 +154,8 @@ namespace SixLabors.ImageSharp.Processing
int patternY = y % this.pattern.Rows;
MemoryAllocator memoryAllocator = this.Target.MemoryAllocator;
using (IBuffer<float> amountBuffer = memoryAllocator.Allocate<float>(scanline.Length))
using (IBuffer<TPixel> overlay = memoryAllocator.Allocate<TPixel>(scanline.Length))
using (IMemoryOwner<float> amountBuffer = memoryAllocator.Allocate<float>(scanline.Length))
using (IMemoryOwner<TPixel> overlay = memoryAllocator.Allocate<TPixel>(scanline.Length))
{
Span<float> amountSpan = amountBuffer.GetSpan();
Span<TPixel> overlaySpan = overlay.GetSpan();

3
src/ImageSharp.Drawing/Processing/Processors/Drawing/DrawImageProcessor.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
@ -134,7 +135,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
MemoryAllocator memoryAllocator = this.Image.GetConfiguration().MemoryAllocator;
using (IBuffer<float> amount = memoryAllocator.Allocate<float>(width))
using (IMemoryOwner<float> amount = memoryAllocator.Allocate<float>(width))
{
amount.GetSpan().Fill(this.Opacity);

4
src/ImageSharp.Drawing/Processing/Processors/Drawing/FillProcessor.cs

@ -2,10 +2,10 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Processing;
using SixLabors.Memory;
using SixLabors.Primitives;
@ -76,7 +76,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
startY = 0;
}
using (IBuffer<float> amount = source.MemoryAllocator.Allocate<float>(width))
using (IMemoryOwner<float> amount = source.MemoryAllocator.Allocate<float>(width))
using (BrushApplicator<TPixel> applicator = this.brush.CreateApplicator(
source,
sourceRectangle,

6
src/ImageSharp.Drawing/Processing/Processors/Drawing/FillRegionProcessor.cs

@ -2,6 +2,8 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.ImageSharp.Primitives;
using SixLabors.ImageSharp.Utils;
@ -94,8 +96,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Drawing
using (BrushApplicator<TPixel> applicator = this.Brush.CreateApplicator(source, rect, this.Options))
{
int scanlineWidth = maxX - minX;
using (IBuffer<float> bBuffer = source.MemoryAllocator.Allocate<float>(maxIntersections))
using (IBuffer<float> bScanline = source.MemoryAllocator.Allocate<float>(scanlineWidth))
using (IMemoryOwner<float> bBuffer = source.MemoryAllocator.Allocate<float>(maxIntersections))
using (IMemoryOwner<float> bScanline = source.MemoryAllocator.Allocate<float>(scanlineWidth))
{
bool scanlineDirty = true;
float subpixelFraction = 1f / subpixelCount;

5
src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Collections.Generic;
using SixLabors.Fonts;
using SixLabors.ImageSharp.Advanced;
@ -336,8 +337,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text
// take the path inside the path builder, scan thing and generate a Buffer2d representing the glyph and cache it.
Buffer2D<float> fullBuffer = this.MemoryAllocator.Allocate2D<float>(size.Width + 1, size.Height + 1, AllocationOptions.Clean);
using (IBuffer<float> bufferBacking = this.MemoryAllocator.Allocate<float>(path.MaxIntersections))
using (IBuffer<PointF> rowIntersectionBuffer = this.MemoryAllocator.Allocate<PointF>(size.Width))
using (IMemoryOwner<float> bufferBacking = this.MemoryAllocator.Allocate<float>(path.MaxIntersections))
using (IMemoryOwner<PointF> rowIntersectionBuffer = this.MemoryAllocator.Allocate<PointF>(size.Width))
{
float subpixelFraction = 1f / subpixelCount;
float subpixelFractionPoint = subpixelFraction / subpixelCount;

5
src/ImageSharp.Drawing/Processing/RecolorBrush{TPixel}.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Numerics;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
@ -138,8 +139,8 @@ namespace SixLabors.ImageSharp.Processing
{
MemoryAllocator memoryAllocator = this.Target.MemoryAllocator;
using (IBuffer<float> amountBuffer = memoryAllocator.Allocate<float>(scanline.Length))
using (IBuffer<TPixel> overlay = memoryAllocator.Allocate<TPixel>(scanline.Length))
using (IMemoryOwner<float> amountBuffer = memoryAllocator.Allocate<float>(scanline.Length))
using (IMemoryOwner<TPixel> overlay = memoryAllocator.Allocate<TPixel>(scanline.Length))
{
Span<float> amountSpan = amountBuffer.GetSpan();
Span<TPixel> overlaySpan = overlay.GetSpan();

6
src/ImageSharp.Drawing/Processing/SolidBrush{TPixel}.cs

@ -2,6 +2,8 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
@ -65,7 +67,7 @@ namespace SixLabors.ImageSharp.Processing
/// <summary>
/// Gets the colors.
/// </summary>
protected IBuffer<TPixel> Colors { get; }
protected IMemoryOwner<TPixel> Colors { get; }
/// <summary>
/// Gets the color for a single pixel.
@ -96,7 +98,7 @@ namespace SixLabors.ImageSharp.Processing
}
else
{
using (IBuffer<float> amountBuffer = memoryAllocator.Allocate<float>(scanline.Length))
using (IMemoryOwner<float> amountBuffer = memoryAllocator.Allocate<float>(scanline.Length))
{
Span<float> amountSpan = amountBuffer.GetSpan();

9
src/ImageSharp/Common/Helpers/ParallelFor.cs

@ -1,4 +1,5 @@
using System;
using System.Buffers;
using System.Threading.Tasks;
using SixLabors.Memory;
@ -32,23 +33,23 @@ namespace SixLabors.ImageSharp
int toExclusive,
Configuration configuration,
int bufferLength,
Action<int, IBuffer<T>> body)
Action<int, IMemoryOwner<T>> body)
where T : struct
{
MemoryAllocator memoryAllocator = configuration.MemoryAllocator;
ParallelOptions parallelOptions = configuration.ParallelOptions;
IBuffer<T> InitBuffer()
IMemoryOwner<T> InitBuffer()
{
return memoryAllocator.Allocate<T>(bufferLength);
}
void CleanUpBuffer(IBuffer<T> buffer)
void CleanUpBuffer(IMemoryOwner<T> buffer)
{
buffer.Dispose();
}
IBuffer<T> BodyFunc(int i, ParallelLoopState state, IBuffer<T> buffer)
IMemoryOwner<T> BodyFunc(int i, ParallelLoopState state, IMemoryOwner<T> buffer)
{
body(i, buffer);
return buffer;

7
src/ImageSharp/Formats/Gif/LzwDecoder.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@ -32,17 +33,17 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <summary>
/// The prefix buffer.
/// </summary>
private readonly IBuffer<int> prefix;
private readonly IMemoryOwner<int> prefix;
/// <summary>
/// The suffix buffer.
/// </summary>
private readonly IBuffer<int> suffix;
private readonly IMemoryOwner<int> suffix;
/// <summary>
/// The pixel stack buffer.
/// </summary>
private readonly IBuffer<int> pixelStack;
private readonly IMemoryOwner<int> pixelStack;
/// <summary>
/// Initializes a new instance of the <see cref="LzwDecoder"/> class

5
src/ImageSharp/Formats/Gif/LzwEncoder.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@ -66,12 +67,12 @@ namespace SixLabors.ImageSharp.Formats.Gif
/// <summary>
/// The hash table.
/// </summary>
private readonly IBuffer<int> hashTable;
private readonly IMemoryOwner<int> hashTable;
/// <summary>
/// The code table.
/// </summary>
private readonly IBuffer<int> codeTable;
private readonly IMemoryOwner<int> codeTable;
/// <summary>
/// Define the storage for the packet accumulator.

2
src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegBlockPostProcessor.cs

@ -9,7 +9,7 @@ using SixLabors.Primitives;
namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
{
/// <summary>
/// Encapsulates the implementation of processing "raw" <see cref="IBuffer{T}"/>-s into Jpeg image channels.
/// Encapsulates the implementation of processing "raw" jpeg buffers into Jpeg image channels.
/// </summary>
[StructLayout(LayoutKind.Sequential)]
internal struct JpegBlockPostProcessor

3
src/ImageSharp/Formats/Jpeg/Components/Decoder/JpegImagePostProcessor.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Linq;
using System.Numerics;
using SixLabors.ImageSharp.Advanced;
@ -37,7 +38,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.Components.Decoder
/// <summary>
/// Temporal buffer to store a row of colors.
/// </summary>
private readonly IBuffer<Vector4> rgbaBuffer;
private readonly IMemoryOwner<Vector4> rgbaBuffer;
/// <summary>
/// The <see cref="JpegColorConverter"/> corresponding to the current <see cref="JpegColorSpace"/> determined by <see cref="IRawJpegData.ColorSpace"/>.

3
src/ImageSharp/Formats/Jpeg/PdfJsPort/Components/PdfJsHuffmanTable.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using SixLabors.Memory;
@ -48,7 +49,7 @@ namespace SixLabors.ImageSharp.Formats.Jpeg.PdfJsPort.Components
public PdfJsHuffmanTable(MemoryAllocator memoryAllocator, ReadOnlySpan<byte> count, ReadOnlySpan<byte> values)
{
const int Length = 257;
using (IBuffer<short> huffcode = memoryAllocator.Allocate<short>(Length))
using (IMemoryOwner<short> huffcode = memoryAllocator.Allocate<short>(Length))
{
ref short huffcodeRef = ref MemoryMarshal.GetReference(huffcode.GetSpan());

3
src/ImageSharp/Image.WrapMemory.cs

@ -34,8 +34,7 @@ namespace SixLabors.ImageSharp
ImageMetaData metaData)
where TPixel : struct, IPixel<TPixel>
{
var buffer = new ConsumedBuffer<TPixel>(pixelMemory);
return new Image<TPixel>(config, buffer, width, height, metaData);
return new Image<TPixel>(config, pixelMemory, width, height, metaData);
}
/// <summary>

2
src/ImageSharp/ImageFrameCollection.cs

@ -30,7 +30,7 @@ namespace SixLabors.ImageSharp
this.frames.Add(new ImageFrame<TPixel>(parent.GetConfiguration(), width, height, backgroundColor));
}
internal ImageFrameCollection(Image<TPixel> parent, int width, int height, IBuffer<TPixel> consumedBuffer)
internal ImageFrameCollection(Image<TPixel> parent, int width, int height, Memory<TPixel> consumedBuffer)
{
Guard.NotNull(parent, nameof(parent));

7
src/ImageSharp/ImageFrame{TPixel}.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Threading.Tasks;
@ -94,7 +95,7 @@ namespace SixLabors.ImageSharp
/// <summary>
/// Initializes a new instance of the <see cref="ImageFrame{TPixel}" /> class wrapping an existing buffer.
/// </summary>
internal ImageFrame(Configuration configuration, int width, int height, IBuffer<TPixel> consumedBuffer)
internal ImageFrame(Configuration configuration, int width, int height, Memory<TPixel> consumedBuffer)
: this(configuration, width, height, consumedBuffer, new ImageFrameMetaData())
{
}
@ -106,7 +107,7 @@ namespace SixLabors.ImageSharp
Configuration configuration,
int width,
int height,
IBuffer<TPixel> consumedBuffer,
Memory<TPixel> consumedBuffer,
ImageFrameMetaData metaData)
{
Guard.NotNull(configuration, nameof(configuration));
@ -272,7 +273,7 @@ namespace SixLabors.ImageSharp
this.Height,
this.configuration,
this.Width,
(int y, IBuffer<Vector4> tempRowBuffer) =>
(int y, IMemoryOwner<Vector4> tempRowBuffer) =>
{
Span<TPixel> sourceRow = this.GetPixelRowSpan(y);
Span<TPixel2> targetRow = target.GetPixelRowSpan(y);

4
src/ImageSharp/Image{TPixel}.cs

@ -86,7 +86,7 @@ namespace SixLabors.ImageSharp
/// Initializes a new instance of the <see cref="Image{TPixel}"/> class
/// consuming an external buffer instance.
/// </summary>
internal Image(Configuration configuration, IBuffer<TPixel> consumedBuffer, int width, int height)
internal Image(Configuration configuration, Memory<TPixel> consumedBuffer, int width, int height)
: this(configuration, consumedBuffer, width, height, new ImageMetaData())
{
}
@ -95,7 +95,7 @@ namespace SixLabors.ImageSharp
/// Initializes a new instance of the <see cref="Image{TPixel}"/> class
/// consuming an external buffer instance.
/// </summary>
internal Image(Configuration configuration, IBuffer<TPixel> consumedBuffer, int width, int height, ImageMetaData metadata)
internal Image(Configuration configuration, Memory<TPixel> consumedBuffer, int width, int height, ImageMetaData metadata)
{
this.configuration = configuration;
this.PixelType = new PixelTypeInfo(Unsafe.SizeOf<TPixel>() * 8);

1
src/ImageSharp/Memory/ArrayPoolMemoryAllocator.Buffer{T}.cs

@ -14,7 +14,6 @@ namespace SixLabors.Memory
{
/// <summary>
/// The buffer implementation of <see cref="ArrayPoolMemoryAllocator"/>.
/// In this implementation <see cref="IBuffer{T}.Memory"/> is owned.
/// </summary>
private class Buffer<T> : ManagedBufferBase<T>
where T : struct

2
src/ImageSharp/Memory/ArrayPoolMemoryAllocator.cs

@ -89,7 +89,7 @@ namespace SixLabors.Memory
}
/// <inheritdoc />
internal override IBuffer<T> Allocate<T>(int length, AllocationOptions options)
internal override IMemoryOwner<T> Allocate<T>(int length, AllocationOptions options = AllocationOptions.None)
{
int itemSizeBytes = Unsafe.SizeOf<T>();
int bufferSizeInBytes = length * itemSizeBytes;

2
src/ImageSharp/Memory/BasicArrayBuffer.cs

@ -7,7 +7,7 @@ using System.Runtime.CompilerServices;
namespace SixLabors.Memory
{
/// <summary>
/// Wraps an array as an <see cref="IBuffer{T}"/> instance. In this implementation <see cref="IBuffer{T}.Memory"/> is owned.
/// Wraps an array as an <see cref="IManagedByteBuffer"/> instance.
/// </summary>
internal class BasicArrayBuffer<T> : ManagedBufferBase<T>
where T : struct

54
src/ImageSharp/Memory/Buffer2D{T}.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Runtime.CompilerServices;
using SixLabors.Primitives;
@ -15,19 +16,31 @@ namespace SixLabors.Memory
internal sealed class Buffer2D<T> : IDisposable
where T : struct
{
private BufferManager<T> buffer;
/// <summary>
/// Initializes a new instance of the <see cref="Buffer2D{T}"/> class.
/// </summary>
/// <param name="wrappedBuffer">The buffer to wrap</param>
/// <param name="width">The number of elements in a row</param>
/// <param name="height">The number of rows</param>
public Buffer2D(IBuffer<T> wrappedBuffer, int width, int height)
public Buffer2D(BufferManager<T> wrappedBuffer, int width, int height)
{
this.Buffer = wrappedBuffer;
this.buffer = wrappedBuffer;
this.Width = width;
this.Height = height;
}
public Buffer2D(IMemoryOwner<T> ownedMemory, int width, int height)
: this(new BufferManager<T>(ownedMemory), width, height)
{
}
public Buffer2D(Memory<T> observedMemory, int width, int height)
: this(new BufferManager<T>(observedMemory), width, height)
{
}
/// <summary>
/// Gets the width.
/// </summary>
@ -39,13 +52,13 @@ namespace SixLabors.Memory
public int Height { get; private set; }
/// <summary>
/// Gets the backing <see cref="IBuffer{T}"/>
/// Gets the backing <see cref="BufferManager{T}"/>
/// </summary>
public IBuffer<T> Buffer { get; private set; }
public BufferManager<T> Buffer => this.buffer;
public Memory<T> Memory => this.Buffer.Memory;
public Span<T> Span => this.Buffer.GetSpan();
public Span<T> Span => this.Memory.Span;
/// <summary>
/// Gets a reference to the element at the specified position.
@ -60,7 +73,7 @@ namespace SixLabors.Memory
{
ImageSharp.DebugGuard.MustBeLessThan(x, this.Width, nameof(x));
DebugGuard.MustBeLessThan(y, this.Height, nameof(y));
Span<T> span = this.Buffer.GetSpan();
Span<T> span = this.Span;
return ref span[(this.Width * y) + x];
}
}
@ -70,7 +83,7 @@ namespace SixLabors.Memory
/// </summary>
public void Dispose()
{
this.Buffer?.Dispose();
this.Buffer.Dispose();
}
/// <summary>
@ -79,36 +92,15 @@ namespace SixLabors.Memory
/// </summary>
public static void SwapOrCopyContent(Buffer2D<T> destination, Buffer2D<T> source)
{
if (source.Buffer.IsMemoryOwner && destination.Buffer.IsMemoryOwner)
{
SwapContents(destination, source);
}
else
{
if (destination.Size() != source.Size())
{
throw new InvalidOperationException("SwapOrCopyContents(): buffers should both owned or the same size!");
}
source.Span.CopyTo(destination.Span);
}
BufferManager<T>.SwapOrCopyContent(ref destination.buffer, ref source.buffer);
SwapDimensionData(destination, source);
}
/// <summary>
/// Swap the contents (<see cref="Buffer"/>, <see cref="Width"/>, <see cref="Height"/>) of the two buffers.
/// Useful to transfer the contents of a temporary <see cref="Buffer2D{T}"/> to a persistent <see cref="SixLabors.ImageSharp.ImageFrame{T}.PixelBuffer"/>
/// </summary>
/// <param name="a">The first buffer</param>
/// <param name="b">The second buffer</param>
private static void SwapContents(Buffer2D<T> a, Buffer2D<T> b)
private static void SwapDimensionData(Buffer2D<T> a, Buffer2D<T> b)
{
Size aSize = a.Size();
Size bSize = b.Size();
IBuffer<T> temp = a.Buffer;
a.Buffer = b.Buffer;
b.Buffer = temp;
b.Width = aSize.Width;
b.Height = aSize.Height;

20
src/ImageSharp/Memory/BufferExtensions.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.IO;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@ -11,8 +12,12 @@ namespace SixLabors.Memory
internal static class BufferExtensions
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Length<T>(this IBuffer<T> buffer)
where T : struct => buffer.GetSpan().Length;
public static Span<T> GetSpan<T>(this IMemoryOwner<T> buffer)
=> buffer.Memory.Span;
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int Length<T>(this IMemoryOwner<T> buffer)
=> buffer.GetSpan().Length;
/// <summary>
/// Gets a <see cref="Span{T}"/> to an offseted position inside the buffer.
@ -21,8 +26,7 @@ namespace SixLabors.Memory
/// <param name="start">The start</param>
/// <returns>The <see cref="Span{T}"/></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<T> Slice<T>(this IBuffer<T> buffer, int start)
where T : struct
public static Span<T> Slice<T>(this IMemoryOwner<T> buffer, int start)
{
return buffer.GetSpan().Slice(start);
}
@ -35,8 +39,7 @@ namespace SixLabors.Memory
/// <param name="length">The length of the slice</param>
/// <returns>The <see cref="Span{T}"/></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<T> Slice<T>(this IBuffer<T> buffer, int start, int length)
where T : struct
public static Span<T> Slice<T>(this IMemoryOwner<T> buffer, int start, int length)
{
return buffer.GetSpan().Slice(start, length);
}
@ -46,13 +49,12 @@ namespace SixLabors.Memory
/// </summary>
/// <param name="buffer">The buffer</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void Clear<T>(this IBuffer<T> buffer)
where T : struct
public static void Clear<T>(this IMemoryOwner<T> buffer)
{
buffer.GetSpan().Clear();
}
public static ref T GetReference<T>(this IBuffer<T> buffer)
public static ref T GetReference<T>(this IMemoryOwner<T> buffer)
where T : struct =>
ref MemoryMarshal.GetReference(buffer.GetSpan());

9
src/ImageSharp/Memory/BufferManager.cs

@ -11,6 +11,11 @@ namespace SixLabors.Memory
/// Implements content transfer logic in <see cref="SwapOrCopyContent"/> that depends on the ownership status.
/// This is needed to transfer the contents of a temporary <see cref="Buffer2D{T}"/> to a persistent <see cref="SixLabors.ImageSharp.ImageFrame{T}.PixelBuffer"/>
/// </summary>
/// <remarks>
/// For a deeper understanding of the owner/consumer model, check out the following docs: <br/>
/// https://gist.github.com/GrabYourPitchforks/4c3e1935fd4d9fa2831dbfcab35dffc6
/// https://www.codemag.com/Article/1807051/Introducing-.NET-Core-2.1-Flagship-Types-Span-T-and-Memory-T
/// </remarks>
internal struct BufferManager<T> : IDisposable
{
public BufferManager(IMemoryOwner<T> memoryOwner)
@ -31,6 +36,10 @@ namespace SixLabors.Memory
public bool OwnsMemory => this.MemoryOwner != null;
public Span<T> GetSpan() => this.Memory.Span;
public void Clear() => this.Memory.Span.Clear();
/// <summary>
/// Swaps the contents of 'destination' with 'source' if the buffers are owned (1),
/// copies the contents of 'source' to 'destination' otherwise (2). Buffers should be of same size in case 2!

34
src/ImageSharp/Memory/ConsumedBuffer.cs

@ -1,34 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
namespace SixLabors.Memory
{
/// <summary>
/// A buffer implementation that consumes an existing <see cref="Memory{T}"/> instance.
/// The ownership of the memory remains external.
/// </summary>
/// <typeparam name="T">The value type</typeparam>
internal sealed class ConsumedBuffer<T> : IBuffer<T>
where T : struct
{
public ConsumedBuffer(Memory<T> memory)
{
this.Memory = memory;
}
public Memory<T> Memory { get; }
public bool IsMemoryOwner => false;
public Span<T> GetSpan()
{
return this.Memory.Span;
}
public void Dispose()
{
}
}
}

38
src/ImageSharp/Memory/IBuffer{T}.cs

@ -1,38 +0,0 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
namespace SixLabors.Memory
{
/// <summary>
/// Represents a contigous memory buffer of value-type items.
/// Depending on it's implementation, an <see cref="IBuffer{T}"/> can (1) OWN or (2) CONSUME the <see cref="Memory{T}"/> instance it wraps.
/// For a deeper understanding of the owner/consumer model, read the following docs: <br/>
/// https://gist.github.com/GrabYourPitchforks/4c3e1935fd4d9fa2831dbfcab35dffc6
/// TODO: We need more SOC here! For owned buffers we should use <see cref="IMemoryOwner{T}"/>.
/// For the consumption case we should not use buffers at all. We need to refactor Buffer2D{T} for this.
/// </summary>
/// <typeparam name="T">The value type</typeparam>
internal interface IBuffer<T> : IDisposable
where T : struct
{
/// <summary>
/// Gets a value indicating whether this instance is owning the <see cref="Memory"/>.
/// </summary>
bool IsMemoryOwner { get; }
/// <summary>
/// Gets the <see cref="Memory{T}"/> ownerd/consumed by this buffer.
/// </summary>
Memory<T> Memory { get; }
/// <summary>
/// Gets the span to the memory "promised" by this buffer when it's OWNED (1).
/// Gets `this.Memory.Span` when the buffer CONSUMED (2).
/// </summary>
/// <returns>The <see cref="Span{T}"/></returns>
Span<T> GetSpan();
}
}

4
src/ImageSharp/Memory/IManagedByteBuffer.cs

@ -1,12 +1,14 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Buffers;
namespace SixLabors.Memory
{
/// <summary>
/// Represents a byte buffer backed by a managed array. Useful for interop with classic .NET API-s.
/// </summary>
internal interface IManagedByteBuffer : IBuffer<byte>
internal interface IManagedByteBuffer : IMemoryOwner<byte>
{
/// <summary>
/// Gets the managed array backing this buffer instance.

4
src/ImageSharp/Memory/ManagedBufferBase.cs

@ -7,9 +7,9 @@ using System.Runtime.InteropServices;
namespace SixLabors.Memory
{
/// <summary>
/// Provides a base class for <see cref="IBuffer{T}"/> implementations by implementing pinning logic for <see cref="MemoryManager{T}"/> adaption.
/// Provides a base class for <see cref="IMemoryOwner{T}"/> implementations by implementing pinning logic for <see cref="MemoryManager{T}"/> adaption.
/// </summary>
internal abstract class ManagedBufferBase<T> : MemoryManager<T>, IBuffer<T>
internal abstract class ManagedBufferBase<T> : MemoryManager<T>
where T : struct
{
private GCHandle pinHandle;

6
src/ImageSharp/Memory/MemoryAllocator.cs

@ -1,6 +1,8 @@
// Copyright (c) Six Labors and contributors.
// Licensed under the Apache License, Version 2.0.
using System.Buffers;
namespace SixLabors.Memory
{
/// <summary>
@ -9,13 +11,13 @@ namespace SixLabors.Memory
public abstract class MemoryAllocator
{
/// <summary>
/// Allocates an <see cref="IBuffer{T}"/> of size <paramref name="length"/>.
/// Allocates an <see cref="IMemoryOwner{T}" />, holding a <see cref="System.Memory{T}"/> of length <paramref name="length"/>.
/// </summary>
/// <typeparam name="T">Type of the data stored in the buffer</typeparam>
/// <param name="length">Size of the buffer to allocate</param>
/// <param name="options">The allocation options.</param>
/// <returns>A buffer of values of type <typeparamref name="T"/>.</returns>
internal abstract IBuffer<T> Allocate<T>(int length, AllocationOptions options = AllocationOptions.None)
internal abstract IMemoryOwner<T> Allocate<T>(int length, AllocationOptions options = AllocationOptions.None)
where T : struct;
/// <summary>

6
src/ImageSharp/Memory/MemoryAllocatorExtensions.cs

@ -1,4 +1,6 @@
using SixLabors.Primitives;
using System.Buffers;
using SixLabors.Primitives;
namespace SixLabors.Memory
{
@ -14,7 +16,7 @@ namespace SixLabors.Memory
AllocationOptions options = AllocationOptions.None)
where T : struct
{
IBuffer<T> buffer = memoryAllocator.Allocate<T>(width * height, options);
IMemoryOwner<T> buffer = memoryAllocator.Allocate<T>(width * height, options);
return new Buffer2D<T>(buffer, width, height);
}

6
src/ImageSharp/Memory/SimpleGcMemoryAllocator.cs

@ -1,4 +1,6 @@
namespace SixLabors.Memory
using System.Buffers;
namespace SixLabors.Memory
{
/// <summary>
/// Implements <see cref="MemoryAllocator"/> by newing up arrays by the GC on every allocation requests.
@ -6,7 +8,7 @@
public sealed class SimpleGcMemoryAllocator : MemoryAllocator
{
/// <inheritdoc />
internal override IBuffer<T> Allocate<T>(int length, AllocationOptions options)
internal override IMemoryOwner<T> Allocate<T>(int length, AllocationOptions options = AllocationOptions.None)
{
return new BasicArrayBuffer<T>(new T[length]);
}

52
src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.cs

@ -2,13 +2,13 @@
// Licensed under the Apache License, Version 2.0.
// <auto-generated />
using System;
using System.Numerics;
using System.Buffers;
using SixLabors.Memory;
namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
using System;
using System.Numerics;
using SixLabors.Memory;
/// <summary>
/// Collection of Porter Duff alpha blending functions applying different composition models.
/// </summary>
@ -44,7 +44,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (IBuffer<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
using (IMemoryOwner<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
{
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -83,7 +83,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (IBuffer<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
using (IMemoryOwner<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
{
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -122,7 +122,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (IBuffer<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
using (IMemoryOwner<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
{
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -161,7 +161,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (IBuffer<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
using (IMemoryOwner<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
{
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -200,7 +200,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (IBuffer<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
using (IMemoryOwner<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
{
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -239,7 +239,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (IBuffer<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
using (IMemoryOwner<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
{
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -278,7 +278,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (IBuffer<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
using (IMemoryOwner<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
{
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -317,7 +317,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (IBuffer<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
using (IMemoryOwner<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
{
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -356,7 +356,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (IBuffer<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
using (IMemoryOwner<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
{
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -395,7 +395,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (IBuffer<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
using (IMemoryOwner<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
{
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -434,7 +434,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (IBuffer<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
using (IMemoryOwner<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
{
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -473,7 +473,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (IBuffer<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
using (IMemoryOwner<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
{
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -512,7 +512,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (IBuffer<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
using (IMemoryOwner<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
{
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -551,7 +551,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (IBuffer<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
using (IMemoryOwner<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
{
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -590,7 +590,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (IBuffer<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
using (IMemoryOwner<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
{
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -629,7 +629,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (IBuffer<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
using (IMemoryOwner<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
{
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -668,7 +668,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (IBuffer<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
using (IMemoryOwner<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
{
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -707,7 +707,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (IBuffer<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
using (IMemoryOwner<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
{
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -746,7 +746,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (IBuffer<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
using (IMemoryOwner<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
{
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -785,7 +785,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (IBuffer<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
using (IMemoryOwner<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
{
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -824,7 +824,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (IBuffer<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
using (IMemoryOwner<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
{
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);

12
src/ImageSharp/PixelFormats/PixelBlenders/DefaultPixelBlenders.Generated.tt

@ -12,13 +12,13 @@
// Licensed under the Apache License, Version 2.0.
// <auto-generated />
using System;
using System.Numerics;
using System.Buffers;
using SixLabors.Memory;
namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
{
using System;
using System.Numerics;
using SixLabors.Memory;
/// <summary>
/// Collection of Porter Duff alpha blending functions applying different composition models.
/// </summary>
@ -86,7 +86,7 @@ namespace SixLabors.ImageSharp.PixelFormats.PixelBlenders
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (IBuffer<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
using (IMemoryOwner<Vector4> buffer = memoryManager.Allocate<Vector4>(destination.Length * 3))
{
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);

5
src/ImageSharp/Processing/Processors/Normalization/HistogramEqualizationProcessor.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Numerics;
using System.Runtime.CompilerServices;
using SixLabors.ImageSharp.Advanced;
@ -43,8 +44,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Normalization
Span<TPixel> pixels = source.GetPixelSpan();
// Build the histogram of the grayscale levels.
using (IBuffer<int> histogramBuffer = memoryAllocator.Allocate<int>(this.LuminanceLevels, AllocationOptions.Clean))
using (IBuffer<int> cdfBuffer = memoryAllocator.Allocate<int>(this.LuminanceLevels, AllocationOptions.Clean))
using (IMemoryOwner<int> histogramBuffer = memoryAllocator.Allocate<int>(this.LuminanceLevels, AllocationOptions.Clean))
using (IMemoryOwner<int> cdfBuffer = memoryAllocator.Allocate<int>(this.LuminanceLevels, AllocationOptions.Clean))
{
Span<int> histogram = histogramBuffer.GetSpan();
for (int i = 0; i < pixels.Length; i++)

5
src/ImageSharp/Processing/Processors/Overlays/BackgroundColorProcessor.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
@ -65,8 +66,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
int width = maxX - minX;
using (IBuffer<TPixel> colors = source.MemoryAllocator.Allocate<TPixel>(width))
using (IBuffer<float> amount = source.MemoryAllocator.Allocate<float>(width))
using (IMemoryOwner<TPixel> colors = source.MemoryAllocator.Allocate<TPixel>(width))
using (IMemoryOwner<float> amount = source.MemoryAllocator.Allocate<float>(width))
{
// Be careful! Do not capture colorSpan & amountSpan in the lambda below!
Span<TPixel> colorSpan = colors.GetSpan();

5
src/ImageSharp/Processing/Processors/Overlays/GlowProcessor.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Numerics;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
@ -111,7 +112,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
}
int width = maxX - minX;
using (IBuffer<TPixel> rowColors = source.MemoryAllocator.Allocate<TPixel>(width))
using (IMemoryOwner<TPixel> rowColors = source.MemoryAllocator.Allocate<TPixel>(width))
{
// Be careful! Do not capture rowColorsSpan in the lambda below!
Span<TPixel> rowColorsSpan = rowColors.GetSpan();
@ -127,7 +128,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
configuration.ParallelOptions,
y =>
{
using (IBuffer<float> amounts = source.MemoryAllocator.Allocate<float>(width))
using (IMemoryOwner<float> amounts = source.MemoryAllocator.Allocate<float>(width))
{
Span<float> amountsSpan = amounts.GetSpan();
int offsetY = y - startY;

5
src/ImageSharp/Processing/Processors/Overlays/VignetteProcessor.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Numerics;
using System.Threading.Tasks;
using SixLabors.ImageSharp.Advanced;
@ -113,7 +114,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
}
int width = maxX - minX;
using (IBuffer<TPixel> rowColors = source.MemoryAllocator.Allocate<TPixel>(width))
using (IMemoryOwner<TPixel> rowColors = source.MemoryAllocator.Allocate<TPixel>(width))
{
// Be careful! Do not capture rowColorsSpan in the lambda below!
Span<TPixel> rowColorsSpan = rowColors.GetSpan();
@ -129,7 +130,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Overlays
configuration.ParallelOptions,
y =>
{
using (IBuffer<float> amounts = source.MemoryAllocator.Allocate<float>(width))
using (IMemoryOwner<float> amounts = source.MemoryAllocator.Allocate<float>(width))
{
Span<float> amountsSpan = amounts.GetSpan();
int offsetY = y - startY;

4
src/ImageSharp/Processing/Processors/Quantization/QuantizedFrame{TPixel}.cs

@ -2,6 +2,8 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
@ -15,7 +17,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
public class QuantizedFrame<TPixel> : IDisposable
where TPixel : struct, IPixel<TPixel>
{
private IBuffer<byte> pixels;
private IMemoryOwner<byte> pixels;
/// <summary>
/// Initializes a new instance of the <see cref="QuantizedFrame{TPixel}"/> class.

45
src/ImageSharp/Processing/Processors/Quantization/WuFrameQuantizer{TPixel}.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Numerics;
using System.Runtime.CompilerServices;
@ -70,37 +71,37 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
/// <summary>
/// Moment of <c>P(c)</c>.
/// </summary>
private IBuffer<long> vwt;
private IMemoryOwner<long> vwt;
/// <summary>
/// Moment of <c>r*P(c)</c>.
/// </summary>
private IBuffer<long> vmr;
private IMemoryOwner<long> vmr;
/// <summary>
/// Moment of <c>g*P(c)</c>.
/// </summary>
private IBuffer<long> vmg;
private IMemoryOwner<long> vmg;
/// <summary>
/// Moment of <c>b*P(c)</c>.
/// </summary>
private IBuffer<long> vmb;
private IMemoryOwner<long> vmb;
/// <summary>
/// Moment of <c>a*P(c)</c>.
/// </summary>
private IBuffer<long> vma;
private IMemoryOwner<long> vma;
/// <summary>
/// Moment of <c>c^2*P(c)</c>.
/// </summary>
private IBuffer<float> m2;
private IMemoryOwner<float> m2;
/// <summary>
/// Color space tag.
/// </summary>
private IBuffer<byte> tag;
private IMemoryOwner<byte> tag;
/// <summary>
/// Maximum allowed color depth
@ -467,18 +468,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
Span<long> vmaSpan = this.vma.GetSpan();
Span<float> m2Span = this.m2.GetSpan();
using (IBuffer<long> volume = memoryAllocator.Allocate<long>(IndexCount * IndexAlphaCount))
using (IBuffer<long> volumeR = memoryAllocator.Allocate<long>(IndexCount * IndexAlphaCount))
using (IBuffer<long> volumeG = memoryAllocator.Allocate<long>(IndexCount * IndexAlphaCount))
using (IBuffer<long> volumeB = memoryAllocator.Allocate<long>(IndexCount * IndexAlphaCount))
using (IBuffer<long> volumeA = memoryAllocator.Allocate<long>(IndexCount * IndexAlphaCount))
using (IBuffer<float> volume2 = memoryAllocator.Allocate<float>(IndexCount * IndexAlphaCount))
using (IBuffer<long> area = memoryAllocator.Allocate<long>(IndexAlphaCount))
using (IBuffer<long> areaR = memoryAllocator.Allocate<long>(IndexAlphaCount))
using (IBuffer<long> areaG = memoryAllocator.Allocate<long>(IndexAlphaCount))
using (IBuffer<long> areaB = memoryAllocator.Allocate<long>(IndexAlphaCount))
using (IBuffer<long> areaA = memoryAllocator.Allocate<long>(IndexAlphaCount))
using (IBuffer<float> area2 = memoryAllocator.Allocate<float>(IndexAlphaCount))
using (IMemoryOwner<long> volume = memoryAllocator.Allocate<long>(IndexCount * IndexAlphaCount))
using (IMemoryOwner<long> volumeR = memoryAllocator.Allocate<long>(IndexCount * IndexAlphaCount))
using (IMemoryOwner<long> volumeG = memoryAllocator.Allocate<long>(IndexCount * IndexAlphaCount))
using (IMemoryOwner<long> volumeB = memoryAllocator.Allocate<long>(IndexCount * IndexAlphaCount))
using (IMemoryOwner<long> volumeA = memoryAllocator.Allocate<long>(IndexCount * IndexAlphaCount))
using (IMemoryOwner<float> volume2 = memoryAllocator.Allocate<float>(IndexCount * IndexAlphaCount))
using (IMemoryOwner<long> area = memoryAllocator.Allocate<long>(IndexAlphaCount))
using (IMemoryOwner<long> areaR = memoryAllocator.Allocate<long>(IndexAlphaCount))
using (IMemoryOwner<long> areaG = memoryAllocator.Allocate<long>(IndexAlphaCount))
using (IMemoryOwner<long> areaB = memoryAllocator.Allocate<long>(IndexAlphaCount))
using (IMemoryOwner<long> areaA = memoryAllocator.Allocate<long>(IndexAlphaCount))
using (IMemoryOwner<float> area2 = memoryAllocator.Allocate<float>(IndexAlphaCount))
{
Span<long> volumeSpan = volume.GetSpan();
Span<long> volumeRSpan = volumeR.GetSpan();
@ -791,7 +792,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
this.colorCube = new Box[this.colors];
float[] vv = new float[this.colors];
ref var cube = ref this.colorCube[0];
ref Box cube = ref this.colorCube[0];
cube.R0 = cube.G0 = cube.B0 = cube.A0 = 0;
cube.R1 = cube.G1 = cube.B1 = IndexCount - 1;
cube.A1 = IndexAlphaCount - 1;
@ -800,8 +801,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Quantization
for (int i = 1; i < this.colors; i++)
{
ref var nextCube = ref this.colorCube[next];
ref var currentCube = ref this.colorCube[i];
ref Box nextCube = ref this.colorCube[next];
ref Box currentCube = ref this.colorCube[i];
if (this.Cut(ref nextCube, ref currentCube))
{
vv[next] = nextCube.Volume > 1 ? this.Variance(ref nextCube) : 0F;

3
src/ImageSharp/Processing/Processors/Transforms/ResizeProcessor.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Linq;
using System.Numerics;
@ -303,7 +304,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
sourceRectangle.Bottom,
configuration,
source.Width,
(int y, IBuffer<Vector4> tempRowBuffer) =>
(int y, IMemoryOwner<Vector4> tempRowBuffer) =>
{
ref Vector4 firstPassRow = ref MemoryMarshal.GetReference(firstPassPixels.GetRowSpan(y));
Span<TPixel> sourceRow = source.GetPixelRowSpan(y);

5
src/ImageSharp/Processing/Processors/Transforms/WeightsWindow.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@ -32,7 +33,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
/// <summary>
/// The buffer containing the weights values.
/// </summary>
private readonly IBuffer<float> buffer;
private readonly BufferManager<float> buffer;
/// <summary>
/// Initializes a new instance of the <see cref="WeightsWindow"/> struct.
@ -66,7 +67,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Transforms
/// </summary>
/// <returns>The <see cref="Span{T}"/></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public Span<float> GetWindowSpan() => this.buffer.Slice(this.flatStartIndex, this.Length);
public Span<float> GetWindowSpan() => this.buffer.GetSpan().Slice(this.flatStartIndex, this.Length);
/// <summary>
/// Computes the sum of vectors in 'rowSpan' weighted by weight values, pointed by this <see cref="WeightsWindow"/> instance.

23
tests/ImageSharp.Benchmarks/Color/Bulk/PackFromVector4.cs

@ -1,21 +1,24 @@
// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk
{
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BenchmarkDotNet.Attributes;
using SixLabors.Memory;
using SixLabors.ImageSharp.PixelFormats;
using System.Buffers;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using BenchmarkDotNet.Attributes;
using SixLabors.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk
{
[Config(typeof(Config.ShortClr))]
public abstract class PackFromVector4<TPixel>
where TPixel : struct, IPixel<TPixel>
{
private IBuffer<Vector4> source;
private IMemoryOwner<Vector4> source;
private IBuffer<TPixel> destination;
private IMemoryOwner<TPixel> destination;
[Params(16, 128, 512)]
public int Count { get; set; }

18
tests/ImageSharp.Benchmarks/Color/Bulk/PackFromXyzw.cs

@ -1,19 +1,21 @@
// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk
{
using System;
using BenchmarkDotNet.Attributes;
using System.Buffers;
using System;
using BenchmarkDotNet.Attributes;
using SixLabors.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk
{
public abstract class PackFromXyzw<TPixel>
where TPixel : struct, IPixel<TPixel>
{
private IBuffer<TPixel> destination;
private IMemoryOwner<TPixel> destination;
private IBuffer<byte> source;
private IMemoryOwner<byte> source;
[Params(16, 128, 1024)]
public int Count { get; set; }

20
tests/ImageSharp.Benchmarks/Color/Bulk/ToVector4.cs

@ -1,20 +1,22 @@
// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk
{
using System;
using System.Numerics;
using BenchmarkDotNet.Attributes;
using System.Buffers;
using System;
using System.Numerics;
using BenchmarkDotNet.Attributes;
using SixLabors.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk
{
public abstract class ToVector4<TPixel>
where TPixel : struct, IPixel<TPixel>
{
private IBuffer<TPixel> source;
private IMemoryOwner<TPixel> source;
private IBuffer<Vector4> destination;
private IMemoryOwner<Vector4> destination;
[Params(64, 300, 1024)]
public int Count { get; set; }

19
tests/ImageSharp.Benchmarks/Color/Bulk/ToXyz.cs

@ -1,20 +1,21 @@
// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk
{
using System;
using System.Numerics;
using BenchmarkDotNet.Attributes;
using System.Buffers;
using System;
using BenchmarkDotNet.Attributes;
using SixLabors.Memory;
using SixLabors.ImageSharp.PixelFormats;
using SixLabors.Memory;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk
{
public abstract class ToXyz<TPixel>
where TPixel : struct, IPixel<TPixel>
{
private IBuffer<TPixel> source;
private IMemoryOwner<TPixel> source;
private IBuffer<byte> destination;
private IMemoryOwner<byte> destination;
[Params(16, 128, 1024)]
public int Count { get; set; }

18
tests/ImageSharp.Benchmarks/Color/Bulk/ToXyzw.cs

@ -1,22 +1,20 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Buffers;
using BenchmarkDotNet.Attributes;
using SixLabors.Memory;
using SixLabors.ImageSharp.PixelFormats;
// ReSharper disable InconsistentNaming
namespace SixLabors.ImageSharp.Benchmarks.ColorSpaces.Bulk
{
using BenchmarkDotNet.Attributes;
using SixLabors.Memory;
using SixLabors.ImageSharp.PixelFormats;
public abstract class ToXyzw<TPixel>
where TPixel : struct, IPixel<TPixel>
{
private IBuffer<TPixel> source;
private IMemoryOwner<TPixel> source;
private IBuffer<byte> destination;
private IMemoryOwner<byte> destination;
[Params(16, 128, 1024)]
public int Count { get; set; }

8
tests/ImageSharp.Benchmarks/PixelBlenders/PorterDuffBulkVsPixel.cs

@ -3,6 +3,8 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
using System.Buffers;
namespace SixLabors.ImageSharp.Benchmarks
{
using System;
@ -24,7 +26,7 @@ namespace SixLabors.ImageSharp.Benchmarks
Guard.MustBeGreaterThanOrEqualTo(source.Length, destination.Length, nameof(source.Length));
Guard.MustBeGreaterThanOrEqualTo(amount.Length, destination.Length, nameof(amount.Length));
using (IBuffer<Vector4> buffer = Configuration.Default.MemoryAllocator.Allocate<Vector4>(destination.Length * 3))
using (IMemoryOwner<Vector4> buffer = Configuration.Default.MemoryAllocator.Allocate<Vector4>(destination.Length * 3))
{
Span<Vector4> destinationSpan = buffer.Slice(0, destination.Length);
Span<Vector4> backgroundSpan = buffer.Slice(destination.Length, destination.Length);
@ -59,7 +61,7 @@ namespace SixLabors.ImageSharp.Benchmarks
{
using (var image = new Image<Rgba32>(800, 800))
{
using (IBuffer<float> amounts = Configuration.Default.MemoryAllocator.Allocate<float>(image.Width))
using (IMemoryOwner<float> amounts = Configuration.Default.MemoryAllocator.Allocate<float>(image.Width))
{
amounts.GetSpan().Fill(1);
@ -80,7 +82,7 @@ namespace SixLabors.ImageSharp.Benchmarks
{
using (var image = new Image<Rgba32>(800, 800))
{
using (IBuffer<float> amounts = Configuration.Default.MemoryAllocator.Allocate<float>(image.Width))
using (IMemoryOwner<float> amounts = Configuration.Default.MemoryAllocator.Allocate<float>(image.Width))
{
amounts.GetSpan().Fill(1);
Buffer2D<Rgba32> pixels = image.GetRootFramePixelBuffer();

4
tests/ImageSharp.Benchmarks/Samplers/Glow.cs

@ -3,6 +3,8 @@
// Licensed under the Apache License, Version 2.0.
// </copyright>
using System.Buffers;
namespace SixLabors.ImageSharp.Benchmarks
{
@ -102,7 +104,7 @@ namespace SixLabors.ImageSharp.Benchmarks
}
int width = maxX - minX;
using (IBuffer<TPixel> rowColors = Configuration.Default.MemoryAllocator.Allocate<TPixel>(width))
using (IMemoryOwner<TPixel> rowColors = Configuration.Default.MemoryAllocator.Allocate<TPixel>(width))
{
Buffer2D<TPixel> sourcePixels = source.PixelBuffer;
rowColors.GetSpan().Fill(glowColor);

7
tests/ImageSharp.Tests/Image/ImageTests.WrapMemory.cs

@ -12,13 +12,6 @@ namespace SixLabors.ImageSharp.Tests
{
public class WrapMemory
{
[Fact]
public void ConsumedBuffer_IsMemoryOwner_ReturnsFalse()
{
var memory = new Memory<int>(new int[55]);
var buffer = new ConsumedBuffer<int>(memory);
Assert.False(buffer.IsMemoryOwner);
}
}
}
}

16
tests/ImageSharp.Tests/Memory/ArrayPoolMemoryManagerTests.cs

@ -3,6 +3,8 @@
// ReSharper disable InconsistentNaming
using System.Buffers;
using SixLabors.ImageSharp.PixelFormats;
namespace SixLabors.ImageSharp.Tests.Memory
@ -30,7 +32,7 @@ namespace SixLabors.ImageSharp.Tests.Memory
private bool CheckIsRentingPooledBuffer<T>(int length)
where T : struct
{
IBuffer<T> buffer = this.MemoryAllocator.Allocate<T>(length);
IMemoryOwner<T> buffer = this.MemoryAllocator.Allocate<T>(length);
ref T ptrToPrevPosition0 = ref buffer.GetReference();
buffer.Dispose();
@ -130,12 +132,12 @@ namespace SixLabors.ImageSharp.Tests.Memory
[InlineData(AllocationOptions.Clean)]
public void CleaningRequests_AreControlledByAllocationParameter_Clean(AllocationOptions options)
{
using (IBuffer<int> firstAlloc = this.MemoryAllocator.Allocate<int>(42))
using (IMemoryOwner<int> firstAlloc = this.MemoryAllocator.Allocate<int>(42))
{
firstAlloc.GetSpan().Fill(666);
}
using (IBuffer<int> secondAlloc = this.MemoryAllocator.Allocate<int>(42, options))
using (IMemoryOwner<int> secondAlloc = this.MemoryAllocator.Allocate<int>(42, options))
{
int expected = options == AllocationOptions.Clean ? 0 : 666;
Assert.Equal(expected, secondAlloc.GetSpan()[0]);
@ -147,7 +149,7 @@ namespace SixLabors.ImageSharp.Tests.Memory
[InlineData(true)]
public void ReleaseRetainedResources_ReplacesInnerArrayPool(bool keepBufferAlive)
{
IBuffer<int> buffer = this.MemoryAllocator.Allocate<int>(32);
IMemoryOwner<int> buffer = this.MemoryAllocator.Allocate<int>(32);
ref int ptrToPrev0 = ref MemoryMarshal.GetReference(buffer.GetSpan());
if (!keepBufferAlive)
@ -165,7 +167,7 @@ namespace SixLabors.ImageSharp.Tests.Memory
[Fact]
public void ReleaseRetainedResources_DisposingPreviouslyAllocatedBuffer_IsAllowed()
{
IBuffer<int> buffer = this.MemoryAllocator.Allocate<int>(32);
IMemoryOwner<int> buffer = this.MemoryAllocator.Allocate<int>(32);
this.MemoryAllocator.ReleaseRetainedResources();
buffer.Dispose();
}
@ -181,11 +183,11 @@ namespace SixLabors.ImageSharp.Tests.Memory
int arrayLengthThreshold = PoolSelectorThresholdInBytes / sizeof(int);
IBuffer<int> small = this.MemoryAllocator.Allocate<int>(arrayLengthThreshold - 1);
IMemoryOwner<int> small = this.MemoryAllocator.Allocate<int>(arrayLengthThreshold - 1);
ref int ptr2Small = ref small.GetReference();
small.Dispose();
IBuffer<int> large = this.MemoryAllocator.Allocate<int>(arrayLengthThreshold + 1);
IMemoryOwner<int> large = this.MemoryAllocator.Allocate<int>(arrayLengthThreshold + 1);
Assert.False(Unsafe.AreSame(ref ptr2Small, ref large.GetReference()));
}

101
tests/ImageSharp.Tests/Memory/Buffer2DTests.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@ -20,7 +21,7 @@ namespace SixLabors.ImageSharp.Tests.Memory
// ReSharper disable once ClassNeverInstantiated.Local
private class Assert : Xunit.Assert
{
public static void SpanPointsTo<T>(Span<T> span, IBuffer<T> buffer, int bufferOffset = 0)
public static void SpanPointsTo<T>(Span<T> span, IMemoryOwner<T> buffer, int bufferOffset = 0)
where T : struct
{
ref T actual = ref MemoryMarshal.GetReference(span);
@ -41,7 +42,7 @@ namespace SixLabors.ImageSharp.Tests.Memory
{
Assert.Equal(width, buffer.Width);
Assert.Equal(height, buffer.Height);
Assert.Equal(width * height, buffer.Buffer.Length());
Assert.Equal(width * height, buffer.Memory.Length);
}
}
@ -70,7 +71,7 @@ namespace SixLabors.ImageSharp.Tests.Memory
// Assert.Equal(width * y, span.Start);
Assert.Equal(width, span.Length);
Assert.SpanPointsTo(span, buffer.Buffer, width * y);
Assert.SpanPointsTo(span, buffer.Buffer.MemoryOwner, width * y);
}
}
@ -86,7 +87,7 @@ namespace SixLabors.ImageSharp.Tests.Memory
// Assert.Equal(width * y + x, span.Start);
Assert.Equal(width - x, span.Length);
Assert.SpanPointsTo(span, buffer.Buffer, width * y + x);
Assert.SpanPointsTo(span, buffer.Buffer.MemoryOwner, width * y + x);
}
}
@ -107,92 +108,24 @@ namespace SixLabors.ImageSharp.Tests.Memory
Assert.True(Unsafe.AreSame(ref expected, ref actual));
}
}
public class SwapOrCopyContent
{
private MemoryAllocator MemoryAllocator { get; } = new TestMemoryAllocator();
[Fact]
public void WhenBothBuffersAreMemoryOwners_ShouldSwap()
{
using (Buffer2D<int> a = this.MemoryAllocator.Allocate2D<int>(10, 5))
using (Buffer2D<int> b = this.MemoryAllocator.Allocate2D<int>(3, 7))
{
IBuffer<int> aa = a.Buffer;
IBuffer<int> bb = b.Buffer;
Buffer2D<int>.SwapOrCopyContent(a, b);
Assert.Equal(bb, a.Buffer);
Assert.Equal(aa, b.Buffer);
Assert.Equal(new Size(3, 7), a.Size());
Assert.Equal(new Size(10, 5), b.Size());
}
}
[Fact]
public void WhenDestIsNotMemoryOwner_SameSize_ShouldCopy()
[Fact]
public void SwapOrCopyContent()
{
using (Buffer2D<int> a = this.MemoryAllocator.Allocate2D<int>(10, 5))
using (Buffer2D<int> b = this.MemoryAllocator.Allocate2D<int>(3, 7))
{
var data = new Rgba32[3 * 7];
var color = new Rgba32(1, 2, 3, 4);
var mmg = new TestMemoryManager<Rgba32>(data);
var aBuff = new ConsumedBuffer<Rgba32>(mmg.Memory);
using (Buffer2D<Rgba32> a = new Buffer2D<Rgba32>(aBuff, 3, 7))
{
IBuffer<Rgba32> aa = a.Buffer;
IMemoryOwner<int> aa = a.Buffer.MemoryOwner;
IMemoryOwner<int> bb = b.Buffer.MemoryOwner;
// Precondition:
Assert.Equal(aBuff, aa);
Buffer2D<int>.SwapOrCopyContent(a, b);
using (Buffer2D<Rgba32> b = this.MemoryAllocator.Allocate2D<Rgba32>(3, 7))
{
IBuffer<Rgba32> bb = b.Buffer;
bb.GetSpan()[10] = color;
Assert.Equal(bb, a.Buffer.MemoryOwner);
Assert.Equal(aa, b.Buffer.MemoryOwner);
// Act:
Buffer2D<Rgba32>.SwapOrCopyContent(a, b);
// Assert:
Assert.Equal(aBuff, a.Buffer);
Assert.Equal(bb, b.Buffer);
}
// Assert:
Assert.Equal(color, a.Buffer.GetSpan()[10]);
}
Assert.Equal(new Size(3, 7), a.Size());
Assert.Equal(new Size(10, 5), b.Size());
}
[Fact]
public void WhenDestIsNotMemoryOwner_DifferentSize_Throws()
{
var data = new Rgba32[3 * 7];
var color = new Rgba32(1, 2, 3, 4);
data[10] = color;
var mmg = new TestMemoryManager<Rgba32>(data);
var aBuff = new ConsumedBuffer<Rgba32>(mmg.Memory);
using (Buffer2D<Rgba32> a = new Buffer2D<Rgba32>(aBuff, 3, 7))
{
IBuffer<Rgba32> aa = a.Buffer;
using (Buffer2D<Rgba32> b = this.MemoryAllocator.Allocate2D<Rgba32>(3, 8))
{
IBuffer<Rgba32> bb = b.Buffer;
Assert.ThrowsAny<InvalidOperationException>(
() =>
{
Buffer2D<Rgba32>.SwapOrCopyContent(a, b);
});
}
Assert.Equal(color, a.Buffer.GetSpan()[10]);
}
}
}
}
}

27
tests/ImageSharp.Tests/Memory/BufferTestSuite.cs

@ -63,15 +63,6 @@ namespace SixLabors.ImageSharp.Tests.Memory
public static readonly TheoryData<int> LenthValues = new TheoryData<int> { 0, 1, 7, 1023, 1024 };
[Fact]
public void IsMemoryOwner()
{
using (IBuffer<float> buffer = this.MemoryAllocator.Allocate<float>(42))
{
Assert.True(buffer.IsMemoryOwner);
}
}
[Theory]
[MemberData(nameof(LenthValues))]
public void HasCorrectLength_byte(int desiredLength)
@ -96,7 +87,7 @@ namespace SixLabors.ImageSharp.Tests.Memory
private void TestHasCorrectLength<T>(int desiredLength)
where T : struct
{
using (IBuffer<T> buffer = this.MemoryAllocator.Allocate<T>(desiredLength))
using (IMemoryOwner<T> buffer = this.MemoryAllocator.Allocate<T>(desiredLength))
{
Assert.Equal(desiredLength, buffer.GetSpan().Length);
}
@ -124,12 +115,12 @@ namespace SixLabors.ImageSharp.Tests.Memory
this.TestCanAllocateCleanBuffer<CustomStruct>(desiredLength);
}
private IBuffer<T> Allocate<T>(int desiredLength, AllocationOptions options, bool managedByteBuffer)
private IMemoryOwner<T> Allocate<T>(int desiredLength, AllocationOptions options, bool managedByteBuffer)
where T : struct
{
if (managedByteBuffer)
{
if (!(this.MemoryAllocator.AllocateManagedByteBuffer(desiredLength, options) is IBuffer<T> buffer))
if (!(this.MemoryAllocator.AllocateManagedByteBuffer(desiredLength, options) is IMemoryOwner<T> buffer))
{
throw new InvalidOperationException("typeof(T) != typeof(byte)");
}
@ -147,7 +138,7 @@ namespace SixLabors.ImageSharp.Tests.Memory
for (int i = 0; i < 10; i++)
{
using (IBuffer<T> buffer = this.Allocate<T>(desiredLength, AllocationOptions.Clean, testManagedByteBuffer))
using (IMemoryOwner<T> buffer = this.Allocate<T>(desiredLength, AllocationOptions.Clean, testManagedByteBuffer))
{
Assert.True(buffer.GetSpan().SequenceEqual(expected));
}
@ -172,7 +163,7 @@ namespace SixLabors.ImageSharp.Tests.Memory
private void TestSpanPropertyIsAlwaysTheSame<T>(int desiredLength, bool testManagedByteBuffer = false)
where T : struct
{
using (IBuffer<T> buffer = this.Allocate<T>(desiredLength, AllocationOptions.None, testManagedByteBuffer))
using (IMemoryOwner<T> buffer = this.Allocate<T>(desiredLength, AllocationOptions.None, testManagedByteBuffer))
{
ref T a = ref MemoryMarshal.GetReference(buffer.GetSpan());
ref T b = ref MemoryMarshal.GetReference(buffer.GetSpan());
@ -201,7 +192,7 @@ namespace SixLabors.ImageSharp.Tests.Memory
private void TestWriteAndReadElements<T>(int desiredLength, Func<int, T> getExpectedValue, bool testManagedByteBuffer = false)
where T : struct
{
using (IBuffer<T> buffer = this.Allocate<T>(desiredLength, AllocationOptions.None, testManagedByteBuffer))
using (IMemoryOwner<T> buffer = this.Allocate<T>(desiredLength, AllocationOptions.None, testManagedByteBuffer))
{
T[] expectedVals = new T[buffer.Length()];
@ -247,7 +238,7 @@ namespace SixLabors.ImageSharp.Tests.Memory
{
var dummy = default(T);
using (IBuffer<T> buffer = this.Allocate<T>(desiredLength, AllocationOptions.None, testManagedByteBuffer))
using (IMemoryOwner<T> buffer = this.Allocate<T>(desiredLength, AllocationOptions.None, testManagedByteBuffer))
{
Assert.ThrowsAny<Exception>(
() =>
@ -294,7 +285,7 @@ namespace SixLabors.ImageSharp.Tests.Memory
[Fact]
public void GetMemory_ReturnsValidMemory()
{
using (IBuffer<CustomStruct> buffer = this.MemoryAllocator.Allocate<CustomStruct>(42))
using (IMemoryOwner<CustomStruct> buffer = this.MemoryAllocator.Allocate<CustomStruct>(42))
{
Span<CustomStruct> span0 = buffer.GetSpan();
span0[10].A = 30;
@ -311,7 +302,7 @@ namespace SixLabors.ImageSharp.Tests.Memory
[Fact]
public unsafe void GetMemory_ResultIsPinnable()
{
using (IBuffer<int> buffer = this.MemoryAllocator.Allocate<int>(42))
using (IMemoryOwner<int> buffer = this.MemoryAllocator.Allocate<int>(42))
{
Span<int> span0 = buffer.GetSpan();
span0[10] = 30;

9
tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@ -57,8 +58,8 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
int times = 200000;
int count = 1024;
using (IBuffer<ImageSharp.PixelFormats.Rgba32> source = Configuration.Default.MemoryAllocator.Allocate<ImageSharp.PixelFormats.Rgba32>(count))
using (IBuffer<Vector4> dest = Configuration.Default.MemoryAllocator.Allocate<Vector4>(count))
using (IMemoryOwner<ImageSharp.PixelFormats.Rgba32> source = Configuration.Default.MemoryAllocator.Allocate<ImageSharp.PixelFormats.Rgba32>(count))
using (IMemoryOwner<Vector4> dest = Configuration.Default.MemoryAllocator.Allocate<Vector4>(count))
{
this.Measure(
times,
@ -537,7 +538,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
where TDest : struct
{
public TSource[] SourceBuffer { get; }
public IBuffer<TDest> ActualDestBuffer { get; }
public IMemoryOwner<TDest> ActualDestBuffer { get; }
public TDest[] ExpectedDestBuffer { get; }
public TestBuffers(TSource[] source, TDest[] expectedDest)
@ -586,7 +587,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
internal static void TestOperation<TSource, TDest>(
TSource[] source,
TDest[] expected,
Action<TSource[], IBuffer<TDest>> action)
Action<TSource[], IMemoryOwner<TDest>> action)
where TSource : struct
where TDest : struct
{

7
tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingBridge.cs

@ -2,6 +2,7 @@
// Licensed under the Apache License, Version 2.0.
using System;
using System.Buffers;
using System.Drawing;
using System.Drawing.Imaging;
@ -43,7 +44,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
var image = new Image<TPixel>(w, h);
using (IBuffer<Bgra32> workBuffer = Configuration.Default.MemoryAllocator.Allocate<Bgra32>(w))
using (IMemoryOwner<Bgra32> workBuffer = Configuration.Default.MemoryAllocator.Allocate<Bgra32>(w))
{
fixed (Bgra32* destPtr = &workBuffer.GetReference())
{
@ -89,7 +90,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
var image = new Image<TPixel>(w, h);
using (IBuffer<Bgr24> workBuffer = Configuration.Default.MemoryAllocator.Allocate<Bgr24>(w))
using (IMemoryOwner<Bgr24> workBuffer = Configuration.Default.MemoryAllocator.Allocate<Bgr24>(w))
{
fixed (Bgr24* destPtr = &workBuffer.GetReference())
{
@ -122,7 +123,7 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
long destRowByteCount = data.Stride;
long sourceRowByteCount = w * sizeof(Bgra32);
using (IBuffer<Bgra32> workBuffer = image.GetConfiguration().MemoryAllocator.Allocate<Bgra32>(w))
using (IMemoryOwner<Bgra32> workBuffer = image.GetConfiguration().MemoryAllocator.Allocate<Bgra32>(w))
{
fixed (Bgra32* sourcePtr = &workBuffer.GetReference())
{

3
tests/ImageSharp.Tests/TestUtilities/TestMemoryAllocator.cs

@ -1,4 +1,5 @@
using System;
using System.Buffers;
using System.Runtime.InteropServices;
using SixLabors.Memory;
@ -17,7 +18,7 @@ namespace SixLabors.ImageSharp.Tests.Memory
/// </summary>
public byte DirtyValue { get; }
internal override IBuffer<T> Allocate<T>(int length, AllocationOptions options = AllocationOptions.None)
internal override IMemoryOwner<T> Allocate<T>(int length, AllocationOptions options = AllocationOptions.None)
{
T[] array = this.AllocateArray<T>(length, options);

3
tests/ImageSharp.Tests/TestUtilities/TestMemoryManager.cs

@ -3,9 +3,6 @@ using System.Buffers;
namespace SixLabors.ImageSharp.Tests
{
using SixLabors.ImageSharp.Advanced;
using SixLabors.ImageSharp.PixelFormats;
class TestMemoryManager<T> : MemoryManager<T>
where T : struct
{

Loading…
Cancel
Save