Commit Description:
Tidy code.
Commit Description:
Tidy code.
File last commit:
Show/Diff file:
Action:
FNA/src/Graphics/Vertices/VertexBuffer.cs
344 lines | 7.2 KiB | text/x-csharp | CSharpLexer
#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
}
}