Browse Source

Merge remote-tracking branch 'origin/PinnedBuffer' into bulk-pixels

pull/126/head
Anton Firszov 9 years ago
parent
commit
d3dc6d2dae
  1. 82
      src/ImageSharp/Colors/PackedPixel/BulkPixelOperations{TColor}.cs
  2. 29
      src/ImageSharp/Common/Extensions/ArrayExtensions.cs
  3. 24
      src/ImageSharp/Common/Memory/BufferPointer.cs
  4. 40
      src/ImageSharp/Common/Memory/BufferPointer{T}.cs
  5. 2
      src/ImageSharp/Common/Memory/PinnedBuffer{T}.cs
  6. 3
      src/ImageSharp/Image/ImageBase{TColor}.cs
  7. 11
      src/ImageSharp/Image/PixelAccessor{TColor}.cs
  8. 24
      tests/ImageSharp.Benchmarks/Color/Bulk/PixelAccessorVirtualCopy.cs
  9. 3
      tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj
  10. 2
      tests/ImageSharp.Sandbox46/Program.cs
  11. 16
      tests/ImageSharp.Tests/Colors/BulkPixelOperationsTests.cs
  12. 26
      tests/ImageSharp.Tests/Common/BufferPointerTests.cs
  13. 4
      tests/ImageSharp.Tests/Common/PinnedBufferTests.cs
  14. 0
      tests/ImageSharp.Tests/Common/PixelDataPoolTests.cs

82
src/ImageSharp/Colors/PackedPixel/BulkPixelOperations{TColor}.cs

@ -29,12 +29,12 @@ namespace ImageSharp
/// <summary>
/// Bulk version of <see cref="IPixel.PackFromVector4(Vector4)"/>
/// </summary>
/// <param name="sourceVectors">The <see cref="ArrayPointer{Vector4}"/> to the source vectors.</param>
/// <param name="destColors">The <see cref="ArrayPointer{TColor}"/> to the destination colors.</param>
/// <param name="sourceVectors">The <see cref="BufferPointer{T}"/> to the source vectors.</param>
/// <param name="destColors">The <see cref="BufferPointer{T}"/> to the destination colors.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFromVector4(
ArrayPointer<Vector4> sourceVectors,
ArrayPointer<TColor> destColors,
BufferPointer<Vector4> sourceVectors,
BufferPointer<TColor> destColors,
int count)
{
Vector4* sp = (Vector4*)sourceVectors.PointerAtOffset;
@ -55,12 +55,12 @@ namespace ImageSharp
/// <summary>
/// Bulk version of <see cref="IPixel.ToVector4()"/>.
/// </summary>
/// <param name="sourceColors">The <see cref="ArrayPointer{TColor}"/> to the source colors.</param>
/// <param name="destVectors">The <see cref="ArrayPointer{Vector4}"/> to the destination vectors.</param>
/// <param name="sourceColors">The <see cref="BufferPointer{T}"/> to the source colors.</param>
/// <param name="destVectors">The <see cref="BufferPointer{T}"/> to the destination vectors.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackToVector4(
ArrayPointer<TColor> sourceColors,
ArrayPointer<Vector4> destVectors,
internal virtual void ToVector4(
BufferPointer<TColor> sourceColors,
BufferPointer<Vector4> destVectors,
int count)
{
byte* sp = (byte*)sourceColors;
@ -78,12 +78,12 @@ namespace ImageSharp
/// <summary>
/// Bulk version of <see cref="IPixel.PackFromBytes(byte, byte, byte, byte)"/> that converts data in <see cref="ComponentOrder.Xyz"/>.
/// </summary>
/// <param name="sourceBytes">The <see cref="ArrayPointer{Byte}"/> to the source bytes.</param>
/// <param name="destColors">The <see cref="ArrayPointer{TColor}"/> to the destination colors.</param>
/// <param name="sourceBytes">The <see cref="BufferPointer{T}"/> to the source bytes.</param>
/// <param name="destColors">The <see cref="BufferPointer{T}"/> to the destination colors.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFromXyzBytes(
ArrayPointer<byte> sourceBytes,
ArrayPointer<TColor> destColors,
BufferPointer<byte> sourceBytes,
BufferPointer<TColor> destColors,
int count)
{
byte* sp = (byte*)sourceBytes;
@ -102,10 +102,10 @@ namespace ImageSharp
/// <summary>
/// Bulk version of <see cref="IPixel.ToXyzBytes(byte[], int)"/>.
/// </summary>
/// <param name="sourceColors">The <see cref="ArrayPointer{TColor}"/> to the source colors.</param>
/// <param name="destBytes">The <see cref="ArrayPointer{Byte}"/> to the destination bytes.</param>
/// <param name="sourceColors">The <see cref="BufferPointer{T}"/> to the source colors.</param>
/// <param name="destBytes">The <see cref="BufferPointer{T}"/> to the destination bytes.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackToXyzBytes(ArrayPointer<TColor> sourceColors, ArrayPointer<byte> destBytes, int count)
internal virtual void ToXyzBytes(BufferPointer<TColor> sourceColors, BufferPointer<byte> destBytes, int count)
{
byte* sp = (byte*)sourceColors;
byte[] dest = destBytes.Array;
@ -121,12 +121,12 @@ namespace ImageSharp
/// <summary>
/// Bulk version of <see cref="IPixel.PackFromBytes(byte, byte, byte, byte)"/> that converts data in <see cref="ComponentOrder.Xyzw"/>.
/// </summary>
/// <param name="sourceBytes">The <see cref="ArrayPointer{Byte}"/> to the source bytes.</param>
/// <param name="destColors">The <see cref="ArrayPointer{TColor}"/> to the destination colors.</param>
/// <param name="sourceBytes">The <see cref="BufferPointer{T}"/> to the source bytes.</param>
/// <param name="destColors">The <see cref="BufferPointer{T}"/> to the destination colors.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFromXyzwBytes(
ArrayPointer<byte> sourceBytes,
ArrayPointer<TColor> destColors,
BufferPointer<byte> sourceBytes,
BufferPointer<TColor> destColors,
int count)
{
byte* sp = (byte*)sourceBytes;
@ -145,12 +145,12 @@ namespace ImageSharp
/// <summary>
/// Bulk version of <see cref="IPixel.ToXyzwBytes(byte[], int)"/>.
/// </summary>
/// <param name="sourceColors">The <see cref="ArrayPointer{TColor}"/> to the source colors.</param>
/// <param name="destBytes">The <see cref="ArrayPointer{Byte}"/> to the destination bytes.</param>
/// <param name="sourceColors">The <see cref="BufferPointer{T}"/> to the source colors.</param>
/// <param name="destBytes">The <see cref="BufferPointer{T}"/> to the destination bytes.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackToXyzwBytes(
ArrayPointer<TColor> sourceColors,
ArrayPointer<byte> destBytes,
internal virtual void ToXyzwBytes(
BufferPointer<TColor> sourceColors,
BufferPointer<byte> destBytes,
int count)
{
byte* sp = (byte*)sourceColors;
@ -167,12 +167,12 @@ namespace ImageSharp
/// <summary>
/// Bulk version of <see cref="IPixel.PackFromBytes(byte, byte, byte, byte)"/> that converts data in <see cref="ComponentOrder.Zyx"/>.
/// </summary>
/// <param name="sourceBytes">The <see cref="ArrayPointer{Byte}"/> to the source bytes.</param>
/// <param name="destColors">The <see cref="ArrayPointer{TColor}"/> to the destination colors.</param>
/// <param name="sourceBytes">The <see cref="BufferPointer{T}"/> to the source bytes.</param>
/// <param name="destColors">The <see cref="BufferPointer{T}"/> to the destination colors.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFromZyxBytes(
ArrayPointer<byte> sourceBytes,
ArrayPointer<TColor> destColors,
BufferPointer<byte> sourceBytes,
BufferPointer<TColor> destColors,
int count)
{
byte* sp = (byte*)sourceBytes;
@ -191,10 +191,10 @@ namespace ImageSharp
/// <summary>
/// Bulk version of <see cref="IPixel.ToZyxBytes(byte[], int)"/>.
/// </summary>
/// <param name="sourceColors">The <see cref="ArrayPointer{TColor}"/> to the source colors.</param>
/// <param name="destBytes">The <see cref="ArrayPointer{Byte}"/> to the destination bytes.</param>
/// <param name="sourceColors">The <see cref="BufferPointer{T}"/> to the source colors.</param>
/// <param name="destBytes">The <see cref="BufferPointer{T}"/> to the destination bytes.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackToZyxBytes(ArrayPointer<TColor> sourceColors, ArrayPointer<byte> destBytes, int count)
internal virtual void ToZyxBytes(BufferPointer<TColor> sourceColors, BufferPointer<byte> destBytes, int count)
{
byte* sp = (byte*)sourceColors;
byte[] dest = destBytes.Array;
@ -210,12 +210,12 @@ namespace ImageSharp
/// <summary>
/// Bulk version of <see cref="IPixel.PackFromBytes(byte, byte, byte, byte)"/> that converts data in <see cref="ComponentOrder.Zyxw"/>.
/// </summary>
/// <param name="sourceBytes">The <see cref="ArrayPointer{Byte}"/> to the source bytes.</param>
/// <param name="destColors">The <see cref="ArrayPointer{TColor}"/> to the destination colors.</param>
/// <param name="sourceBytes">The <see cref="BufferPointer{T}"/> to the source bytes.</param>
/// <param name="destColors">The <see cref="BufferPointer{T}"/> to the destination colors.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackFromZyxwBytes(
ArrayPointer<byte> sourceBytes,
ArrayPointer<TColor> destColors,
BufferPointer<byte> sourceBytes,
BufferPointer<TColor> destColors,
int count)
{
byte* sp = (byte*)sourceBytes;
@ -234,12 +234,12 @@ namespace ImageSharp
/// <summary>
/// Bulk version of <see cref="IPixel.ToZyxwBytes(byte[], int)"/>.
/// </summary>
/// <param name="sourceColors">The <see cref="ArrayPointer{TColor}"/> to the source colors.</param>
/// <param name="destBytes">The <see cref="ArrayPointer{Byte}"/> to the destination bytes.</param>
/// <param name="sourceColors">The <see cref="BufferPointer{T}"/> to the source colors.</param>
/// <param name="destBytes">The <see cref="BufferPointer{T}"/> to the destination bytes.</param>
/// <param name="count">The number of pixels to convert.</param>
internal virtual void PackToZyxwBytes(
ArrayPointer<TColor> sourceColors,
ArrayPointer<byte> destBytes,
internal virtual void ToZyxwBytes(
BufferPointer<TColor> sourceColors,
BufferPointer<byte> destBytes,
int count)
{
byte* sp = (byte*)sourceColors;

29
src/ImageSharp/Common/Extensions/ArrayExtensions.cs

@ -1,29 +0,0 @@
// <copyright file="ArrayExtensions.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
namespace ImageSharp
{
using System;
/// <summary>
/// Extension methods for arrays.
/// </summary>
public static class ArrayExtensions
{
/// <summary>
/// Locks the pixel buffer providing access to the pixels.
/// </summary>
/// <typeparam name="TColor">The pixel format.</typeparam>
/// <param name="pixels">The pixel buffer.</param>
/// <param name="width">Gets the width of the image represented by the pixel buffer.</param>
/// <param name="height">The height of the image represented by the pixel buffer.</param>
/// <returns>The <see cref="PixelAccessor{TColor}"/></returns>
public static PixelAccessor<TColor> Lock<TColor>(this TColor[] pixels, int width, int height)
where TColor : struct, IPixel<TColor>
{
return new PixelAccessor<TColor>(width, height, pixels);
}
}
}

24
src/ImageSharp/Common/Memory/ArrayPointer.cs → src/ImageSharp/Common/Memory/BufferPointer.cs

@ -1,4 +1,4 @@
// <copyright file="ArrayPointer.cs" company="James Jackson-South">
// <copyright file="BufferPointer.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
@ -8,32 +8,32 @@ namespace ImageSharp
using System.Runtime.CompilerServices;
/// <summary>
/// Utility methods to <see cref="ArrayPointer{T}"/>
/// Utility methods for <see cref="BufferPointer{T}"/>
/// </summary>
internal static class ArrayPointer
internal static class BufferPointer
{
/// <summary>
/// Gets an <see cref="ArrayPointer{T}"/> to the beginning of the raw data in 'buffer'.
/// Gets a <see cref="BufferPointer{T}"/> to the beginning of the raw data in 'buffer'.
/// </summary>
/// <typeparam name="T">The element type</typeparam>
/// <param name="buffer">The input <see cref="PinnedBuffer{T}"/></param>
/// <returns>The <see cref="ArrayPointer{T}"/></returns>
/// <returns>The <see cref="BufferPointer{T}"/></returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe ArrayPointer<T> GetArrayPointer<T>(this PinnedBuffer<T> buffer)
public static unsafe BufferPointer<T> Slice<T>(this PinnedBuffer<T> buffer)
where T : struct
{
return new ArrayPointer<T>(buffer.Array, (void*)buffer.Pointer);
return new BufferPointer<T>(buffer.Array, (void*)buffer.Pointer);
}
/// <summary>
/// Copy 'count' number of elements of the same type from 'source' to 'dest'
/// </summary>
/// <typeparam name="T">The element type.</typeparam>
/// <param name="source">The input <see cref="ArrayPointer{T}"/></param>
/// <param name="destination">The destination <see cref="ArrayPointer{T}"/>.</param>
/// <param name="source">The input <see cref="BufferPointer{T}"/></param>
/// <param name="destination">The destination <see cref="BufferPointer{T}"/>.</param>
/// <param name="count">The number of elements to copy</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void Copy<T>(ArrayPointer<T> source, ArrayPointer<T> destination, int count)
public static unsafe void Copy<T>(BufferPointer<T> source, BufferPointer<T> destination, int count)
where T : struct
{
Unsafe.CopyBlock((void*)source.PointerAtOffset, (void*)destination.PointerAtOffset, USizeOf<T>(count));
@ -47,7 +47,7 @@ namespace ImageSharp
/// <param name="destination">The destination buffer.</param>
/// <param name="countInSource">The number of elements to copy from 'source'</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void Copy<T>(ArrayPointer<T> source, ArrayPointer<byte> destination, int countInSource)
public static unsafe void Copy<T>(BufferPointer<T> source, BufferPointer<byte> destination, int countInSource)
where T : struct
{
Unsafe.CopyBlock((void*)source.PointerAtOffset, (void*)destination.PointerAtOffset, USizeOf<T>(countInSource));
@ -61,7 +61,7 @@ namespace ImageSharp
/// <param name="destination">The destination buffer"/></param>
/// <param name="countInDest">The number of <typeparamref name="T"/> elements to copy.</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static unsafe void Copy<T>(ArrayPointer<byte> source, ArrayPointer<T> destination, int countInDest)
public static unsafe void Copy<T>(BufferPointer<byte> source, BufferPointer<T> destination, int countInDest)
where T : struct
{
Unsafe.CopyBlock((void*)source.PointerAtOffset, (void*)destination.PointerAtOffset, USizeOf<T>(countInDest));

40
src/ImageSharp/Common/Memory/ArrayPointer{T}.cs → src/ImageSharp/Common/Memory/BufferPointer{T}.cs

@ -1,4 +1,4 @@
// <copyright file="ArrayPointer{T}.cs" company="James Jackson-South">
// <copyright file="BufferPointer{T}.cs" company="James Jackson-South">
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
// </copyright>
@ -15,21 +15,21 @@ namespace ImageSharp
/// - It's not possible to use it with stack objects or pointers to unmanaged memory, only with managed arrays
/// - It's possible to retrieve a reference to the array (<see cref="Array"/>) so we can pass it to API-s like <see cref="Marshal.Copy(byte[], int, IntPtr, int)"/>
/// - There is no bounds checking for performance reasons. Therefore we don't need to store length. (However this could be added as DEBUG-only feature.)
/// This makes <see cref="ArrayPointer{T}"/> an unsafe type!
/// - Currently the arrays provided to ArrayPointer need to be pinned. This behaviour could be changed using C#7 features.
/// This makes <see cref="BufferPointer{T}"/> an unsafe type!
/// - Currently the arrays provided to BufferPointer need to be pinned. This behaviour could be changed using C#7 features.
/// </summary>
/// <typeparam name="T">The type of elements of the array</typeparam>
internal unsafe struct ArrayPointer<T>
internal unsafe struct BufferPointer<T>
where T : struct
{
/// <summary>
/// Initializes a new instance of the <see cref="ArrayPointer{T}"/> struct from a pinned array and an offset.
/// Initializes a new instance of the <see cref="BufferPointer{T}"/> struct from a pinned array and an offset.
/// </summary>
/// <param name="array">The pinned array</param>
/// <param name="pointerToArray">Pointer to the beginning of array</param>
/// <param name="offset">The offset inside the array</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ArrayPointer(T[] array, void* pointerToArray, int offset)
public BufferPointer(T[] array, void* pointerToArray, int offset)
{
DebugGuard.NotNull(array, nameof(array));
@ -39,12 +39,12 @@ namespace ImageSharp
}
/// <summary>
/// Initializes a new instance of the <see cref="ArrayPointer{T}"/> struct from a pinned array.
/// Initializes a new instance of the <see cref="BufferPointer{T}"/> struct from a pinned array.
/// </summary>
/// <param name="array">The pinned array</param>
/// <param name="pointerToArray">Pointer to the start of 'array'</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ArrayPointer(T[] array, void* pointerToArray)
public BufferPointer(T[] array, void* pointerToArray)
{
DebugGuard.NotNull(array, nameof(array));
@ -69,34 +69,34 @@ namespace ImageSharp
public IntPtr PointerAtOffset { get; private set; }
/// <summary>
/// Convertes <see cref="ArrayPointer{T}"/> instance to a raw 'void*' pointer
/// Convertes <see cref="BufferPointer{T}"/> instance to a raw 'void*' pointer
/// </summary>
/// <param name="arrayPointer">The <see cref="ArrayPointer{T}"/> to convert</param>
/// <param name="bufferPointer">The <see cref="BufferPointer{T}"/> to convert</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static explicit operator void*(ArrayPointer<T> arrayPointer)
public static explicit operator void*(BufferPointer<T> bufferPointer)
{
return (void*)arrayPointer.PointerAtOffset;
return (void*)bufferPointer.PointerAtOffset;
}
/// <summary>
/// Convertes <see cref="ArrayPointer{T}"/> instance to a raw 'byte*' pointer
/// Convertes <see cref="BufferPointer{T}"/> instance to a raw 'byte*' pointer
/// </summary>
/// <param name="arrayPointer">The <see cref="ArrayPointer{T}"/> to convert</param>
/// <param name="bufferPointer">The <see cref="BufferPointer{T}"/> to convert</param>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static explicit operator byte*(ArrayPointer<T> arrayPointer)
public static explicit operator byte*(BufferPointer<T> bufferPointer)
{
return (byte*)arrayPointer.PointerAtOffset;
return (byte*)bufferPointer.PointerAtOffset;
}
/// <summary>
/// Forms a slice out of the given ArrayPointer, beginning at 'offset'.
/// Forms a slice out of the given BufferPointer, beginning at 'offset'.
/// </summary>
/// <param name="offset">The offset in number of elements</param>
/// <returns>The offseted (sliced) ArrayPointer</returns>
/// <returns>The offseted (sliced) BufferPointer</returns>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ArrayPointer<T> Slice(int offset)
public BufferPointer<T> Slice(int offset)
{
ArrayPointer<T> result = default(ArrayPointer<T>);
BufferPointer<T> result = default(BufferPointer<T>);
result.Array = this.Array;
result.Offset = this.Offset + offset;
result.PointerAtOffset = this.PointerAtOffset + (Unsafe.SizeOf<T>() * offset);

2
src/ImageSharp/Common/Memory/PinnedBuffer{T}.cs

@ -23,7 +23,7 @@ namespace ImageSharp
private GCHandle handle;
/// <summary>
/// A value indicating wether this <see cref="PinnedBuffer{T}"/> instance should return the array to the pool.
/// A value indicating whether this <see cref="PinnedBuffer{T}"/> instance should return the array to the pool.
/// </summary>
private bool isPoolingOwner;

3
src/ImageSharp/Image/ImageBase{TColor}.cs

@ -163,9 +163,6 @@ namespace ImageSharp
{
Guard.NotNull(pixelSource, nameof(pixelSource));
// TODO: Was this check really useful? If yes, we can define a bool PixelAccessor<TColor>.IsBoundToImage to re-introduce it:
// Guard.IsTrue(pixelSource.PooledMemory, nameof(pixelSource.PooledMemory), "pixelSource must be using pooled memory");
int newWidth = pixelSource.Width;
int newHeight = pixelSource.Height;

11
src/ImageSharp/Image/PixelAccessor{TColor}.cs

@ -53,17 +53,6 @@ namespace ImageSharp
this.ParallelOptions = image.Configuration.ParallelOptions;
}
/// <summary>
/// Initializes a new instance of the <see cref="PixelAccessor{TColor}"/> class.
/// </summary>
/// <param name="width">The width of the image represented by the pixel buffer.</param>
/// <param name="height">The height of the image represented by the pixel buffer.</param>
/// <param name="pixels">The pixel buffer.</param>
public PixelAccessor(int width, int height, TColor[] pixels)
: this(width, height, new PinnedBuffer<TColor>(width * height, pixels))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="PixelAccessor{TColor}"/> class.
/// </summary>

24
tests/ImageSharp.Benchmarks/Color/Bulk/PixelAccessorVirtualCopy.cs

@ -19,13 +19,13 @@ namespace ImageSharp.Benchmarks.Color.Bulk
{
abstract class CopyExecutor
{
internal abstract void VirtualCopy(ArrayPointer<Color> destination, ArrayPointer<byte> source, int count);
internal abstract void VirtualCopy(BufferPointer<Color> destination, BufferPointer<byte> source, int count);
}
class UnsafeCopyExecutor : CopyExecutor
{
[MethodImpl(MethodImplOptions.NoInlining)]
internal override unsafe void VirtualCopy(ArrayPointer<Color> destination, ArrayPointer<byte> source, int count)
internal override unsafe void VirtualCopy(BufferPointer<Color> destination, BufferPointer<byte> source, int count)
{
Unsafe.CopyBlock((void*)destination.PointerAtOffset, (void*)source.PointerAtOffset, (uint)count*4);
}
@ -76,7 +76,7 @@ namespace ImageSharp.Benchmarks.Color.Bulk
}
[Benchmark]
public void CopyArrayPointerUnsafeInlined()
public void CopyBufferPointerUnsafeInlined()
{
uint byteCount = (uint)this.area.Width * 4;
@ -85,22 +85,22 @@ namespace ImageSharp.Benchmarks.Color.Bulk
for (int y = 0; y < this.Height; y++)
{
ArrayPointer<byte> source = this.GetAreaRow(y);
ArrayPointer<Color> destination = this.GetPixelAccessorRow(targetX, targetY + y);
BufferPointer<byte> source = this.GetAreaRow(y);
BufferPointer<Color> destination = this.GetPixelAccessorRow(targetX, targetY + y);
Unsafe.CopyBlock((void*)destination.PointerAtOffset, (void*)source.PointerAtOffset, byteCount);
}
}
[Benchmark]
public void CopyArrayPointerUnsafeVirtual()
public void CopyBufferPointerUnsafeVirtual()
{
int targetX = this.Width / 4;
int targetY = 0;
for (int y = 0; y < this.Height; y++)
{
ArrayPointer<byte> source = this.GetAreaRow(y);
ArrayPointer<Color> destination = this.GetPixelAccessorRow(targetX, targetY + y);
BufferPointer<byte> source = this.GetAreaRow(y);
BufferPointer<Color> destination = this.GetPixelAccessorRow(targetX, targetY + y);
this.executor.VirtualCopy(destination, source, this.area.Width);
}
}
@ -111,9 +111,9 @@ namespace ImageSharp.Benchmarks.Color.Bulk
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private ArrayPointer<Color> GetPixelAccessorRow(int x, int y)
private BufferPointer<Color> GetPixelAccessorRow(int x, int y)
{
return new ArrayPointer<ImageSharp.Color>(
return new BufferPointer<ImageSharp.Color>(
this.pixelAccessor.PixelBuffer,
(void*)this.pixelAccessor.DataPointer,
(y * this.pixelAccessor.Width) + x
@ -121,9 +121,9 @@ namespace ImageSharp.Benchmarks.Color.Bulk
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private ArrayPointer<byte> GetAreaRow(int y)
private BufferPointer<byte> GetAreaRow(int y)
{
return new ArrayPointer<byte>(this.area.Bytes, this.area.PixelBase, y * this.area.RowStride);
return new BufferPointer<byte>(this.area.Bytes, this.area.PixelBase, y * this.area.RowStride);
}
}
}

3
tests/ImageSharp.Sandbox46/ImageSharp.Sandbox46.csproj

@ -251,9 +251,6 @@
<Compile Include="..\ImageSharp.Tests\Formats\Jpg\YCbCrImageTests.cs">
<Link>Tests\Formats\Jpg\YCbCrImageTests.cs</Link>
</Compile>
<Compile Include="..\ImageSharp.Tests\Image\PixelPoolTests.cs">
<Link>Tests\Image\PixelPoolTests.cs</Link>
</Compile>
<Compile Include="..\ImageSharp.Tests\MetaData\ImagePropertyTests.cs">
<Link>Tests\MetaData\ImagePropertyTests.cs</Link>
</Compile>

2
tests/ImageSharp.Sandbox46/Program.cs

@ -37,7 +37,7 @@ namespace ImageSharp.Sandbox46
/// </param>
public static void Main(string[] args)
{
//RunDecodeJpegProfilingTests();
// RunDecodeJpegProfilingTests();
TestPixelAccessorCopyFromXyzw();
Console.ReadLine();
}

16
tests/ImageSharp.Tests/Colors/BulkPixelOperationsTests.cs

@ -67,7 +67,7 @@
TestOperation(
source,
expected,
(ops, s, d) => ops.PackToVector4(s, d, count)
(ops, s, d) => ops.ToVector4(s, d, count)
);
}
@ -109,7 +109,7 @@
TestOperation(
source,
expected,
(ops, s, d) => ops.PackToXyzBytes(s, d, count)
(ops, s, d) => ops.ToXyzBytes(s, d, count)
);
}
@ -150,7 +150,7 @@
TestOperation(
source,
expected,
(ops, s, d) => ops.PackToXyzwBytes(s, d, count)
(ops, s, d) => ops.ToXyzwBytes(s, d, count)
);
}
@ -191,7 +191,7 @@
TestOperation(
source,
expected,
(ops, s, d) => ops.PackToZyxBytes(s, d, count)
(ops, s, d) => ops.ToZyxBytes(s, d, count)
);
}
@ -232,7 +232,7 @@
TestOperation(
source,
expected,
(ops, s, d) => ops.PackToZyxwBytes(s, d, count)
(ops, s, d) => ops.ToZyxwBytes(s, d, count)
);
}
@ -245,8 +245,8 @@
public PinnedBuffer<TDest> ActualDestBuffer { get; }
public PinnedBuffer<TDest> ExpectedDestBuffer { get; }
public ArrayPointer<TSource> Source => this.SourceBuffer.GetArrayPointer();
public ArrayPointer<TDest> ActualDest => this.ActualDestBuffer.GetArrayPointer();
public BufferPointer<TSource> Source => this.SourceBuffer.Slice();
public BufferPointer<TDest> ActualDest => this.ActualDestBuffer.Slice();
public TestBuffers(TSource[] source, TDest[] expectedDest)
{
@ -277,7 +277,7 @@
private static void TestOperation<TSource, TDest>(
TSource[] source,
TDest[] expected,
Action<BulkPixelOperations<TColor>, ArrayPointer<TSource>, ArrayPointer<TDest>> action)
Action<BulkPixelOperations<TColor>, BufferPointer<TSource>, BufferPointer<TDest>> action)
where TSource : struct
where TDest : struct
{

26
tests/ImageSharp.Tests/Common/ArrayPointerTests.cs → tests/ImageSharp.Tests/Common/BufferPointerTests.cs

@ -7,7 +7,7 @@ namespace ImageSharp.Tests.Common
using Xunit;
public unsafe class ArrayPointerTests
public unsafe class BufferPointerTests
{
public struct Foo
{
@ -33,7 +33,7 @@ namespace ImageSharp.Tests.Common
fixed (Foo* p = array)
{
// Act:
ArrayPointer<Foo> ap = new ArrayPointer<Foo>(array, p);
BufferPointer<Foo> ap = new BufferPointer<Foo>(array, p);
// Assert:
Assert.Equal(array, ap.Array);
@ -49,7 +49,7 @@ namespace ImageSharp.Tests.Common
fixed (Foo* p = array)
{
// Act:
ArrayPointer<Foo> ap = new ArrayPointer<Foo>(array, p, offset);
BufferPointer<Foo> ap = new BufferPointer<Foo>(array, p, offset);
// Assert:
Assert.Equal(array, ap.Array);
@ -67,7 +67,7 @@ namespace ImageSharp.Tests.Common
int totalOffset = offset0 + offset1;
fixed (Foo* p = array)
{
ArrayPointer<Foo> ap = new ArrayPointer<Foo>(array, p, offset0);
BufferPointer<Foo> ap = new BufferPointer<Foo>(array, p, offset0);
// Act:
ap = ap.Slice(offset1);
@ -92,10 +92,10 @@ namespace ImageSharp.Tests.Common
fixed (Foo* pSource = source)
fixed (Foo* pDest = dest)
{
ArrayPointer<Foo> apSource = new ArrayPointer<Foo>(source, pSource);
ArrayPointer<Foo> apDest = new ArrayPointer<Foo>(dest, pDest);
BufferPointer<Foo> apSource = new BufferPointer<Foo>(source, pSource);
BufferPointer<Foo> apDest = new BufferPointer<Foo>(dest, pDest);
ArrayPointer.Copy(apSource, apDest, count);
BufferPointer.Copy(apSource, apDest, count);
}
Assert.Equal(source[0], dest[0]);
@ -115,10 +115,10 @@ namespace ImageSharp.Tests.Common
fixed (Foo* pSource = source)
fixed (byte* pDest = dest)
{
ArrayPointer<Foo> apSource = new ArrayPointer<Foo>(source, pSource);
ArrayPointer<byte> apDest = new ArrayPointer<byte>(dest, pDest);
BufferPointer<Foo> apSource = new BufferPointer<Foo>(source, pSource);
BufferPointer<byte> apDest = new BufferPointer<byte>(dest, pDest);
ArrayPointer.Copy(apSource, apDest, count);
BufferPointer.Copy(apSource, apDest, count);
}
Assert.True(ElementsAreEqual(source, dest, 0));
@ -138,10 +138,10 @@ namespace ImageSharp.Tests.Common
fixed(byte* pSource = source)
fixed (Foo* pDest = dest)
{
ArrayPointer<byte> apSource = new ArrayPointer<byte>(source, pSource);
ArrayPointer<Foo> apDest = new ArrayPointer<Foo>(dest, pDest);
BufferPointer<byte> apSource = new BufferPointer<byte>(source, pSource);
BufferPointer<Foo> apDest = new BufferPointer<Foo>(dest, pDest);
ArrayPointer.Copy(apSource, apDest, count);
BufferPointer.Copy(apSource, apDest, count);
}
Assert.True(ElementsAreEqual(dest, source, 0));

4
tests/ImageSharp.Tests/Common/PinnedBufferTests.cs

@ -57,13 +57,13 @@
}
[Fact]
public void GetArrayPointer()
public void Slice()
{
Foo[] a = { new Foo() { A = 1, B = 2 }, new Foo() { A = 3, B = 4 } };
using (PinnedBuffer<Foo> buffer = new PinnedBuffer<Foo>(a))
{
var arrayPtr = buffer.GetArrayPointer();
var arrayPtr = buffer.Slice();
Assert.Equal(a, arrayPtr.Array);
Assert.Equal(0, arrayPtr.Offset);

0
tests/ImageSharp.Tests/Image/PixelPoolTests.cs → tests/ImageSharp.Tests/Common/PixelDataPoolTests.cs

Loading…
Cancel
Save