diff --git a/src/ImageSharp/Memory/Buffer2D{T}.cs b/src/ImageSharp/Memory/Buffer2D{T}.cs
index e527c90c0..6b18aaa8f 100644
--- a/src/ImageSharp/Memory/Buffer2D{T}.cs
+++ b/src/ImageSharp/Memory/Buffer2D{T}.cs
@@ -21,7 +21,7 @@ namespace SixLabors.ImageSharp.Memory
/// The buffer to wrap
/// The number of elements in a row
/// The number of rows
- public Buffer2D(Buffer wrappedBuffer, int width, int height)
+ public Buffer2D(IBuffer wrappedBuffer, int width, int height)
{
this.Buffer = wrappedBuffer;
this.Width = width;
@@ -36,7 +36,7 @@ namespace SixLabors.ImageSharp.Memory
public Span Span => this.Buffer.Span;
- public Buffer Buffer { get; }
+ public IBuffer Buffer { get; }
///
/// Gets a reference to the element at the specified position.
diff --git a/src/ImageSharp/Memory/Buffer{T}.cs b/src/ImageSharp/Memory/Buffer{T}.cs
index 1ee1571c8..55eb44820 100644
--- a/src/ImageSharp/Memory/Buffer{T}.cs
+++ b/src/ImageSharp/Memory/Buffer{T}.cs
@@ -18,16 +18,6 @@ namespace SixLabors.ImageSharp.Memory
{
private MemoryManager memoryManager;
- ///
- /// A pointer to the first element of when pinned.
- ///
- private IntPtr pointer;
-
- ///
- /// A handle that allows to access the managed as an unmanaged memory by pinning.
- ///
- private GCHandle handle;
-
// why is there such a rule? :S Protected should be fine for a field!
#pragma warning disable SA1401 // Fields should be private
///
@@ -36,22 +26,7 @@ namespace SixLabors.ImageSharp.Memory
protected T[] array;
#pragma warning restore SA1401 // Fields should be private
- ///
- /// Initializes a new instance of the class.
- ///
- /// The array to pin.
- public Buffer(T[] array)
- {
- this.Length = array.Length;
- this.array = array;
- }
-
- ///
- /// Initializes a new instance of the class.
- ///
- /// The array to pin.
- /// The count of "relevant" elements in 'array'.
- public Buffer(T[] array, int length)
+ internal Buffer(T[] array, int length, MemoryManager memoryManager)
{
if (array.Length < length)
{
@@ -60,22 +35,9 @@ namespace SixLabors.ImageSharp.Memory
this.Length = length;
this.array = array;
- }
-
- internal Buffer(T[] array, int length, MemoryManager memoryManager)
- : this(array, length)
- {
this.memoryManager = memoryManager;
}
- ///
- /// Finalizes an instance of the class.
- ///
- ~Buffer()
- {
- this.UnPin();
- }
-
///
/// Gets a value indicating whether this instance is disposed, or has lost ownership of .
///
@@ -140,7 +102,6 @@ namespace SixLabors.ImageSharp.Memory
}
this.IsDisposedOrLostArrayOwnership = true;
- this.UnPin();
this.memoryManager?.Release(this);
@@ -166,33 +127,10 @@ namespace SixLabors.ImageSharp.Memory
}
this.IsDisposedOrLostArrayOwnership = true;
- this.UnPin();
- T[] array = this.array;
+ T[] a = this.array;
this.array = null;
this.memoryManager = null;
- return array;
- }
-
- ///
- /// Pins .
- ///
- /// The pinned pointer
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public IntPtr Pin()
- {
- if (this.IsDisposedOrLostArrayOwnership)
- {
- throw new InvalidOperationException(
- "Pin() is invalid on a buffer with IsDisposedOrLostArrayOwnership == true!");
- }
-
- if (this.pointer == IntPtr.Zero)
- {
- this.handle = GCHandle.Alloc(this.array, GCHandleType.Pinned);
- this.pointer = this.handle.AddrOfPinnedObject();
- }
-
- return this.pointer;
+ return a;
}
///
@@ -202,20 +140,5 @@ namespace SixLabors.ImageSharp.Memory
{
return this.array;
}
-
- ///
- /// Unpins .
- ///
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- private void UnPin()
- {
- if (this.pointer == IntPtr.Zero || !this.handle.IsAllocated)
- {
- return;
- }
-
- this.handle.Free();
- this.pointer = IntPtr.Zero;
- }
}
}
\ No newline at end of file
diff --git a/src/ImageSharp/Memory/SimpleManagedMemoryManager.cs b/src/ImageSharp/Memory/SimpleManagedMemoryManager.cs
index 12d8582c7..ac4098c71 100644
--- a/src/ImageSharp/Memory/SimpleManagedMemoryManager.cs
+++ b/src/ImageSharp/Memory/SimpleManagedMemoryManager.cs
@@ -8,7 +8,7 @@
///
internal override Buffer Allocate(int length, bool clear)
{
- return new Buffer(new T[length], length);
+ return new Buffer(new T[length], length, this);
}
internal override IManagedByteBuffer AllocateManagedByteBuffer(int length, bool clear)
diff --git a/src/ImageSharp/Processing/Processors/Transforms/WeightsWindow.cs b/src/ImageSharp/Processing/Processors/Transforms/WeightsWindow.cs
index 1ee61a9a6..399b3db84 100644
--- a/src/ImageSharp/Processing/Processors/Transforms/WeightsWindow.cs
+++ b/src/ImageSharp/Processing/Processors/Transforms/WeightsWindow.cs
@@ -32,7 +32,7 @@ namespace SixLabors.ImageSharp.Processing.Processors
///
/// The buffer containing the weights values.
///
- private readonly Buffer buffer;
+ private readonly IBuffer buffer;
///
/// Initializes a new instance of the struct.
@@ -57,7 +57,8 @@ namespace SixLabors.ImageSharp.Processing.Processors
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ref float GetStartReference()
{
- return ref this.buffer[this.flatStartIndex];
+ Span span = this.buffer.Span;
+ return ref span[this.flatStartIndex];
}
///
diff --git a/tests/ImageSharp.Benchmarks/Color/Bulk/PackFromVector4ReferenceVsPointer.cs b/tests/ImageSharp.Benchmarks/Color/Bulk/PackFromVector4ReferenceVsPointer.cs
deleted file mode 100644
index 8925fe903..000000000
--- a/tests/ImageSharp.Benchmarks/Color/Bulk/PackFromVector4ReferenceVsPointer.cs
+++ /dev/null
@@ -1,77 +0,0 @@
-namespace SixLabors.ImageSharp.Benchmarks
-{
- using System.Numerics;
- using System.Runtime.CompilerServices;
-
- using BenchmarkDotNet.Attributes;
-
- using SixLabors.ImageSharp;
- using SixLabors.ImageSharp.Memory;
-
- ///
- /// Compares two implementation candidates for general BulkPixelOperations.ToVector4():
- /// - One iterating with pointers
- /// - One iterating with ref locals
- ///
- public unsafe class PackFromVector4ReferenceVsPointer
- {
- private Buffer destination;
-
- private Buffer source;
-
- [Params(16, 128, 1024)]
- public int Count { get; set; }
-
- [GlobalSetup]
- public void Setup()
- {
- this.destination = Configuration.Default.MemoryManager.Allocate(this.Count);
- this.source = Configuration.Default.MemoryManager.Allocate(this.Count * 4);
- this.source.Pin();
- this.destination.Pin();
- }
-
- [GlobalCleanup]
- public void Cleanup()
- {
- this.source.Dispose();
- this.destination.Dispose();
- }
-
- [Benchmark(Baseline = true)]
- public void PackUsingPointers()
- {
- Vector4* sp = (Vector4*)this.source.Pin();
- byte* dp = (byte*)this.destination.Pin();
- int count = this.Count;
- int size = sizeof(Rgba32);
-
- for (int i = 0; i < count; i++)
- {
- Vector4 v = Unsafe.Read(sp);
- Rgba32 c = default(Rgba32);
- c.PackFromVector4(v);
- Unsafe.Write(dp, c);
-
- sp++;
- dp += size;
- }
- }
-
- [Benchmark]
- public void PackUsingReferences()
- {
- ref Vector4 sp = ref this.source.DangerousGetPinnableReference();
- ref Rgba32 dp = ref this.destination.DangerousGetPinnableReference();
- int count = this.Count;
-
- for (int i = 0; i < count; i++)
- {
- dp.PackFromVector4(sp);
-
- sp = Unsafe.Add(ref sp, 1);
- dp = Unsafe.Add(ref dp, 1);
- }
- }
- }
-}
\ No newline at end of file
diff --git a/tests/ImageSharp.Benchmarks/General/IterateArray.cs b/tests/ImageSharp.Benchmarks/General/IterateArray.cs
deleted file mode 100644
index e06d71f4a..000000000
--- a/tests/ImageSharp.Benchmarks/General/IterateArray.cs
+++ /dev/null
@@ -1,73 +0,0 @@
-namespace SixLabors.ImageSharp.Benchmarks.General
-{
- using System.Numerics;
- using System.Runtime.CompilerServices;
-
- using BenchmarkDotNet.Attributes;
-
- using SixLabors.ImageSharp.Memory;
-
- public class IterateArray
- {
- // Usual pinned stuff
- private Buffer buffer;
-
- // An array that's not pinned by intent!
- private Vector4[] array;
-
- [Params(64, 1024)]
- public int Length { get; set; }
-
- [GlobalSetup]
- public void Setup()
- {
- this.buffer = Configuration.Default.MemoryManager.Allocate(this.Length);
- this.buffer.Pin();
- this.array = new Vector4[this.Length];
- }
-
- [Benchmark(Baseline = true)]
- public Vector4 IterateIndexed()
- {
- Vector4 sum = new Vector4();
- Vector4[] a = this.array;
-
- for (int i = 0; i < a.Length; i++)
- {
- sum += a[i];
- }
- return sum;
- }
-
- [Benchmark]
- public unsafe Vector4 IterateUsingPointers()
- {
- Vector4 sum = new Vector4();
-
- Vector4* ptr = (Vector4*) this.buffer.Pin();
- Vector4* end = ptr + this.Length;
-
- for (; ptr < end; ptr++)
- {
- sum += *ptr;
- }
-
- return sum;
- }
-
- [Benchmark]
- public Vector4 IterateUsingReferences()
- {
- Vector4 sum = new Vector4();
-
- ref Vector4 start = ref this.array[0];
-
- for (int i = 0; i < this.Length; i++)
- {
- sum += Unsafe.Add(ref start, i);
- }
-
- return sum;
- }
- }
-}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs
index ffac1eafa..b5d4aaebe 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/JpegColorConverterTests.cs
@@ -289,7 +289,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
}
// no need to dispose when buffer is not array owner
- buffers[i] = new Buffer2D(new Buffer(values, values.Length), values.Length, 1);
+ buffers[i] = new Buffer2D(new FakeBuffer(values), values.Length, 1);
}
return new JpegColorConverter.ComponentValues(buffers, 0);
}
diff --git a/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs b/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs
index 46d832883..4508c6863 100644
--- a/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs
+++ b/tests/ImageSharp.Tests/Formats/Jpg/SpectralJpegTests.cs
@@ -106,7 +106,7 @@ namespace SixLabors.ImageSharp.Tests.Formats.Jpg
this.Output.WriteLine($"Component{i}: {diff}");
averageDifference += diff.average;
totalDifference += diff.total;
- tolerance += libJpegComponent.SpectralBlocks.Buffer.Length;
+ tolerance += libJpegComponent.SpectralBlocks.Buffer.Span.Length;
}
averageDifference /= componentCount;
diff --git a/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs b/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs
index 50c3ff005..6afce94fd 100644
--- a/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs
+++ b/tests/ImageSharp.Tests/Memory/Buffer2DTests.cs
@@ -16,11 +16,11 @@ namespace SixLabors.ImageSharp.Tests.Memory
// ReSharper disable once ClassNeverInstantiated.Local
private class Assert : Xunit.Assert
{
- public static void SpanPointsTo(Span span, Buffer buffer, int bufferOffset = 0)
+ public static void SpanPointsTo(Span span, IBuffer buffer, int bufferOffset = 0)
where T : struct
{
ref T actual = ref span.DangerousGetPinnableReference();
- ref T expected = ref Unsafe.Add(ref buffer[0], bufferOffset);
+ ref T expected = ref Unsafe.Add(ref buffer.DangerousGetPinnableReference(), bufferOffset);
Assert.True(Unsafe.AreSame(ref expected, ref actual), "span does not point to the expected position");
}
@@ -35,7 +35,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.Buffer.Length());
}
}
@@ -47,7 +47,7 @@ namespace SixLabors.ImageSharp.Tests.Memory
using (Buffer2D buffer = Configuration.Default.MemoryManager.Allocate2D(42, 42, true))
{
Span span = buffer.Span;
- for (int j = 0; j < buffer.Buffer.Length; j++)
+ for (int j = 0; j < span.Length; j++)
{
Assert.Equal(0, span[j]);
span[j] = 666;
diff --git a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs
index 8787fba55..2ea06d724 100644
--- a/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs
+++ b/tests/ImageSharp.Tests/PixelFormats/PixelOperationsTests.cs
@@ -333,25 +333,23 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
where TSource : struct
where TDest : struct
{
- public Buffer SourceBuffer { get; }
+ public TSource[] SourceBuffer { get; }
public Buffer ActualDestBuffer { get; }
- public Buffer ExpectedDestBuffer { get; }
+ public TDest[] ExpectedDestBuffer { get; }
public Span Source => this.SourceBuffer;
public Span ActualDest => this.ActualDestBuffer;
public TestBuffers(TSource[] source, TDest[] expectedDest)
{
- this.SourceBuffer = new Buffer(source);
- this.ExpectedDestBuffer = new Buffer(expectedDest);
+ this.SourceBuffer = source;
+ this.ExpectedDestBuffer = expectedDest;
this.ActualDestBuffer = Configuration.Default.MemoryManager.Allocate(expectedDest.Length);
}
public void Dispose()
{
- this.SourceBuffer.Dispose();
this.ActualDestBuffer.Dispose();
- this.ExpectedDestBuffer.Dispose();
}
private const float Tolerance = 0.0001f;
@@ -363,7 +361,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
if (typeof(TDest) == typeof(Vector4))
{
- Span expected = this.ExpectedDestBuffer.Span.NonPortableCast();
+ Span expected = this.ExpectedDestBuffer.AsSpan().NonPortableCast();
Span actual = this.ActualDestBuffer.Span.NonPortableCast();
for (int i = 0; i < count; i++)
@@ -375,7 +373,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
}
else
{
- Span expected = this.ExpectedDestBuffer.Span;
+ Span expected = this.ExpectedDestBuffer.AsSpan();
Span actual = this.ActualDestBuffer.Span;
for (int i = 0; i < count; i++)
{
@@ -388,7 +386,7 @@ namespace SixLabors.ImageSharp.Tests.PixelFormats
internal static void TestOperation(
TSource[] source,
TDest[] expected,
- Action, Buffer> action)
+ Action> action)
where TSource : struct
where TDest : struct
{
diff --git a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingBridge.cs b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingBridge.cs
index d14a0165a..b8907e81e 100644
--- a/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingBridge.cs
+++ b/tests/ImageSharp.Tests/TestUtilities/ReferenceCodecs/SystemDrawingBridge.cs
@@ -96,18 +96,20 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
var image = new Image(w, h);
- using (var workBuffer = Configuration.Default.MemoryManager.Allocate(w))
+ using (IBuffer workBuffer = Configuration.Default.MemoryManager.Allocate(w))
{
- var destPtr = (Argb32*)workBuffer.Pin();
- for (int y = 0; y < h; y++)
+ fixed (Argb32* destPtr = &workBuffer.DangerousGetPinnableReference())
{
- Span row = image.Frames.RootFrame.GetPixelRowSpan(y);
+ for (int y = 0; y < h; y++)
+ {
+ Span row = image.Frames.RootFrame.GetPixelRowSpan(y);
- byte* sourcePtr = sourcePtrBase + data.Stride * y;
+ byte* sourcePtr = sourcePtrBase + data.Stride * y;
- Buffer.MemoryCopy(sourcePtr, destPtr, destRowByteCount, sourceRowByteCount);
+ Buffer.MemoryCopy(sourcePtr, destPtr, destRowByteCount, sourceRowByteCount);
- FromArgb32(workBuffer, row);
+ FromArgb32(workBuffer.Span, row);
+ }
}
}
@@ -138,18 +140,20 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
var image = new Image(w, h);
- using (var workBuffer = Configuration.Default.MemoryManager.Allocate(w))
+ using (IBuffer workBuffer = Configuration.Default.MemoryManager.Allocate(w))
{
- var destPtr = (Rgb24*)workBuffer.Pin();
- for (int y = 0; y < h; y++)
+ fixed (Rgb24* destPtr = &workBuffer.DangerousGetPinnableReference())
{
- Span row = image.Frames.RootFrame.GetPixelRowSpan(y);
+ for (int y = 0; y < h; y++)
+ {
+ Span row = image.Frames.RootFrame.GetPixelRowSpan(y);
- byte* sourcePtr = sourcePtrBase + data.Stride * y;
+ byte* sourcePtr = sourcePtrBase + data.Stride * y;
- Buffer.MemoryCopy(sourcePtr, destPtr, destRowByteCount, sourceRowByteCount);
+ Buffer.MemoryCopy(sourcePtr, destPtr, destRowByteCount, sourceRowByteCount);
- FromRgb24(workBuffer, row);
+ FromRgb24(workBuffer.Span, row);
+ }
}
}
@@ -170,17 +174,19 @@ namespace SixLabors.ImageSharp.Tests.TestUtilities.ReferenceCodecs
long destRowByteCount = data.Stride;
long sourceRowByteCount = w * sizeof(Argb32);
- using (var workBuffer = Configuration.Default.MemoryManager.Allocate(w))
+ using (IBuffer workBuffer = image.GetConfiguration().MemoryManager.Allocate(w))
{
- var sourcePtr = (Argb32*)workBuffer.Pin();
-
- for (int y = 0; y < h; y++)
+ fixed (Argb32* sourcePtr = &workBuffer.DangerousGetPinnableReference())
{
- Span row = image.Frames.RootFrame.GetPixelRowSpan(y);
- ToArgb32(row, workBuffer);
- byte* destPtr = destPtrBase + data.Stride * y;
- Buffer.MemoryCopy(sourcePtr, destPtr, destRowByteCount, sourceRowByteCount);
+ for (int y = 0; y < h; y++)
+ {
+ Span row = image.Frames.RootFrame.GetPixelRowSpan(y);
+ ToArgb32(row, workBuffer.Span);
+ byte* destPtr = destPtrBase + data.Stride * y;
+
+ Buffer.MemoryCopy(sourcePtr, destPtr, destRowByteCount, sourceRowByteCount);
+ }
}
}
diff --git a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs
index 54e55f7e5..b830acdef 100644
--- a/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs
+++ b/tests/ImageSharp.Tests/TestUtilities/TestImageExtensions.cs
@@ -151,7 +151,7 @@ namespace SixLabors.ImageSharp.Tests
bool appendPixelTypeToFileName = true)
where TPixel : struct, IPixel
{
- using (Image firstFrameOnlyImage = new Image(image.Width, image.Height))
+ using (var firstFrameOnlyImage = new Image(image.Width, image.Height))
using (Image referenceImage = GetReferenceOutputImage(
provider,
testOutputDetails,
@@ -378,9 +378,11 @@ namespace SixLabors.ImageSharp.Tests
Span pixels = image.Frames.RootFrame.GetPixelSpan();
- for (int i = 0; i < buffer.Buffer.Length; i++)
+ Span bufferSpan = buffer.Span;
+
+ for (int i = 0; i < bufferSpan.Length; i++)
{
- float value = buffer.Buffer[i] * scale;
+ float value = bufferSpan[i] * scale;
var v = new Vector4(value, value, value, 1f);
pixels[i].PackFromVector4(v);
}