#region License
#endregion
#region WIIU_GAMEPAD Option
#endregion
#region Using Statements
using
System;
using
System.Collections.Generic;
using
System.Runtime.InteropServices;
#endregion
namespace
Microsoft.Xna.Framework.Graphics
{
public
class
GraphicsDevice : IDisposable
{
#region Public GraphicsDevice State Properties
public
bool
IsDisposed
{
get
;
private
set
;
}
public
GraphicsDeviceStatus GraphicsDeviceStatus
{
get
{
return
GraphicsDeviceStatus.Normal;
}
}
public
GraphicsAdapter Adapter
{
get
;
private
set
;
}
public
GraphicsProfile GraphicsProfile
{
get
;
private
set
;
}
public
PresentationParameters PresentationParameters
{
get
;
private
set
;
}
#endregion
#region Public Graphics Display Properties
public
DisplayMode DisplayMode
{
get
{
if
(PresentationParameters.IsFullScreen)
{
return
new
DisplayMode(
GLDevice.Backbuffer.Width,
GLDevice.Backbuffer.Height,
SurfaceFormat.Color
);
}
return
Adapter.CurrentDisplayMode;
}
}
#endregion
#region Public GL State Properties
public
TextureCollection Textures
{
get
;
private
set
;
}
public
SamplerStateCollection SamplerStates
{
get
;
private
set
;
}
public
TextureCollection VertexTextures
{
get
;
private
set
;
}
public
SamplerStateCollection VertexSamplerStates
{
get
;
private
set
;
}
public
BlendState BlendState
{
get
{
return
nextBlend;
}
set
{
nextBlend = value;
}
}
public
DepthStencilState DepthStencilState
{
get
{
return
nextDepthStencil;
}
set
{
nextDepthStencil = value;
}
}
public
RasterizerState RasterizerState
{
get
;
set
;
}
private
Rectangle INTERNAL_scissorRectangle;
public
Rectangle ScissorRectangle
{
get
{
return
INTERNAL_scissorRectangle;
}
set
{
INTERNAL_scissorRectangle = value;
GLDevice.SetScissorRect(
value,
RenderTargetCount > 0
);
}
}
private
Viewport INTERNAL_viewport;
public
Viewport Viewport
{
get
{
return
INTERNAL_viewport;
}
set
{
INTERNAL_viewport = value;
GLDevice.SetViewport(
value,
RenderTargetCount > 0
);
}
}
public
Color BlendFactor
{
get
{
return
GLDevice.BlendFactor;
}
set
{
GLDevice.BlendFactor = value;
}
}
public
int
MultiSampleMask
{
get
{
return
GLDevice.MultiSampleMask;
}
set
{
GLDevice.MultiSampleMask = value;
}
}
public
int
ReferenceStencil
{
get
{
return
GLDevice.ReferenceStencil;
}
set
{
GLDevice.ReferenceStencil = value;
}
}
#endregion
#region Public Buffer Object Properties
public
IndexBuffer Indices
{
get
;
set
;
}
#endregion
#region Internal RenderTarget Properties
internal
int
RenderTargetCount
{
get
;
private
set
;
}
#endregion
#region Internal GL Device
internal
readonly
IGLDevice GLDevice;
#endregion
#region Private State Shadowing Variables
private
BlendState currentBlend;
private
BlendState nextBlend;
private
DepthStencilState currentDepthStencil;
private
DepthStencilState nextDepthStencil;
#endregion
#region Private Vertex Sampler Offset Variable
private
int
vertexSamplerStart;
#endregion
#region Internal Sampler Change Queue
private
readonly
Queue<
int
> modifiedSamplers =
new
Queue<
int
>();
private
readonly
Queue<
int
> modifiedVertexSamplers =
new
Queue<
int
>();
#endregion
#region Private Disposal Variables
private
readonly
List<WeakReference> resources =
new
List<WeakReference>();
private
readonly
object
resourcesLock =
new
object
();
#endregion
#region Private Clear Variables
#if DEBUG
private
static
readonly
Vector4 DiscardColor =
new
Color(68, 34, 136, 255).ToVector4();
#else
private
static
readonly
Vector4 DiscardColor =
new
Vector4(0.0f, 0.0f, 0.0f, 1.0f);
#endif
#endregion
#region Private RenderTarget Variables
private
readonly
RenderTargetBinding[] renderTargetBindings =
new
RenderTargetBinding[4];
#endregion
#region Private Buffer Object Variables
private
VertexBufferBinding[] vertexBufferBindings =
new
VertexBufferBinding[16];
private
int
vertexBufferCount = 0;
private
bool
vertexBuffersUpdated =
false
;
#endregion
#region GraphicsDevice Events
#pragma warning disable 0067
public
event
EventHandler<EventArgs> DeviceLost;
#pragma warning restore 0067
public
event
EventHandler<EventArgs> DeviceReset;
public
event
EventHandler<EventArgs> DeviceResetting;
public
event
EventHandler<ResourceCreatedEventArgs> ResourceCreated;
public
event
EventHandler<ResourceDestroyedEventArgs> ResourceDestroyed;
public
event
EventHandler<EventArgs> Disposing;
internal
void
OnResourceCreated()
{
if
(ResourceCreated !=
null
)
{
ResourceCreated(
this
, (ResourceCreatedEventArgs) EventArgs.Empty);
}
}
internal
void
OnResourceDestroyed()
{
if
(ResourceDestroyed !=
null
)
{
ResourceDestroyed(
this
, (ResourceDestroyedEventArgs) EventArgs.Empty);
}
}
#endregion
#region Constructor, Deconstructor, Dispose Methods
/// <summary>
/// Initializes a new instance of the <see cref="GraphicsDevice" /> class.
/// </summary>
/// <param name="adapter">The graphics adapter.</param>
/// <param name="graphicsProfile">The graphics profile.</param>
/// <param name="presentationParameters">The presentation options.</param>
/// <exception cref="ArgumentNullException">
/// <paramref name="presentationParameters"/> is <see langword="null"/>.
/// </exception>
public
GraphicsDevice(
GraphicsAdapter adapter,
GraphicsProfile graphicsProfile,
PresentationParameters presentationParameters
) {
if
(presentationParameters ==
null
)
{
throw
new
ArgumentNullException(
"presentationParameters"
);
}
Adapter = adapter;
PresentationParameters = presentationParameters;
GraphicsProfile = graphicsProfile;
PresentationParameters.MultiSampleCount = MathHelper.ClosestMSAAPower(
PresentationParameters.MultiSampleCount
);
GLDevice = FNAPlatform.CreateGLDevice(PresentationParameters);
Input.Mouse.INTERNAL_BackBufferWidth = PresentationParameters.BackBufferWidth;
Input.Mouse.INTERNAL_BackBufferHeight = PresentationParameters.BackBufferHeight;
BlendState = BlendState.Opaque;
DepthStencilState = DepthStencilState.Default;
RasterizerState = RasterizerState.CullCounterClockwise;
int
maxTextures = Math.Min(GLDevice.MaxTextureSlots, 16);
int
maxVertexTextures = MathHelper.Clamp(GLDevice.MaxTextureSlots - 16, 0, 4);
vertexSamplerStart = GLDevice.MaxTextureSlots - maxVertexTextures;
Textures =
new
TextureCollection(
maxTextures,
modifiedSamplers
);
SamplerStates =
new
SamplerStateCollection(
maxTextures,
modifiedSamplers
);
VertexTextures =
new
TextureCollection(
maxVertexTextures,
modifiedVertexSamplers
);
VertexSamplerStates =
new
SamplerStateCollection(
maxVertexTextures,
modifiedVertexSamplers
);
Viewport =
new
Viewport(PresentationParameters.Bounds);
ScissorRectangle = Viewport.Bounds;
#if WIIU_GAMEPAD
wiiuStream = DRC.drc_new_streamer();
if
(wiiuStream == IntPtr.Zero)
{
FNAPlatform.Log(
"Failed to alloc GamePad stream!"
);
return
;
}
if
(DRC.drc_start_streamer(wiiuStream) < 1)
{
FNAPlatform.Log(
"Failed to start GamePad stream!"
);
DRC.drc_delete_streamer(wiiuStream);
wiiuStream = IntPtr.Zero;
return
;
}
DRC.drc_enable_system_input_feeder(wiiuStream);
wiiuPixelData =
new
byte
[
PresentationParameters.BackBufferWidth *
PresentationParameters.BackBufferHeight *
4
];
#endif
}
~GraphicsDevice()
{
Dispose(
false
);
}
public
void
Dispose()
{
Dispose(
true
);
GC.SuppressFinalize(
this
);
}
protected
virtual
void
Dispose(
bool
disposing)
{
if
(!IsDisposed)
{
if
(disposing)
{
if
(Disposing !=
null
)
{
Disposing(
this
, EventArgs.Empty);
}
lock
(resourcesLock)
{
foreach
(WeakReference resource
in
resources.ToArray())
{
object
target = resource.Target;
if
(target !=
null
)
{
(target
as
IDisposable).Dispose();
}
}
resources.Clear();
}
GLDevice.Dispose();
#if WIIU_GAMEPAD
if
(wiiuStream != IntPtr.Zero)
{
DRC.drc_stop_streamer(wiiuStream);
DRC.drc_delete_streamer(wiiuStream);
wiiuStream = IntPtr.Zero;
}
#endif
}
IsDisposed =
true
;
}
}
#endregion
#region Internal Resource Management Methods
internal
void
AddResourceReference(WeakReference resourceReference)
{
lock
(resourcesLock)
{
resources.Add(resourceReference);
}
}
internal
void
RemoveResourceReference(WeakReference resourceReference)
{
lock
(resourcesLock)
{
resources.Remove(resourceReference);
}
}
#endregion
#region Public Present Method
public
void
Present()
{
GLDevice.SwapBuffers(
null
,
null
,
PresentationParameters.DeviceWindowHandle
);
#if WIIU_GAMEPAD
if
(wiiuStream != IntPtr.Zero)
{
GetBackBufferData(wiiuPixelData);
DRC.drc_push_vid_frame(
wiiuStream,
wiiuPixelData,
(
uint
) wiiuPixelData.Length,
(
ushort
) GLDevice.Backbuffer.Width,
(
ushort
) GLDevice.Backbuffer.Height,
DRC.drc_pixel_format.DRC_RGBA,
DRC.drc_flipping_mode.DRC_NO_FLIP
);
}
#endif
}
public
void
Present(
Rectangle? sourceRectangle,
Rectangle? destinationRectangle,
IntPtr overrideWindowHandle
) {
GLDevice.SwapBuffers(
sourceRectangle,
destinationRectangle,
overrideWindowHandle
);
#if WIIU_GAMEPAD
if
(wiiuStream != IntPtr.Zero)
{
GetBackBufferData(wiiuPixelData);
DRC.drc_push_vid_frame(
wiiuStream,
wiiuPixelData,
(
uint
) wiiuPixelData.Length,
(
ushort
) GLDevice.Backbuffer.Width,
(
ushort
) GLDevice.Backbuffer.Height,
DRC.drc_pixel_format.DRC_RGBA,
DRC.drc_flipping_mode.DRC_NO_FLIP
);
}
#endif
}
#endregion
#region Public Reset Methods
public
void
Reset()
{
Reset(PresentationParameters, Adapter);
}
public
void
Reset(PresentationParameters presentationParameters)
{
Reset(presentationParameters, Adapter);
}
public
void
Reset(
PresentationParameters presentationParameters,
GraphicsAdapter graphicsAdapter
) {
if
(presentationParameters ==
null
)
{
throw
new
ArgumentNullException(
"presentationParameters"
);
}
if
(DeviceResetting !=
null
)
{
DeviceResetting(
this
, EventArgs.Empty);
}
PresentationParameters = presentationParameters;
PresentationParameters.MultiSampleCount = Math.Min(
MathHelper.ClosestMSAAPower(
PresentationParameters.MultiSampleCount
),
GLDevice.MaxMultiSampleCount
);
GLDevice.ResetBackbuffer(
PresentationParameters,
RenderTargetCount > 0
);
Input.Mouse.INTERNAL_BackBufferWidth = PresentationParameters.BackBufferWidth;
Input.Mouse.INTERNAL_BackBufferHeight = PresentationParameters.BackBufferHeight;
#if WIIU_GAMEPAD
wiiuPixelData =
new
byte
[
PresentationParameters.BackBufferWidth *
PresentationParameters.BackBufferHeight *
4
];
#endif
Viewport =
new
Viewport(
0,
0,
PresentationParameters.BackBufferWidth,
PresentationParameters.BackBufferHeight
);
ScissorRectangle =
new
Rectangle(
0,
0,
PresentationParameters.BackBufferWidth,
PresentationParameters.BackBufferHeight
);
Adapter = graphicsAdapter;
if
(DeviceReset !=
null
)
{
DeviceReset(
this
, EventArgs.Empty);
}
}
#endregion
#region Public Clear Methods
public
void
Clear(Color color)
{
Clear(
ClearOptions.Target | ClearOptions.DepthBuffer | ClearOptions.Stencil,
color.ToVector4(),
Viewport.MaxDepth,
0
);
}
public
void
Clear(ClearOptions options, Color color,
float
depth,
int
stencil)
{
Clear(
options,
color.ToVector4(),
depth,
stencil
);
}
public
void
Clear(ClearOptions options, Vector4 color,
float
depth,
int
stencil)
{
DepthFormat dsFormat;
if
(RenderTargetCount == 0)
{
dsFormat = GLDevice.Backbuffer.DepthFormat;
}
else
{
dsFormat = (renderTargetBindings[0].RenderTarget
as
IRenderTarget).DepthStencilFormat;
}
if
(dsFormat == DepthFormat.None)
{
options &= ClearOptions.Target;
}
else
if
(dsFormat != DepthFormat.Depth24Stencil8)
{
options &= ~ClearOptions.Stencil;
}
GLDevice.Clear(
options,
color,
depth,
stencil
);
}
#endregion
#region Public Backbuffer Methods
public
void
GetBackBufferData<T>(T[] data) where T :
struct
{
GLDevice.ReadBackbuffer(data, 0, data.Length,
null
);
}
public
void
GetBackBufferData<T>(
T[] data,
int
startIndex,
int
elementCount
) where T :
struct
{
GLDevice.ReadBackbuffer(data, startIndex, elementCount,
null
);
}
public
void
GetBackBufferData<T>(
Rectangle? rect,
T[] data,
int
startIndex,
int
elementCount
) where T :
struct
{
GLDevice.ReadBackbuffer(data, startIndex, elementCount, rect);
}
#endregion
#region Public RenderTarget Methods
public
void
SetRenderTarget(RenderTarget2D renderTarget)
{
if
(renderTarget ==
null
)
{
SetRenderTargets(
null
);
}
else
{
SetRenderTargets(
new
RenderTargetBinding(renderTarget));
}
}
public
void
SetRenderTarget(RenderTargetCube renderTarget, CubeMapFace cubeMapFace)
{
if
(renderTarget ==
null
)
{
SetRenderTargets(
null
);
}
else
{
SetRenderTargets(
new
RenderTargetBinding(renderTarget, cubeMapFace));
}
}
public
void
SetRenderTargets(
params
RenderTargetBinding[] renderTargets)
{
if
(renderTargets ==
null
&& RenderTargetCount == 0)
{
return
;
}
else
if
(renderTargets !=
null
&& renderTargets.Length == RenderTargetCount)
{
bool
isRedundant =
true
;
for
(
int
i = 0; i < renderTargets.Length; i += 1)
{
if
( renderTargets[i].RenderTarget != renderTargetBindings[i].RenderTarget ||
renderTargets[i].CubeMapFace != renderTargetBindings[i].CubeMapFace )
{
isRedundant =
false
;
}
}
if
(isRedundant)
{
return
;
}
}
int
newWidth;
int
newHeight;
RenderTargetUsage clearTarget;
if
(renderTargets ==
null
|| renderTargets.Length == 0)
{
GLDevice.SetRenderTargets(
null
,
null
, DepthFormat.None);
newWidth = PresentationParameters.BackBufferWidth;
newHeight = PresentationParameters.BackBufferHeight;
clearTarget = PresentationParameters.RenderTargetUsage;
for
(
int
i = 0; i < RenderTargetCount; i += 1)
{
GLDevice.ResolveTarget(renderTargetBindings[i]);
}
Array.Clear(renderTargetBindings, 0, renderTargetBindings.Length);
RenderTargetCount = 0;
}
else
{
IRenderTarget target = renderTargets[0].RenderTarget
as
IRenderTarget;
GLDevice.SetRenderTargets(
renderTargets,
target.DepthStencilBuffer,
target.DepthStencilFormat
);
newWidth = target.Width;
newHeight = target.Height;
clearTarget = target.RenderTargetUsage;
for
(
int
i = 0; i < RenderTargetCount; i += 1)
{
bool
stillBound =
false
;
for
(
int
j = 0; j < renderTargets.Length; j += 1)
{
if
(renderTargetBindings[i].RenderTarget == renderTargets[j].RenderTarget)
{
stillBound =
true
;
break
;
}
}
if
(stillBound)
{
continue
;
}
GLDevice.ResolveTarget(renderTargetBindings[i]);
}
Array.Clear(renderTargetBindings, 0, renderTargetBindings.Length);
Array.Copy(renderTargets, renderTargetBindings, renderTargets.Length);
RenderTargetCount = renderTargets.Length;
}
Viewport =
new
Viewport(0, 0, newWidth, newHeight);
ScissorRectangle =
new
Rectangle(0, 0, newWidth, newHeight);
if
(clearTarget == RenderTargetUsage.DiscardContents)
{
Clear(
ClearOptions.Target | ClearOptions.DepthBuffer | ClearOptions.Stencil,
DiscardColor,
Viewport.MaxDepth,
0
);
}
}
public
RenderTargetBinding[] GetRenderTargets()
{
RenderTargetBinding[] bindings =
new
RenderTargetBinding[RenderTargetCount];
Array.Copy(renderTargetBindings, bindings, RenderTargetCount);
return
bindings;
}
#endregion
#region Public Buffer Object Methods
public
void
SetVertexBuffer(VertexBuffer vertexBuffer)
{
SetVertexBuffer(vertexBuffer, 0);
}
public
void
SetVertexBuffer(VertexBuffer vertexBuffer,
int
vertexOffset)
{
if
(vertexBuffer ==
null
)
{
if
(vertexBufferCount == 0)
{
return
;
}
for
(
int
i = 0; i < vertexBufferCount; i += 1)
{
vertexBufferBindings[i] = VertexBufferBinding.None;
}
vertexBufferCount = 0;
vertexBuffersUpdated =
true
;
return
;
}
if
( !ReferenceEquals(vertexBufferBindings[0].VertexBuffer, vertexBuffer) ||
vertexBufferBindings[0].VertexOffset != vertexOffset )
{
vertexBufferBindings[0] =
new
VertexBufferBinding(
vertexBuffer,
vertexOffset
);
vertexBuffersUpdated =
true
;
}
if
(vertexBufferCount > 1)
{
for
(
int
i = 1; i < vertexBufferCount; i += 1)
{
vertexBufferBindings[i] = VertexBufferBinding.None;
}
vertexBuffersUpdated =
true
;
}
vertexBufferCount = 1;
}
public
void
SetVertexBuffers(
params
VertexBufferBinding[] vertexBuffers)
{
if
(vertexBuffers ==
null
)
{
if
(vertexBufferCount == 0)
{
return
;
}
for
(
int
j = 0; j < vertexBufferCount; j += 1)
{
vertexBufferBindings[j] = VertexBufferBinding.None;
}
vertexBufferCount = 0;
vertexBuffersUpdated =
true
;
return
;
}
if
(vertexBuffers.Length > vertexBufferBindings.Length)
{
throw
new
ArgumentOutOfRangeException(
"vertexBuffers"
,
String.Format(
"Max Vertex Buffers supported is {0}"
,
vertexBufferBindings.Length
)
);
}
int
i = 0;
while
(i < vertexBuffers.Length)
{
if
( !ReferenceEquals(vertexBufferBindings[i].VertexBuffer, vertexBuffers[i].VertexBuffer) ||
vertexBufferBindings[i].VertexOffset != vertexBuffers[i].VertexOffset ||
vertexBufferBindings[i].InstanceFrequency != vertexBuffers[i].InstanceFrequency )
{
vertexBufferBindings[i] = vertexBuffers[i];
vertexBuffersUpdated =
true
;
}
i += 1;
}
if
(vertexBuffers.Length < vertexBufferCount)
{
while
(i < vertexBufferCount)
{
vertexBufferBindings[i] = VertexBufferBinding.None;
i += 1;
}
vertexBuffersUpdated =
true
;
}
vertexBufferCount = vertexBuffers.Length;
}
public
VertexBufferBinding[] GetVertexBuffers()
{
VertexBufferBinding[] result =
new
VertexBufferBinding[vertexBufferCount];
Array.Copy(
vertexBufferBindings,
result,
vertexBufferCount
);
return
result;
}
#endregion
#region DrawPrimitives: VertexBuffer, IndexBuffer
/// <summary>
/// Draw geometry by indexing into the vertex buffer.
/// </summary>
/// <param name="primitiveType">
/// The type of primitives in the index buffer.
/// </param>
/// <param name="baseVertex">
/// Used to offset the vertex range indexed from the vertex buffer.
/// </param>
/// <param name="minVertexIndex">
/// A hint of the lowest vertex indexed relative to baseVertex.
/// </param>
/// <param name="numVertices">
/// A hint of the maximum vertex indexed.
/// </param>
/// <param name="startIndex">
/// The index within the index buffer to start drawing from.
/// </param>
/// <param name="primitiveCount">
/// The number of primitives to render from the index buffer.
/// </param>
public
void
DrawIndexedPrimitives(
PrimitiveType primitiveType,
int
baseVertex,
int
minVertexIndex,
int
numVertices,
int
startIndex,
int
primitiveCount
) {
ApplyState();
GLDevice.ApplyVertexAttributes(
vertexBufferBindings,
vertexBufferCount,
vertexBuffersUpdated,
baseVertex
);
vertexBuffersUpdated =
false
;
GLDevice.DrawIndexedPrimitives(
primitiveType,
baseVertex,
minVertexIndex,
numVertices,
startIndex,
primitiveCount,
Indices
);
}
public
void
DrawInstancedPrimitives(
PrimitiveType primitiveType,
int
baseVertex,
int
minVertexIndex,
int
numVertices,
int
startIndex,
int
primitiveCount,
int
instanceCount
) {
if
(!GLDevice.SupportsHardwareInstancing)
{
throw
new
NoSuitableGraphicsDeviceException(
"Your hardware does not support hardware instancing!"
);
}
ApplyState();
GLDevice.ApplyVertexAttributes(
vertexBufferBindings,
vertexBufferCount,
vertexBuffersUpdated,
baseVertex
);
vertexBuffersUpdated =
false
;
GLDevice.DrawInstancedPrimitives(
primitiveType,
baseVertex,
minVertexIndex,
numVertices,
startIndex,
primitiveCount,
instanceCount,
Indices
);
}
#endregion
#region DrawPrimitives: VertexBuffer, No Indices
public
void
DrawPrimitives(
PrimitiveType primitiveType,
int
vertexStart,
int
primitiveCount
) {
ApplyState();
GLDevice.ApplyVertexAttributes(
vertexBufferBindings,
vertexBufferCount,
vertexBuffersUpdated,
0
);
vertexBuffersUpdated =
false
;
GLDevice.DrawPrimitives(
primitiveType,
vertexStart,
primitiveCount
);
}
#endregion
#region DrawPrimitives: Vertex Arrays, Index Arrays
public
void
DrawUserIndexedPrimitives<T>(
PrimitiveType primitiveType,
T[] vertexData,
int
vertexOffset,
int
numVertices,
short
[] indexData,
int
indexOffset,
int
primitiveCount
) where T :
struct
, IVertexType {
ApplyState();
GCHandle vbHandle = GCHandle.Alloc(vertexData, GCHandleType.Pinned);
GCHandle ibHandle = GCHandle.Alloc(indexData, GCHandleType.Pinned);
IntPtr vbPtr = vbHandle.AddrOfPinnedObject();
IntPtr ibPtr = ibHandle.AddrOfPinnedObject();
VertexDeclaration vertexDeclaration = VertexDeclarationCache<T>.VertexDeclaration;
vertexDeclaration.GraphicsDevice =
this
;
GLDevice.ApplyVertexAttributes(
vertexDeclaration,
vbPtr,
vertexOffset
);
GLDevice.DrawUserIndexedPrimitives(
primitiveType,
vbPtr,
vertexOffset,
numVertices,
ibPtr,
indexOffset,
IndexElementSize.SixteenBits,
primitiveCount
);
ibHandle.Free();
vbHandle.Free();
}
public
void
DrawUserIndexedPrimitives<T>(
PrimitiveType primitiveType,
T[] vertexData,
int
vertexOffset,
int
numVertices,
short
[] indexData,
int
indexOffset,
int
primitiveCount,
VertexDeclaration vertexDeclaration
) where T :
struct
{
ApplyState();
GCHandle vbHandle = GCHandle.Alloc(vertexData, GCHandleType.Pinned);
GCHandle ibHandle = GCHandle.Alloc(indexData, GCHandleType.Pinned);
IntPtr vbPtr = vbHandle.AddrOfPinnedObject();
IntPtr ibPtr = ibHandle.AddrOfPinnedObject();
vertexDeclaration.GraphicsDevice =
this
;
GLDevice.ApplyVertexAttributes(
vertexDeclaration,
vbPtr,
vertexOffset
);
GLDevice.DrawUserIndexedPrimitives(
primitiveType,
vbPtr,
vertexOffset,
numVertices,
ibPtr,
indexOffset,
IndexElementSize.SixteenBits,
primitiveCount
);
ibHandle.Free();
vbHandle.Free();
}
public
void
DrawUserIndexedPrimitives<T>(
PrimitiveType primitiveType,
T[] vertexData,
int
vertexOffset,
int
numVertices,
int
[] indexData,
int
indexOffset,
int
primitiveCount
) where T :
struct
, IVertexType {
ApplyState();
GCHandle vbHandle = GCHandle.Alloc(vertexData, GCHandleType.Pinned);
GCHandle ibHandle = GCHandle.Alloc(indexData, GCHandleType.Pinned);
IntPtr vbPtr = vbHandle.AddrOfPinnedObject();
IntPtr ibPtr = ibHandle.AddrOfPinnedObject();
VertexDeclaration vertexDeclaration = VertexDeclarationCache<T>.VertexDeclaration;
vertexDeclaration.GraphicsDevice =
this
;
GLDevice.ApplyVertexAttributes(
vertexDeclaration,
vbPtr,
vertexOffset
);
GLDevice.DrawUserIndexedPrimitives(
primitiveType,
vbPtr,
vertexOffset,
numVertices,
ibPtr,
indexOffset,
IndexElementSize.ThirtyTwoBits,
primitiveCount
);
ibHandle.Free();
vbHandle.Free();
}
public
void
DrawUserIndexedPrimitives<T>(
PrimitiveType primitiveType,
T[] vertexData,
int
vertexOffset,
int
numVertices,
int
[] indexData,
int
indexOffset,
int
primitiveCount,
VertexDeclaration vertexDeclaration
) where T :
struct
, IVertexType {
ApplyState();
GCHandle vbHandle = GCHandle.Alloc(vertexData, GCHandleType.Pinned);
GCHandle ibHandle = GCHandle.Alloc(indexData, GCHandleType.Pinned);
IntPtr vbPtr = vbHandle.AddrOfPinnedObject();
IntPtr ibPtr = ibHandle.AddrOfPinnedObject();
vertexDeclaration.GraphicsDevice =
this
;
GLDevice.ApplyVertexAttributes(
vertexDeclaration,
vbPtr,
vertexOffset
);
GLDevice.DrawUserIndexedPrimitives(
primitiveType,
vbPtr,
vertexOffset,
numVertices,
ibPtr,
indexOffset,
IndexElementSize.ThirtyTwoBits,
primitiveCount
);
ibHandle.Free();
vbHandle.Free();
}
#endregion
#region DrawPrimitives: Vertex Arrays, No Indices
public
void
DrawUserPrimitives<T>(
PrimitiveType primitiveType,
T[] vertexData,
int
vertexOffset,
int
primitiveCount
) where T :
struct
, IVertexType {
ApplyState();
GCHandle vbHandle = GCHandle.Alloc(vertexData, GCHandleType.Pinned);
IntPtr vbPtr = vbHandle.AddrOfPinnedObject();
VertexDeclaration vertexDeclaration = VertexDeclarationCache<T>.VertexDeclaration;
vertexDeclaration.GraphicsDevice =
this
;
GLDevice.ApplyVertexAttributes(
vertexDeclaration,
vbPtr,
0
);
GLDevice.DrawUserPrimitives(
primitiveType,
vbPtr,
vertexOffset,
primitiveCount
);
vbHandle.Free();
}
public
void
DrawUserPrimitives<T>(
PrimitiveType primitiveType,
T[] vertexData,
int
vertexOffset,
int
primitiveCount,
VertexDeclaration vertexDeclaration
) where T :
struct
{
ApplyState();
GCHandle vbHandle = GCHandle.Alloc(vertexData, GCHandleType.Pinned);
IntPtr vbPtr = vbHandle.AddrOfPinnedObject();
vertexDeclaration.GraphicsDevice =
this
;
GLDevice.ApplyVertexAttributes(
vertexDeclaration,
vbPtr,
0
);
GLDevice.DrawUserPrimitives(
primitiveType,
vbPtr,
vertexOffset,
primitiveCount
);
vbHandle.Free();
}
#endregion
#region FNA Extensions
public
void
SetStringMarkerEXT(
string
text)
{
GLDevice.SetStringMarker(text);
}
#endregion
#region Private State Flush Methods
private
void
ApplyState()
{
if
(currentBlend != nextBlend)
{
GLDevice.SetBlendState(nextBlend);
currentBlend = nextBlend;
}
if
(currentDepthStencil != nextDepthStencil)
{
GLDevice.SetDepthStencilState(nextDepthStencil);
currentDepthStencil = nextDepthStencil;
}
GLDevice.ApplyRasterizerState(
RasterizerState,
RenderTargetCount > 0
);
while
(modifiedSamplers.Count > 0)
{
int
sampler = modifiedSamplers.Dequeue();
GLDevice.VerifySampler(
sampler,
Textures[sampler],
SamplerStates[sampler]
);
}
while
(modifiedVertexSamplers.Count > 0)
{
int
sampler = modifiedVertexSamplers.Dequeue();
GLDevice.VerifySampler(
vertexSamplerStart + sampler,
VertexTextures[sampler],
VertexSamplerStates[sampler]
);
}
}
#endregion
#region Wii U GamePad Support, libdrc Interop
#if WIIU_GAMEPAD
private
static
class
DRC
{
private
const
string
nativeLibName =
"libdrc.so"
;
public
enum
drc_pixel_format
{
DRC_RGB,
DRC_RGBA,
DRC_BGR,
DRC_BGRA,
DRC_RGB565
}
public
enum
drc_flipping_mode
{
DRC_NO_FLIP,
DRC_FLIP_VERTICALLY
}
[DllImportAttribute(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
public
static
extern
IntPtr drc_new_streamer();
[DllImportAttribute(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
public
static
extern
void
drc_delete_streamer(IntPtr self);
[DllImportAttribute(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
public
static
extern
int
drc_start_streamer(IntPtr self);
[DllImportAttribute(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
public
static
extern
void
drc_stop_streamer(IntPtr self);
[DllImportAttribute(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
public
static
extern
int
drc_push_vid_frame(
IntPtr self,
byte
[] buffer,
uint
size,
ushort
width,
ushort
height,
drc_pixel_format pixfmt,
drc_flipping_mode flipmode
);
[DllImportAttribute(nativeLibName, CallingConvention = CallingConvention.Cdecl)]
public
static
extern
void
drc_enable_system_input_feeder(IntPtr self);
}
private
IntPtr wiiuStream;
private
byte
[] wiiuPixelData;
#endif
#endregion
}
}