Show More
Commit Description:
Various UI improvements.
Commit Description:
Various UI improvements.
References:
File last commit:
Show/Diff file:
Action:
FNA/src/Graphics/Vertices/VertexBuffer.cs
344 lines | 7.2 KiB | text/x-csharp | CSharpLexer
344 lines | 7.2 KiB | text/x-csharp | CSharpLexer
r0 | #region License | |||
/* FNA - XNA4 Reimplementation for Desktop Platforms | ||||
* Copyright 2009-2020 Ethan Lee and the MonoGame Team | ||||
* | ||||
* Released under the Microsoft Public License. | ||||
* See LICENSE for details. | ||||
*/ | ||||
#endregion | ||||
#region Using Statements | ||||
using System; | ||||
using System.Runtime.InteropServices; | ||||
#endregion | ||||
namespace Microsoft.Xna.Framework.Graphics | ||||
{ | ||||
public class VertexBuffer : GraphicsResource | ||||
{ | ||||
#region Public Properties | ||||
public BufferUsage BufferUsage | ||||
{ | ||||
get; | ||||
private set; | ||||
} | ||||
public int VertexCount | ||||
{ | ||||
get; | ||||
private set; | ||||
} | ||||
public VertexDeclaration VertexDeclaration | ||||
{ | ||||
get; | ||||
private set; | ||||
} | ||||
#endregion | ||||
#region Internal Properties | ||||
internal IGLBuffer buffer; | ||||
#endregion | ||||
#region Public Constructors | ||||
public VertexBuffer( | ||||
GraphicsDevice graphicsDevice, | ||||
VertexDeclaration vertexDeclaration, | ||||
int vertexCount, | ||||
BufferUsage bufferUsage | ||||
) : this( | ||||
graphicsDevice, | ||||
vertexDeclaration, | ||||
vertexCount, | ||||
bufferUsage, | ||||
false | ||||
) { | ||||
} | ||||
public VertexBuffer( | ||||
GraphicsDevice graphicsDevice, | ||||
Type type, | ||||
int vertexCount, | ||||
BufferUsage bufferUsage | ||||
) : this( | ||||
graphicsDevice, | ||||
VertexDeclaration.FromType(type), | ||||
vertexCount, | ||||
bufferUsage, | ||||
false | ||||
) { | ||||
} | ||||
#endregion | ||||
#region Protected Constructor | ||||
protected VertexBuffer( | ||||
GraphicsDevice graphicsDevice, | ||||
VertexDeclaration vertexDeclaration, | ||||
int vertexCount, | ||||
BufferUsage bufferUsage, | ||||
bool dynamic | ||||
) { | ||||
if (graphicsDevice == null) | ||||
{ | ||||
throw new ArgumentNullException("graphicsDevice"); | ||||
} | ||||
GraphicsDevice = graphicsDevice; | ||||
VertexDeclaration = vertexDeclaration; | ||||
VertexCount = vertexCount; | ||||
BufferUsage = bufferUsage; | ||||
// Make sure the graphics device is assigned in the vertex declaration. | ||||
if (vertexDeclaration.GraphicsDevice != graphicsDevice) | ||||
{ | ||||
vertexDeclaration.GraphicsDevice = graphicsDevice; | ||||
} | ||||
buffer = GraphicsDevice.GLDevice.GenVertexBuffer( | ||||
dynamic, | ||||
bufferUsage, | ||||
VertexCount, | ||||
VertexDeclaration.VertexStride | ||||
); | ||||
} | ||||
#endregion | ||||
#region Protected Dispose Method | ||||
protected override void Dispose(bool disposing) | ||||
{ | ||||
if (!IsDisposed) | ||||
{ | ||||
GraphicsDevice.GLDevice.AddDisposeVertexBuffer(buffer); | ||||
} | ||||
base.Dispose(disposing); | ||||
} | ||||
#endregion | ||||
#region Public GetData Methods | ||||
public void GetData<T>(T[] data) where T : struct | ||||
{ | ||||
GetData<T>( | ||||
0, | ||||
data, | ||||
0, | ||||
data.Length, | ||||
Marshal.SizeOf(typeof(T)) | ||||
); | ||||
} | ||||
public void GetData<T>( | ||||
T[] data, | ||||
int startIndex, | ||||
int elementCount | ||||
) where T : struct { | ||||
GetData<T>( | ||||
0, | ||||
data, | ||||
startIndex, | ||||
elementCount, | ||||
Marshal.SizeOf(typeof(T)) | ||||
); | ||||
} | ||||
public void GetData<T>( | ||||
int offsetInBytes, | ||||
T[] data, | ||||
int startIndex, | ||||
int elementCount, | ||||
int vertexStride | ||||
) where T : struct { | ||||
if (data == null) | ||||
{ | ||||
throw new ArgumentNullException("data"); | ||||
} | ||||
if (data.Length < (startIndex + elementCount)) | ||||
{ | ||||
throw new ArgumentOutOfRangeException( | ||||
"elementCount", | ||||
"This parameter must be a valid index within the array." | ||||
); | ||||
} | ||||
if (BufferUsage == BufferUsage.WriteOnly) | ||||
{ | ||||
throw new NotSupportedException("Calling GetData on a resource that was created with BufferUsage.WriteOnly is not supported."); | ||||
} | ||||
int elementSizeInBytes = Marshal.SizeOf(typeof(T)); | ||||
if (vertexStride == 0) | ||||
{ | ||||
vertexStride = elementSizeInBytes; | ||||
} | ||||
else if (vertexStride < elementSizeInBytes) | ||||
{ | ||||
throw new ArgumentOutOfRangeException( | ||||
"vertexStride", | ||||
"The vertex stride is too small for the type of data requested. This is not allowed." | ||||
); | ||||
} | ||||
if ( elementCount > 1 && | ||||
(elementCount * vertexStride) > (VertexCount * VertexDeclaration.VertexStride) ) | ||||
{ | ||||
throw new InvalidOperationException("The array is not the correct size for the amount of data requested."); | ||||
} | ||||
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); | ||||
GraphicsDevice.GLDevice.GetVertexBufferData( | ||||
buffer, | ||||
offsetInBytes, | ||||
handle.AddrOfPinnedObject(), | ||||
startIndex, | ||||
elementCount, | ||||
elementSizeInBytes, | ||||
vertexStride | ||||
); | ||||
handle.Free(); | ||||
} | ||||
#endregion | ||||
#region Public SetData Methods | ||||
public void SetData<T>(T[] data) where T : struct | ||||
{ | ||||
ErrorCheck(data, 0, data.Length, Marshal.SizeOf(typeof(T))); | ||||
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); | ||||
GraphicsDevice.GLDevice.SetVertexBufferData( | ||||
buffer, | ||||
0, | ||||
handle.AddrOfPinnedObject(), | ||||
data.Length * Marshal.SizeOf(typeof(T)), | ||||
SetDataOptions.None | ||||
); | ||||
handle.Free(); | ||||
} | ||||
public void SetData<T>( | ||||
T[] data, | ||||
int startIndex, | ||||
int elementCount | ||||
) where T : struct { | ||||
ErrorCheck(data, startIndex, elementCount, Marshal.SizeOf(typeof(T))); | ||||
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); | ||||
GraphicsDevice.GLDevice.SetVertexBufferData( | ||||
buffer, | ||||
0, | ||||
handle.AddrOfPinnedObject() + (startIndex * Marshal.SizeOf(typeof(T))), | ||||
elementCount * Marshal.SizeOf(typeof(T)), | ||||
SetDataOptions.None | ||||
); | ||||
handle.Free(); | ||||
} | ||||
public void SetData<T>( | ||||
int offsetInBytes, | ||||
T[] data, | ||||
int startIndex, | ||||
int elementCount, | ||||
int vertexStride | ||||
) where T : struct { | ||||
ErrorCheck(data, startIndex, elementCount, vertexStride); | ||||
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); | ||||
GraphicsDevice.GLDevice.SetVertexBufferData( | ||||
buffer, | ||||
offsetInBytes, | ||||
handle.AddrOfPinnedObject() + (startIndex * Marshal.SizeOf(typeof(T))), | ||||
elementCount * Marshal.SizeOf(typeof(T)), | ||||
SetDataOptions.None | ||||
); | ||||
handle.Free(); | ||||
} | ||||
#endregion | ||||
#region Public Extensions | ||||
public void SetDataPointerEXT( | ||||
int offsetInBytes, | ||||
IntPtr data, | ||||
int dataLength, | ||||
SetDataOptions options | ||||
) { | ||||
GraphicsDevice.GLDevice.SetVertexBufferData( | ||||
buffer, | ||||
offsetInBytes, | ||||
data, | ||||
dataLength, | ||||
options | ||||
); | ||||
} | ||||
#endregion | ||||
#region Internal Methods | ||||
[System.Diagnostics.Conditional("DEBUG")] | ||||
internal void ErrorCheck<T>( | ||||
T[] data, | ||||
int startIndex, | ||||
int elementCount, | ||||
int vertexStride | ||||
) where T : struct { | ||||
if (data == null) | ||||
{ | ||||
throw new ArgumentNullException("data"); | ||||
} | ||||
if ((startIndex + elementCount > data.Length) || elementCount <= 0) | ||||
{ | ||||
throw new InvalidOperationException( | ||||
"The array specified in the data parameter" + | ||||
" is not the correct size for the amount of" + | ||||
" data requested." | ||||
); | ||||
} | ||||
if ( elementCount > 1 && | ||||
(elementCount * vertexStride) > (VertexCount * VertexDeclaration.VertexStride) ) | ||||
{ | ||||
throw new InvalidOperationException( | ||||
"The vertex stride is larger than the vertex buffer." | ||||
); | ||||
} | ||||
int elementSizeInBytes = Marshal.SizeOf(typeof(T)); | ||||
if (vertexStride == 0) | ||||
{ | ||||
vertexStride = elementSizeInBytes; | ||||
} | ||||
if (vertexStride < elementSizeInBytes) | ||||
{ | ||||
throw new ArgumentOutOfRangeException( | ||||
"The vertex stride must be greater than" + | ||||
" or equal to the size of the specified data (" + | ||||
elementSizeInBytes.ToString() + ")." | ||||
); | ||||
} | ||||
} | ||||
#endregion | ||||
#region Internal Context Reset Method | ||||
/// <summary> | ||||
/// The GraphicsDevice is resetting, so GPU resources must be recreated. | ||||
/// </summary> | ||||
internal protected override void GraphicsDeviceResetting() | ||||
{ | ||||
// FIXME: Do we even want to bother with DeviceResetting for GL? -flibit | ||||
} | ||||
#endregion | ||||
} | ||||
} | ||||