diff --git a/src/ImageSharp/Common/Memory/BufferSpan.cs b/src/ImageSharp/Common/Memory/BufferSpan.cs index 09adadc7d..6dad393c3 100644 --- a/src/ImageSharp/Common/Memory/BufferSpan.cs +++ b/src/ImageSharp/Common/Memory/BufferSpan.cs @@ -64,26 +64,34 @@ namespace ImageSharp if (PerTypeValues.IsPrimitiveType) { Buffer.BlockCopy(source.Array, source.ByteOffset, destination.Array, destination.ByteOffset, byteCount); + return; } - else if (byteCount > ByteCountThreshold) - { - ref byte destRef = ref Unsafe.As(ref destination.DangerousGetPinnableReference()); - fixed (void* pinnedPtr = &destRef) + ref byte destRef = ref Unsafe.As(ref destination.DangerousGetPinnableReference()); + + fixed (void* pinnedDest = &destRef) + { +#if !NETSTANDARD1_1 + ref byte srcRef = ref source.DangerousGetPinnableReference(); + fixed (void* pinnedSrc = &srcRef) { - Marshal.Copy(source.Array, source.Start, (IntPtr)pinnedPtr, byteCount); + Buffer.MemoryCopy(pinnedSrc, pinnedDest, byteCount, byteCount); + return; } - } - else - { +#else + if (byteCount > ByteCountThreshold) + { + IntPtr ptr = (IntPtr)pinnedDest; + Marshal.Copy(source.Array, source.Start, ptr, byteCount); + } + ref byte srcRef = ref source.DangerousGetPinnableReference(); - ref byte destRef = ref Unsafe.As(ref destination.DangerousGetPinnableReference()); fixed (void* pinnedSrc = &srcRef) - fixed (void* pinnedDest = &destRef) { - Unsafe.CopyBlock(pinnedDest, pinnedSrc, (uint)byteCount); + Unsafe.CopyBlock(pinnedSrc, pinnedDest, (uint)byteCount); } +#endif } } @@ -113,48 +121,59 @@ namespace ImageSharp where T : struct where TDest : struct { - // TODO: Refactor this method when Unsafe.CopyBlock(ref T, ref T) gets available! + // TODO: Use Unsafe.CopyBlock(ref T, ref T) for small buffers when it gets available! int byteCount = SizeOf(countInSource); if (PerTypeValues.IsPrimitiveType && PerTypeValues.IsPrimitiveType) { Buffer.BlockCopy(source.Array, source.ByteOffset, destination.Array, destination.ByteOffset, byteCount); + return; } - else if (byteCount > ByteCountThreshold) - { - ref byte destRef = ref Unsafe.As(ref destination.DangerousGetPinnableReference()); - fixed (void* pinnedPtr = &destRef) + ref byte destRef = ref Unsafe.As(ref destination.DangerousGetPinnableReference()); + + fixed (void* pinnedDest = &destRef) + { +#if !NETSTANDARD1_1 + ref byte srcRef = ref Unsafe.As(ref source.DangerousGetPinnableReference()); + fixed (void* pinnedSrc = &srcRef) { - IntPtr ptr = (IntPtr)pinnedPtr; + Buffer.MemoryCopy(pinnedSrc, pinnedDest, byteCount, byteCount); + return; + } +#else + if (byteCount > ByteCountThreshold) + { + IntPtr ptr = (IntPtr)pinnedDest; if (Unsafe.SizeOf() == sizeof(long)) { Marshal.Copy(Unsafe.As(source.Array), source.Start, ptr, countInSource); + return; } else if (Unsafe.SizeOf() == sizeof(int)) { Marshal.Copy(Unsafe.As(source.Array), source.Start, ptr, countInSource); + return; } else if (Unsafe.SizeOf() == sizeof(short)) { Marshal.Copy(Unsafe.As(source.Array), source.Start, ptr, countInSource); + return; } else if (Unsafe.SizeOf() == sizeof(byte)) { Marshal.Copy(Unsafe.As(source.Array), source.Start, ptr, countInSource); + return; } } - } - else - { + ref byte srcRef = ref Unsafe.As(ref source.DangerousGetPinnableReference()); - ref byte destRef = ref Unsafe.As(ref destination.DangerousGetPinnableReference()); fixed (void* pinnedSrc = &srcRef) - fixed (void* pinnedDest = &destRef) { - Unsafe.CopyBlock(pinnedDest, pinnedSrc, (uint)byteCount); + Unsafe.CopyBlock(pinnedSrc, pinnedDest, (uint)byteCount); } +#endif } }