assets stream data directly into unmanaged memory
parent
3bd435746b
commit
1cf04a7279
|
@ -53,11 +53,8 @@ namespace MoonWorks.Audio
|
||||||
}
|
}
|
||||||
|
|
||||||
// mostly borrowed from https://github.com/FNA-XNA/FNA/blob/b71b4a35ae59970ff0070dea6f8620856d8d4fec/src/Audio/SoundEffect.cs#L385
|
// mostly borrowed from https://github.com/FNA-XNA/FNA/blob/b71b4a35ae59970ff0070dea6f8620856d8d4fec/src/Audio/SoundEffect.cs#L385
|
||||||
public static StaticSound LoadWav(AudioDevice device, string filePath)
|
public static unsafe StaticSound LoadWav(AudioDevice device, string filePath)
|
||||||
{
|
{
|
||||||
// Sample data
|
|
||||||
byte[] data;
|
|
||||||
|
|
||||||
// WaveFormatEx data
|
// WaveFormatEx data
|
||||||
ushort wFormatTag;
|
ushort wFormatTag;
|
||||||
ushort nChannels;
|
ushort nChannels;
|
||||||
|
@ -68,141 +65,144 @@ namespace MoonWorks.Audio
|
||||||
int samplerLoopStart = 0;
|
int samplerLoopStart = 0;
|
||||||
int samplerLoopEnd = 0;
|
int samplerLoopEnd = 0;
|
||||||
|
|
||||||
using (BinaryReader reader = new BinaryReader(File.OpenRead(filePath)))
|
using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
|
||||||
|
using var reader = new BinaryReader(stream);
|
||||||
|
|
||||||
|
// RIFF Signature
|
||||||
|
string signature = new string(reader.ReadChars(4));
|
||||||
|
if (signature != "RIFF")
|
||||||
{
|
{
|
||||||
// RIFF Signature
|
throw new NotSupportedException("Specified stream is not a wave file.");
|
||||||
string signature = new string(reader.ReadChars(4));
|
|
||||||
if (signature != "RIFF")
|
|
||||||
{
|
|
||||||
throw new NotSupportedException("Specified stream is not a wave file.");
|
|
||||||
}
|
|
||||||
|
|
||||||
reader.ReadUInt32(); // Riff Chunk Size
|
|
||||||
|
|
||||||
string wformat = new string(reader.ReadChars(4));
|
|
||||||
if (wformat != "WAVE")
|
|
||||||
{
|
|
||||||
throw new NotSupportedException("Specified stream is not a wave file.");
|
|
||||||
}
|
|
||||||
|
|
||||||
// WAVE Header
|
|
||||||
string format_signature = new string(reader.ReadChars(4));
|
|
||||||
while (format_signature != "fmt ")
|
|
||||||
{
|
|
||||||
reader.ReadBytes(reader.ReadInt32());
|
|
||||||
format_signature = new string(reader.ReadChars(4));
|
|
||||||
}
|
|
||||||
|
|
||||||
int format_chunk_size = reader.ReadInt32();
|
|
||||||
|
|
||||||
wFormatTag = reader.ReadUInt16();
|
|
||||||
nChannels = reader.ReadUInt16();
|
|
||||||
nSamplesPerSec = reader.ReadUInt32();
|
|
||||||
nAvgBytesPerSec = reader.ReadUInt32();
|
|
||||||
nBlockAlign = reader.ReadUInt16();
|
|
||||||
wBitsPerSample = reader.ReadUInt16();
|
|
||||||
|
|
||||||
// Reads residual bytes
|
|
||||||
if (format_chunk_size > 16)
|
|
||||||
{
|
|
||||||
reader.ReadBytes(format_chunk_size - 16);
|
|
||||||
}
|
|
||||||
|
|
||||||
// data Signature
|
|
||||||
string data_signature = new string(reader.ReadChars(4));
|
|
||||||
while (data_signature.ToLowerInvariant() != "data")
|
|
||||||
{
|
|
||||||
reader.ReadBytes(reader.ReadInt32());
|
|
||||||
data_signature = new string(reader.ReadChars(4));
|
|
||||||
}
|
|
||||||
if (data_signature != "data")
|
|
||||||
{
|
|
||||||
throw new NotSupportedException("Specified wave file is not supported.");
|
|
||||||
}
|
|
||||||
|
|
||||||
int waveDataLength = reader.ReadInt32();
|
|
||||||
data = reader.ReadBytes(waveDataLength);
|
|
||||||
|
|
||||||
// Scan for other chunks
|
|
||||||
while (reader.PeekChar() != -1)
|
|
||||||
{
|
|
||||||
char[] chunkIDChars = reader.ReadChars(4);
|
|
||||||
if (chunkIDChars.Length < 4)
|
|
||||||
{
|
|
||||||
break; // EOL!
|
|
||||||
}
|
|
||||||
byte[] chunkSizeBytes = reader.ReadBytes(4);
|
|
||||||
if (chunkSizeBytes.Length < 4)
|
|
||||||
{
|
|
||||||
break; // EOL!
|
|
||||||
}
|
|
||||||
string chunk_signature = new string(chunkIDChars);
|
|
||||||
int chunkDataSize = BitConverter.ToInt32(chunkSizeBytes, 0);
|
|
||||||
if (chunk_signature == "smpl") // "smpl", Sampler Chunk Found
|
|
||||||
{
|
|
||||||
reader.ReadUInt32(); // Manufacturer
|
|
||||||
reader.ReadUInt32(); // Product
|
|
||||||
reader.ReadUInt32(); // Sample Period
|
|
||||||
reader.ReadUInt32(); // MIDI Unity Note
|
|
||||||
reader.ReadUInt32(); // MIDI Pitch Fraction
|
|
||||||
reader.ReadUInt32(); // SMPTE Format
|
|
||||||
reader.ReadUInt32(); // SMPTE Offset
|
|
||||||
uint numSampleLoops = reader.ReadUInt32();
|
|
||||||
int samplerData = reader.ReadInt32();
|
|
||||||
|
|
||||||
for (int i = 0; i < numSampleLoops; i += 1)
|
|
||||||
{
|
|
||||||
reader.ReadUInt32(); // Cue Point ID
|
|
||||||
reader.ReadUInt32(); // Type
|
|
||||||
int start = reader.ReadInt32();
|
|
||||||
int end = reader.ReadInt32();
|
|
||||||
reader.ReadUInt32(); // Fraction
|
|
||||||
reader.ReadUInt32(); // Play Count
|
|
||||||
|
|
||||||
if (i == 0) // Grab loopStart and loopEnd from first sample loop
|
|
||||||
{
|
|
||||||
samplerLoopStart = start;
|
|
||||||
samplerLoopEnd = end;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (samplerData != 0) // Read Sampler Data if it exists
|
|
||||||
{
|
|
||||||
reader.ReadBytes(samplerData);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else // Read unwanted chunk data and try again
|
|
||||||
{
|
|
||||||
reader.ReadBytes(chunkDataSize);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// End scan
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return new StaticSound(
|
reader.ReadUInt32(); // Riff Chunk Size
|
||||||
|
|
||||||
|
string wformat = new string(reader.ReadChars(4));
|
||||||
|
if (wformat != "WAVE")
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("Specified stream is not a wave file.");
|
||||||
|
}
|
||||||
|
|
||||||
|
// WAVE Header
|
||||||
|
string format_signature = new string(reader.ReadChars(4));
|
||||||
|
while (format_signature != "fmt ")
|
||||||
|
{
|
||||||
|
reader.ReadBytes(reader.ReadInt32());
|
||||||
|
format_signature = new string(reader.ReadChars(4));
|
||||||
|
}
|
||||||
|
|
||||||
|
int format_chunk_size = reader.ReadInt32();
|
||||||
|
|
||||||
|
wFormatTag = reader.ReadUInt16();
|
||||||
|
nChannels = reader.ReadUInt16();
|
||||||
|
nSamplesPerSec = reader.ReadUInt32();
|
||||||
|
nAvgBytesPerSec = reader.ReadUInt32();
|
||||||
|
nBlockAlign = reader.ReadUInt16();
|
||||||
|
wBitsPerSample = reader.ReadUInt16();
|
||||||
|
|
||||||
|
// Reads residual bytes
|
||||||
|
if (format_chunk_size > 16)
|
||||||
|
{
|
||||||
|
reader.ReadBytes(format_chunk_size - 16);
|
||||||
|
}
|
||||||
|
|
||||||
|
// data Signature
|
||||||
|
string data_signature = new string(reader.ReadChars(4));
|
||||||
|
while (data_signature.ToLowerInvariant() != "data")
|
||||||
|
{
|
||||||
|
reader.ReadBytes(reader.ReadInt32());
|
||||||
|
data_signature = new string(reader.ReadChars(4));
|
||||||
|
}
|
||||||
|
if (data_signature != "data")
|
||||||
|
{
|
||||||
|
throw new NotSupportedException("Specified wave file is not supported.");
|
||||||
|
}
|
||||||
|
|
||||||
|
int waveDataLength = reader.ReadInt32();
|
||||||
|
var waveDataBuffer = NativeMemory.Alloc((nuint) waveDataLength);
|
||||||
|
var waveDataSpan = new Span<byte>(waveDataBuffer, waveDataLength);
|
||||||
|
stream.ReadExactly(waveDataSpan);
|
||||||
|
|
||||||
|
// Scan for other chunks
|
||||||
|
while (reader.PeekChar() != -1)
|
||||||
|
{
|
||||||
|
char[] chunkIDChars = reader.ReadChars(4);
|
||||||
|
if (chunkIDChars.Length < 4)
|
||||||
|
{
|
||||||
|
break; // EOL!
|
||||||
|
}
|
||||||
|
byte[] chunkSizeBytes = reader.ReadBytes(4);
|
||||||
|
if (chunkSizeBytes.Length < 4)
|
||||||
|
{
|
||||||
|
break; // EOL!
|
||||||
|
}
|
||||||
|
string chunk_signature = new string(chunkIDChars);
|
||||||
|
int chunkDataSize = BitConverter.ToInt32(chunkSizeBytes, 0);
|
||||||
|
if (chunk_signature == "smpl") // "smpl", Sampler Chunk Found
|
||||||
|
{
|
||||||
|
reader.ReadUInt32(); // Manufacturer
|
||||||
|
reader.ReadUInt32(); // Product
|
||||||
|
reader.ReadUInt32(); // Sample Period
|
||||||
|
reader.ReadUInt32(); // MIDI Unity Note
|
||||||
|
reader.ReadUInt32(); // MIDI Pitch Fraction
|
||||||
|
reader.ReadUInt32(); // SMPTE Format
|
||||||
|
reader.ReadUInt32(); // SMPTE Offset
|
||||||
|
uint numSampleLoops = reader.ReadUInt32();
|
||||||
|
int samplerData = reader.ReadInt32();
|
||||||
|
|
||||||
|
for (int i = 0; i < numSampleLoops; i += 1)
|
||||||
|
{
|
||||||
|
reader.ReadUInt32(); // Cue Point ID
|
||||||
|
reader.ReadUInt32(); // Type
|
||||||
|
int start = reader.ReadInt32();
|
||||||
|
int end = reader.ReadInt32();
|
||||||
|
reader.ReadUInt32(); // Fraction
|
||||||
|
reader.ReadUInt32(); // Play Count
|
||||||
|
|
||||||
|
if (i == 0) // Grab loopStart and loopEnd from first sample loop
|
||||||
|
{
|
||||||
|
samplerLoopStart = start;
|
||||||
|
samplerLoopEnd = end;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (samplerData != 0) // Read Sampler Data if it exists
|
||||||
|
{
|
||||||
|
reader.ReadBytes(samplerData);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // Read unwanted chunk data and try again
|
||||||
|
{
|
||||||
|
reader.ReadBytes(chunkDataSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// End scan
|
||||||
|
|
||||||
|
var sound = new StaticSound(
|
||||||
device,
|
device,
|
||||||
wFormatTag,
|
wFormatTag,
|
||||||
wBitsPerSample,
|
wBitsPerSample,
|
||||||
nBlockAlign,
|
nBlockAlign,
|
||||||
nChannels,
|
nChannels,
|
||||||
nSamplesPerSec,
|
nSamplesPerSec,
|
||||||
data,
|
(nint) waveDataBuffer,
|
||||||
0,
|
(uint) waveDataLength,
|
||||||
(uint) data.Length
|
true
|
||||||
);
|
);
|
||||||
|
|
||||||
|
return sound;
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe StaticSound(
|
public StaticSound(
|
||||||
AudioDevice device,
|
AudioDevice device,
|
||||||
ushort formatTag,
|
ushort formatTag,
|
||||||
ushort bitsPerSample,
|
ushort bitsPerSample,
|
||||||
ushort blockAlign,
|
ushort blockAlign,
|
||||||
ushort channels,
|
ushort channels,
|
||||||
uint samplesPerSecond,
|
uint samplesPerSecond,
|
||||||
byte[] buffer,
|
IntPtr bufferPtr,
|
||||||
uint bufferOffset, /* number of bytes */
|
uint bufferLengthInBytes,
|
||||||
uint bufferLength /* number of bytes */
|
bool ownsBuffer) : base(device)
|
||||||
) : base(device)
|
|
||||||
{
|
{
|
||||||
FormatTag = formatTag;
|
FormatTag = formatTag;
|
||||||
BitsPerSample = bitsPerSample;
|
BitsPerSample = bitsPerSample;
|
||||||
|
@ -210,19 +210,17 @@ namespace MoonWorks.Audio
|
||||||
Channels = channels;
|
Channels = channels;
|
||||||
SamplesPerSecond = samplesPerSecond;
|
SamplesPerSecond = samplesPerSecond;
|
||||||
|
|
||||||
Handle = new FAudio.FAudioBuffer();
|
Handle = new FAudio.FAudioBuffer
|
||||||
Handle.Flags = FAudio.FAUDIO_END_OF_STREAM;
|
{
|
||||||
Handle.pContext = IntPtr.Zero;
|
Flags = FAudio.FAUDIO_END_OF_STREAM,
|
||||||
Handle.AudioBytes = bufferLength;
|
pContext = IntPtr.Zero,
|
||||||
Handle.pAudioData = (nint) NativeMemory.Alloc(bufferLength);
|
pAudioData = bufferPtr,
|
||||||
Marshal.Copy(buffer, (int) bufferOffset, Handle.pAudioData, (int) bufferLength);
|
AudioBytes = bufferLengthInBytes,
|
||||||
Handle.PlayBegin = 0;
|
PlayBegin = 0,
|
||||||
Handle.PlayLength = 0;
|
PlayLength = 0
|
||||||
|
};
|
||||||
|
|
||||||
LoopStart = 0;
|
OwnsBuffer = ownsBuffer;
|
||||||
LoopLength = 0;
|
|
||||||
|
|
||||||
OwnsBuffer = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe StaticSound(
|
public unsafe StaticSound(
|
||||||
|
@ -256,35 +254,6 @@ namespace MoonWorks.Audio
|
||||||
OwnsBuffer = true;
|
OwnsBuffer = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public StaticSound(
|
|
||||||
AudioDevice device,
|
|
||||||
ushort formatTag,
|
|
||||||
ushort bitsPerSample,
|
|
||||||
ushort blockAlign,
|
|
||||||
ushort channels,
|
|
||||||
uint samplesPerSecond,
|
|
||||||
IntPtr bufferPtr,
|
|
||||||
uint bufferLengthInBytes) : base(device)
|
|
||||||
{
|
|
||||||
FormatTag = formatTag;
|
|
||||||
BitsPerSample = bitsPerSample;
|
|
||||||
BlockAlign = blockAlign;
|
|
||||||
Channels = channels;
|
|
||||||
SamplesPerSecond = samplesPerSecond;
|
|
||||||
|
|
||||||
Handle = new FAudio.FAudioBuffer
|
|
||||||
{
|
|
||||||
Flags = FAudio.FAUDIO_END_OF_STREAM,
|
|
||||||
pContext = IntPtr.Zero,
|
|
||||||
pAudioData = bufferPtr,
|
|
||||||
AudioBytes = bufferLengthInBytes,
|
|
||||||
PlayBegin = 0,
|
|
||||||
PlayLength = 0
|
|
||||||
};
|
|
||||||
|
|
||||||
OwnsBuffer = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets a sound instance from the pool.
|
/// Gets a sound instance from the pool.
|
||||||
/// NOTE: If you lose track of instances, you will create garbage collection pressure!
|
/// NOTE: If you lose track of instances, you will create garbage collection pressure!
|
||||||
|
|
|
@ -15,10 +15,13 @@ namespace MoonWorks.Audio
|
||||||
|
|
||||||
public unsafe static StreamingSoundOgg Load(AudioDevice device, string filePath)
|
public unsafe static StreamingSoundOgg Load(AudioDevice device, string filePath)
|
||||||
{
|
{
|
||||||
var fileData = File.ReadAllBytes(filePath);
|
var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
|
||||||
var fileDataPtr = NativeMemory.Alloc((nuint) fileData.Length);
|
var fileDataPtr = NativeMemory.Alloc((nuint) fileStream.Length);
|
||||||
Marshal.Copy(fileData, 0, (IntPtr) fileDataPtr, fileData.Length);
|
var fileDataSpan = new Span<byte>(fileDataPtr, (int) fileStream.Length);
|
||||||
var vorbisHandle = FAudio.stb_vorbis_open_memory((IntPtr) fileDataPtr, fileData.Length, out int error, IntPtr.Zero);
|
fileStream.ReadExactly(fileDataSpan);
|
||||||
|
fileStream.Close();
|
||||||
|
|
||||||
|
var vorbisHandle = FAudio.stb_vorbis_open_memory((IntPtr) fileDataPtr, fileDataSpan.Length, out int error, IntPtr.Zero);
|
||||||
if (error != 0)
|
if (error != 0)
|
||||||
{
|
{
|
||||||
NativeMemory.Free(fileDataPtr);
|
NativeMemory.Free(fileDataPtr);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using WellspringCS;
|
using WellspringCS;
|
||||||
|
|
||||||
namespace MoonWorks.Graphics.Font
|
namespace MoonWorks.Graphics.Font
|
||||||
|
@ -12,11 +13,15 @@ namespace MoonWorks.Graphics.Font
|
||||||
|
|
||||||
public unsafe Font(string path)
|
public unsafe Font(string path)
|
||||||
{
|
{
|
||||||
var bytes = File.ReadAllBytes(path);
|
var fileStream = new FileStream(path, FileMode.Open, FileAccess.Read);
|
||||||
fixed (byte* pByte = &bytes[0])
|
var fileByteBuffer = NativeMemory.Alloc((nuint) fileStream.Length);
|
||||||
{
|
var fileByteSpan = new Span<byte>(fileByteBuffer, (int) fileStream.Length);
|
||||||
Handle = Wellspring.Wellspring_CreateFont((IntPtr) pByte, (uint) bytes.Length);
|
fileStream.ReadExactly(fileByteSpan);
|
||||||
}
|
fileStream.Close();
|
||||||
|
|
||||||
|
Handle = Wellspring.Wellspring_CreateFont((IntPtr) fileByteBuffer, (uint) fileByteSpan.Length);
|
||||||
|
|
||||||
|
NativeMemory.Free(fileByteBuffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void Dispose(bool disposing)
|
protected virtual void Dispose(bool disposing)
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
using RefreshCS;
|
using RefreshCS;
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
|
||||||
namespace MoonWorks.Graphics
|
namespace MoonWorks.Graphics
|
||||||
{
|
{
|
||||||
|
@ -13,10 +14,8 @@ namespace MoonWorks.Graphics
|
||||||
|
|
||||||
public unsafe ShaderModule(GraphicsDevice device, string filePath) : base(device)
|
public unsafe ShaderModule(GraphicsDevice device, string filePath) : base(device)
|
||||||
{
|
{
|
||||||
using (FileStream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read))
|
using var stream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
|
||||||
{
|
Handle = CreateFromStream(device, stream);
|
||||||
Handle = CreateFromStream(device, stream);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public unsafe ShaderModule(GraphicsDevice device, Stream stream) : base(device)
|
public unsafe ShaderModule(GraphicsDevice device, Stream stream) : base(device)
|
||||||
|
@ -24,19 +23,20 @@ namespace MoonWorks.Graphics
|
||||||
Handle = CreateFromStream(device, stream);
|
Handle = CreateFromStream(device, stream);
|
||||||
}
|
}
|
||||||
|
|
||||||
private unsafe static IntPtr CreateFromStream(GraphicsDevice device, Stream stream)
|
private static unsafe IntPtr CreateFromStream(GraphicsDevice device, Stream stream)
|
||||||
{
|
{
|
||||||
var bytecode = new byte[stream.Length];
|
var bytecodeBuffer = NativeMemory.Alloc((nuint) stream.Length);
|
||||||
stream.Read(bytecode, 0, (int) stream.Length);
|
var bytecodeSpan = new Span<byte>(bytecodeBuffer, (int) stream.Length);
|
||||||
|
stream.ReadExactly(bytecodeSpan);
|
||||||
|
|
||||||
fixed (byte* ptr = bytecode)
|
Refresh.ShaderModuleCreateInfo shaderModuleCreateInfo;
|
||||||
{
|
shaderModuleCreateInfo.codeSize = (nuint) stream.Length;
|
||||||
Refresh.ShaderModuleCreateInfo shaderModuleCreateInfo;
|
shaderModuleCreateInfo.byteCode = (nint) bytecodeBuffer;
|
||||||
shaderModuleCreateInfo.codeSize = (UIntPtr) bytecode.Length;
|
|
||||||
shaderModuleCreateInfo.byteCode = (IntPtr) ptr;
|
|
||||||
|
|
||||||
return Refresh.Refresh_CreateShaderModule(device.Handle, shaderModuleCreateInfo);
|
var shaderModule = Refresh.Refresh_CreateShaderModule(device.Handle, shaderModuleCreateInfo);
|
||||||
}
|
|
||||||
|
NativeMemory.Free(bytecodeBuffer);
|
||||||
|
return shaderModule;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
using RefreshCS;
|
using RefreshCS;
|
||||||
|
|
||||||
namespace MoonWorks.Graphics
|
namespace MoonWorks.Graphics
|
||||||
|
@ -217,47 +218,44 @@ namespace MoonWorks.Graphics
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Texture LoadDDS(GraphicsDevice graphicsDevice, CommandBuffer commandBuffer, System.IO.Stream stream)
|
public unsafe static Texture LoadDDS(GraphicsDevice graphicsDevice, CommandBuffer commandBuffer, System.IO.Stream stream)
|
||||||
{
|
{
|
||||||
using (var reader = new BinaryReader(stream))
|
using var reader = new BinaryReader(stream);
|
||||||
|
Texture texture;
|
||||||
|
int faces;
|
||||||
|
ParseDDS(reader, out var format, out var width, out var height, out var levels, out var isCube);
|
||||||
|
|
||||||
|
if (isCube)
|
||||||
{
|
{
|
||||||
Texture texture;
|
texture = CreateTextureCube(graphicsDevice, (uint) width, format, TextureUsageFlags.Sampler, (uint) levels);
|
||||||
int faces;
|
faces = 6;
|
||||||
ParseDDS(reader, out var format, out var width, out var height, out var levels, out var isCube);
|
|
||||||
|
|
||||||
if (isCube)
|
|
||||||
{
|
|
||||||
texture = CreateTextureCube(graphicsDevice, (uint) width, format, TextureUsageFlags.Sampler, (uint) levels);
|
|
||||||
faces = 6;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
texture = CreateTexture2D(graphicsDevice, (uint) width, (uint) height, format, TextureUsageFlags.Sampler, (uint) levels);
|
|
||||||
faces = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < faces; i += 1)
|
|
||||||
{
|
|
||||||
for (int j = 0; j < levels; j += 1)
|
|
||||||
{
|
|
||||||
var levelWidth = width >> j;
|
|
||||||
var levelHeight = height >> j;
|
|
||||||
|
|
||||||
var pixels = reader.ReadBytes(
|
|
||||||
Texture.CalculateDDSLevelSize(
|
|
||||||
levelWidth,
|
|
||||||
levelHeight,
|
|
||||||
format
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
var textureSlice = new TextureSlice(texture, new Rect(0, 0, levelWidth, levelHeight), 0, (uint) i, (uint) j);
|
|
||||||
commandBuffer.SetTextureData(textureSlice, pixels);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return texture;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
texture = CreateTexture2D(graphicsDevice, (uint) width, (uint) height, format, TextureUsageFlags.Sampler, (uint) levels);
|
||||||
|
faces = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < faces; i += 1)
|
||||||
|
{
|
||||||
|
for (int j = 0; j < levels; j += 1)
|
||||||
|
{
|
||||||
|
var levelWidth = width >> j;
|
||||||
|
var levelHeight = height >> j;
|
||||||
|
|
||||||
|
var levelSize = CalculateDDSLevelSize(levelWidth, levelHeight, format);
|
||||||
|
var byteBuffer = NativeMemory.Alloc((nuint) levelSize);
|
||||||
|
var byteSpan = new Span<byte>(byteBuffer, levelSize);
|
||||||
|
stream.ReadExactly(byteSpan);
|
||||||
|
|
||||||
|
var textureSlice = new TextureSlice(texture, new Rect(0, 0, levelWidth, levelHeight), 0, (uint) i, (uint) j);
|
||||||
|
commandBuffer.SetTextureData(textureSlice, (nint) byteBuffer, (uint) levelSize);
|
||||||
|
|
||||||
|
NativeMemory.Free(byteBuffer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return texture;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
/* Heavily based on https://github.com/FNA-XNA/FNA/blob/master/src/Media/Xiph/VideoPlayer.cs */
|
/* Heavily based on https://github.com/FNA-XNA/FNA/blob/master/src/Media/Xiph/VideoPlayer.cs */
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
|
using SDL2;
|
||||||
|
|
||||||
namespace MoonWorks.Video
|
namespace MoonWorks.Video
|
||||||
{
|
{
|
||||||
|
@ -16,6 +18,7 @@ namespace MoonWorks.Video
|
||||||
internal IntPtr Handle;
|
internal IntPtr Handle;
|
||||||
private IntPtr rwData;
|
private IntPtr rwData;
|
||||||
private void* videoData;
|
private void* videoData;
|
||||||
|
private int videoDataLength;
|
||||||
|
|
||||||
public double FramesPerSecond => fps;
|
public double FramesPerSecond => fps;
|
||||||
public int Width => yWidth;
|
public int Width => yWidth;
|
||||||
|
@ -31,16 +34,19 @@ namespace MoonWorks.Video
|
||||||
|
|
||||||
public Video(string filename)
|
public Video(string filename)
|
||||||
{
|
{
|
||||||
if (!System.IO.File.Exists(filename))
|
if (!File.Exists(filename))
|
||||||
{
|
{
|
||||||
throw new ArgumentException("Video file not found!");
|
throw new ArgumentException("Video file not found!");
|
||||||
}
|
}
|
||||||
|
|
||||||
var bytes = System.IO.File.ReadAllBytes(filename);
|
var fileStream = new FileStream(filename, FileMode.Open, FileAccess.Read);
|
||||||
videoData = NativeMemory.Alloc((nuint) bytes.Length);
|
videoDataLength = (int) fileStream.Length;
|
||||||
Marshal.Copy(bytes, 0, (IntPtr) videoData, bytes.Length);
|
videoData = NativeMemory.Alloc((nuint) videoDataLength);
|
||||||
rwData = SDL2.SDL.SDL_RWFromMem((IntPtr) videoData, bytes.Length);
|
var fileBufferSpan = new Span<byte>(videoData, videoDataLength);
|
||||||
|
fileStream.ReadExactly(fileBufferSpan);
|
||||||
|
fileStream.Close();
|
||||||
|
|
||||||
|
rwData = SDL.SDL_RWFromMem((IntPtr) videoData, videoDataLength);
|
||||||
if (Theorafile.tf_open_callbacks(rwData, out Handle, callbacks) < 0)
|
if (Theorafile.tf_open_callbacks(rwData, out Handle, callbacks) < 0)
|
||||||
{
|
{
|
||||||
throw new ArgumentException("Invalid video file!");
|
throw new ArgumentException("Invalid video file!");
|
||||||
|
@ -98,6 +104,7 @@ namespace MoonWorks.Video
|
||||||
|
|
||||||
// free unmanaged resources (unmanaged objects)
|
// free unmanaged resources (unmanaged objects)
|
||||||
Theorafile.tf_close(ref Handle);
|
Theorafile.tf_close(ref Handle);
|
||||||
|
SDL.SDL_RWclose(rwData);
|
||||||
NativeMemory.Free(videoData);
|
NativeMemory.Free(videoData);
|
||||||
|
|
||||||
IsDisposed = true;
|
IsDisposed = true;
|
||||||
|
|
Loading…
Reference in New Issue