Ryujinx/Ryujinx.Graphics/Gal/OpenGL/OGLStreamBuffer.cs

125 lines
2.8 KiB
C#
Raw Normal View History

using System;
using OpenTK.Graphics.OpenGL;
namespace Ryujinx.Graphics.Gal.OpenGL
{
abstract class OGLStreamBuffer : IDisposable
{
public int Handle { get; protected set; }
protected BufferTarget Target;
protected int Size;
private bool Mapped = false;
public OGLStreamBuffer(BufferTarget Target, int MaxSize)
{
Handle = 0;
Mapped = false;
this.Target = Target;
this.Size = MaxSize;
}
public static OGLStreamBuffer Create(BufferTarget Target, int MaxSize)
{
return new SubDataBuffer(Target, MaxSize);
}
public void Allocate()
{
if (this.Handle == 0)
{
GL.CreateBuffers(1, out int Handle);
this.Handle = Handle;
InternAllocate();
}
}
public byte[] Map(int Size)
{
if (Handle == 0 || Mapped || Size > this.Size)
{
throw new InvalidOperationException();
}
byte[] Memory = InternMap(Size);
Mapped = true;
return Memory;
}
public void Unmap(int UsedSize)
{
if (Handle == 0 || !Mapped)
{
throw new InvalidOperationException();
}
InternUnmap(UsedSize);
Mapped = false;
}
protected abstract void InternAllocate();
protected abstract byte[] InternMap(int Size);
protected abstract void InternUnmap(int UsedSize);
public void Dispose()
{
Dispose(true);
}
protected virtual void Dispose(bool Disposing)
{
if (Disposing && Handle != 0)
{
GL.DeleteBuffer(Handle);
Handle = 0;
}
}
}
class SubDataBuffer : OGLStreamBuffer
{
private byte[] Memory;
public SubDataBuffer(BufferTarget Target, int MaxSize)
: base(Target, MaxSize)
{
Memory = new byte[MaxSize];
}
protected override void InternAllocate()
{
GL.BindBuffer(Target, Handle);
GL.BufferData(Target, Size, IntPtr.Zero, BufferUsageHint.StreamDraw);
}
protected override byte[] InternMap(int Size)
{
return Memory;
}
protected override void InternUnmap(int UsedSize)
{
GL.BindBuffer(Target, Handle);
unsafe
{
fixed (byte* MemoryPtr = Memory)
{
GL.BufferSubData(Target, IntPtr.Zero, UsedSize, (IntPtr)MemoryPtr);
}
}
}
}
}