mirror of
https://github.com/ryujinx-mirror/ryujinx.git
synced 2025-03-13 02:39:39 -05:00

* rebase * add methods Ryyjinx.Common EmbeddedResources and SteamUtils * GAL changes - change SetData() methods and ThreadedTexture commands to use IMemoryOwner<byte> instead of SpanOrArray<byte> * Ryujinx.Graphics.Texture: change texture conversion methods to return IMemoryOwner<byte> and allocate from ByteMemoryPool * Ryujinx.Graphics.OpenGL: update ITexture and Texture-like types with SetData() methods to take IMemoryOwner<byte> instead of SpanOrArray<byte> * Ryujinx.Graphics.Vulkan: update ITexture and Texture-like types with SetData() methods to take IMemoryOwner<byte> instead of SpanOrArray<byte> * Ryujinx.Graphics.Gpu: update ITexture and Texture-like types with SetData() methods to take IMemoryOwner<byte> instead of SpanOrArray<byte> * Remove now-unused SpanOrArray<T> * post-rebase cleanup * PixelConverter: remove unsafe modifier on safe methods, and remove one unnecessary cast * use ByteMemoryPool.Rent() in GetWritableRegion() impls * fix formatting, rename `ReadRentedMemory()` to `ReadFileToRentedMemory()`` * Texture.ConvertToHostCompatibleFormat(): dispose of `result` in Astc decode branch
91 lines
2.8 KiB
C#
91 lines
2.8 KiB
C#
using Microsoft.IO;
|
|
using Ryujinx.Common.Memory;
|
|
using System.Buffers;
|
|
using System.IO;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace Ryujinx.Common.Utilities
|
|
{
|
|
public static class StreamUtils
|
|
{
|
|
public static byte[] StreamToBytes(Stream input)
|
|
{
|
|
using RecyclableMemoryStream output = StreamToRecyclableMemoryStream(input);
|
|
|
|
return output.ToArray();
|
|
}
|
|
|
|
public static IMemoryOwner<byte> StreamToRentedMemory(Stream input)
|
|
{
|
|
if (input is MemoryStream inputMemoryStream)
|
|
{
|
|
return MemoryStreamToRentedMemory(inputMemoryStream);
|
|
}
|
|
else if (input.CanSeek)
|
|
{
|
|
long bytesExpected = input.Length;
|
|
|
|
IMemoryOwner<byte> ownedMemory = ByteMemoryPool.Rent(bytesExpected);
|
|
|
|
var destSpan = ownedMemory.Memory.Span;
|
|
|
|
int totalBytesRead = 0;
|
|
|
|
while (totalBytesRead < bytesExpected)
|
|
{
|
|
int bytesRead = input.Read(destSpan[totalBytesRead..]);
|
|
|
|
if (bytesRead == 0)
|
|
{
|
|
ownedMemory.Dispose();
|
|
|
|
throw new IOException($"Tried reading {bytesExpected} but the stream closed after reading {totalBytesRead}.");
|
|
}
|
|
|
|
totalBytesRead += bytesRead;
|
|
}
|
|
|
|
return ownedMemory;
|
|
}
|
|
else
|
|
{
|
|
// If input is (non-seekable) then copy twice: first into a RecyclableMemoryStream, then to a rented IMemoryOwner<byte>.
|
|
using RecyclableMemoryStream output = StreamToRecyclableMemoryStream(input);
|
|
|
|
return MemoryStreamToRentedMemory(output);
|
|
}
|
|
}
|
|
|
|
public static async Task<byte[]> StreamToBytesAsync(Stream input, CancellationToken cancellationToken = default)
|
|
{
|
|
using MemoryStream stream = MemoryStreamManager.Shared.GetStream();
|
|
|
|
await input.CopyToAsync(stream, cancellationToken);
|
|
|
|
return stream.ToArray();
|
|
}
|
|
|
|
private static IMemoryOwner<byte> MemoryStreamToRentedMemory(MemoryStream input)
|
|
{
|
|
input.Position = 0;
|
|
|
|
IMemoryOwner<byte> ownedMemory = ByteMemoryPool.Rent(input.Length);
|
|
|
|
// Discard the return value because we assume reading a MemoryStream always succeeds completely.
|
|
_ = input.Read(ownedMemory.Memory.Span);
|
|
|
|
return ownedMemory;
|
|
}
|
|
|
|
private static RecyclableMemoryStream StreamToRecyclableMemoryStream(Stream input)
|
|
{
|
|
RecyclableMemoryStream stream = MemoryStreamManager.Shared.GetStream();
|
|
|
|
input.CopyTo(stream);
|
|
|
|
return stream;
|
|
}
|
|
}
|
|
}
|