Show More
Commit Description:
Various UI improvements.
Commit Description:
Various UI improvements.
References:
File last commit:
Show/Diff file:
Action:
FNA/src/Graphics/GraphicsDevice.cs
1559 lines | 35.7 KiB | text/x-csharp | CSharpLexer
1559 lines | 35.7 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 WIIU_GAMEPAD Option | ||||
// #define WIIU_GAMEPAD | ||||
/* This is something I added for myself, because I am a complete goof. | ||||
* You should NEVER enable this in your shipping build. | ||||
* Let your hacker customers self-build FNA, they'll know what to do. | ||||
* -flibit | ||||
*/ | ||||
#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 Internal Constants | ||||
// Per XNA4 General Spec | ||||
internal const int MAX_TEXTURE_SAMPLERS = 16; | ||||
// Per XNA4 HiDef Spec | ||||
internal const int MAX_VERTEX_ATTRIBUTES = 16; | ||||
internal const int MAX_RENDERTARGET_BINDINGS = 4; | ||||
internal const int MAX_VERTEXTEXTURE_SAMPLERS = 4; | ||||
#endregion | ||||
#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; | ||||
} | ||||
/* We have to store this internally because we flip the Rectangle for | ||||
* when we aren't rendering to a target. I'd love to remove this. | ||||
* -flibit | ||||
*/ | ||||
private Rectangle INTERNAL_scissorRectangle; | ||||
public Rectangle ScissorRectangle | ||||
{ | ||||
get | ||||
{ | ||||
return INTERNAL_scissorRectangle; | ||||
} | ||||
set | ||||
{ | ||||
INTERNAL_scissorRectangle = value; | ||||
GLDevice.SetScissorRect(value); | ||||
} | ||||
} | ||||
/* We have to store this internally because we flip the Viewport for | ||||
* when we aren't rendering to a target. I'd love to remove this. | ||||
* -flibit | ||||
*/ | ||||
private Viewport INTERNAL_viewport; | ||||
public Viewport Viewport | ||||
{ | ||||
get | ||||
{ | ||||
return INTERNAL_viewport; | ||||
} | ||||
set | ||||
{ | ||||
INTERNAL_viewport = value; | ||||
GLDevice.SetViewport(value); | ||||
} | ||||
} | ||||
public Color BlendFactor | ||||
{ | ||||
get | ||||
{ | ||||
return GLDevice.BlendFactor; | ||||
} | ||||
set | ||||
{ | ||||
/* FIXME: Does this affect the value found in | ||||
* BlendState? | ||||
* -flibit | ||||
*/ | ||||
GLDevice.BlendFactor = value; | ||||
} | ||||
} | ||||
public int MultiSampleMask | ||||
{ | ||||
get | ||||
{ | ||||
return GLDevice.MultiSampleMask; | ||||
} | ||||
set | ||||
{ | ||||
/* FIXME: Does this affect the value found in | ||||
* BlendState? | ||||
* -flibit | ||||
*/ | ||||
GLDevice.MultiSampleMask = value; | ||||
} | ||||
} | ||||
public int ReferenceStencil | ||||
{ | ||||
get | ||||
{ | ||||
return GLDevice.ReferenceStencil; | ||||
} | ||||
set | ||||
{ | ||||
/* FIXME: Does this affect the value found in | ||||
* DepthStencilState? | ||||
* -flibit | ||||
*/ | ||||
GLDevice.ReferenceStencil = value; | ||||
} | ||||
} | ||||
#endregion | ||||
#region Public Buffer Object Properties | ||||
public IndexBuffer Indices | ||||
{ | ||||
get; | ||||
set; | ||||
} | ||||
#endregion | ||||
#region Internal GL Device | ||||
internal readonly IGLDevice GLDevice; | ||||
#endregion | ||||
#region Internal Pipeline Cache | ||||
internal readonly PipelineCache PipelineCache; | ||||
#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 bool[] modifiedSamplers = new bool[MAX_TEXTURE_SAMPLERS]; | ||||
private readonly bool[] modifiedVertexSamplers = new bool[MAX_VERTEXTEXTURE_SAMPLERS]; | ||||
#endregion | ||||
#region Private Disposal Variables | ||||
/* Use WeakReference for the global resources list as we do not | ||||
* know when a resource may be disposed and collected. We do not | ||||
* want to prevent a resource from being collected by holding a | ||||
* strong reference to it in this list. | ||||
*/ | ||||
private readonly List<WeakReference> resources = new List<WeakReference>(); | ||||
private readonly object resourcesLock = new object(); | ||||
#endregion | ||||
#region Private Clear Variables | ||||
/* On Intel Integrated graphics, there is a fast hw unit for doing | ||||
* clears to colors where all components are either 0 or 255. | ||||
* Despite XNA4 using Purple here, we use black (in Release) to avoid | ||||
* performance warnings on Intel/Mesa. | ||||
* -sulix | ||||
*/ | ||||
#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[MAX_RENDERTARGET_BINDINGS]; | ||||
private int renderTargetCount = 0; | ||||
// Used to prevent allocs on SetRenderTarget() | ||||
private readonly RenderTargetBinding[] singleTargetCache = new RenderTargetBinding[1]; | ||||
#endregion | ||||
#region Private Buffer Object Variables | ||||
private readonly VertexBufferBinding[] vertexBufferBindings = new VertexBufferBinding[MAX_VERTEX_ATTRIBUTES]; | ||||
private int vertexBufferCount = 0; | ||||
private bool vertexBuffersUpdated = false; | ||||
#endregion | ||||
#region GraphicsDevice Events | ||||
#pragma warning disable 0067 | ||||
// We never lose devices, but lol XNA4 compliance -flibit | ||||
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; | ||||
// TODO: Hook this up to GraphicsResource | ||||
internal void OnResourceCreated(object resource) | ||||
{ | ||||
if (ResourceCreated != null) | ||||
{ | ||||
ResourceCreated(this, new ResourceCreatedEventArgs(resource)); | ||||
} | ||||
} | ||||
// TODO: Hook this up to GraphicsResource | ||||
internal void OnResourceDestroyed(string name, object tag) | ||||
{ | ||||
if (ResourceDestroyed != null) | ||||
{ | ||||
ResourceDestroyed(this, new ResourceDestroyedEventArgs(name, tag)); | ||||
} | ||||
} | ||||
#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"); | ||||
} | ||||
// Set the properties from the constructor parameters. | ||||
Adapter = adapter; | ||||
PresentationParameters = presentationParameters; | ||||
GraphicsProfile = graphicsProfile; | ||||
PresentationParameters.MultiSampleCount = MathHelper.ClosestMSAAPower( | ||||
PresentationParameters.MultiSampleCount | ||||
); | ||||
// Set up the IGLDevice | ||||
GLDevice = FNAPlatform.CreateGLDevice(PresentationParameters, adapter); | ||||
// The mouse needs to know this for faux-backbuffer mouse scaling. | ||||
Input.Mouse.INTERNAL_BackBufferWidth = PresentationParameters.BackBufferWidth; | ||||
Input.Mouse.INTERNAL_BackBufferHeight = PresentationParameters.BackBufferHeight; | ||||
// The Touch Panel needs this too, for the same reason. | ||||
Input.Touch.TouchPanel.DisplayWidth = PresentationParameters.BackBufferWidth; | ||||
Input.Touch.TouchPanel.DisplayHeight = PresentationParameters.BackBufferHeight; | ||||
// Force set the default render states. | ||||
BlendState = BlendState.Opaque; | ||||
DepthStencilState = DepthStencilState.Default; | ||||
RasterizerState = RasterizerState.CullCounterClockwise; | ||||
// Initialize the Texture/Sampler state containers | ||||
int maxTextures = Math.Min(GLDevice.MaxTextureSlots, MAX_TEXTURE_SAMPLERS); | ||||
int maxVertexTextures = MathHelper.Clamp( | ||||
GLDevice.MaxTextureSlots - MAX_TEXTURE_SAMPLERS, | ||||
0, | ||||
MAX_VERTEXTEXTURE_SAMPLERS | ||||
); | ||||
vertexSamplerStart = GLDevice.MaxTextureSlots - maxVertexTextures; | ||||
Textures = new TextureCollection( | ||||
maxTextures, | ||||
modifiedSamplers | ||||
); | ||||
SamplerStates = new SamplerStateCollection( | ||||
maxTextures, | ||||
modifiedSamplers | ||||
); | ||||
VertexTextures = new TextureCollection( | ||||
maxVertexTextures, | ||||
modifiedVertexSamplers | ||||
); | ||||
VertexSamplerStates = new SamplerStateCollection( | ||||
maxVertexTextures, | ||||
modifiedVertexSamplers | ||||
); | ||||
// Set the default viewport and scissor rect. | ||||
Viewport = new Viewport(PresentationParameters.Bounds); | ||||
ScissorRectangle = Viewport.Bounds; | ||||
// Set the initial swap interval | ||||
GLDevice.SetPresentationInterval( | ||||
PresentationParameters.PresentationInterval | ||||
); | ||||
// Allocate the pipeline cache to be used by Effects | ||||
PipelineCache = new PipelineCache(this); | ||||
#if WIIU_GAMEPAD | ||||
wiiuStream = DRC.drc_new_streamer(); | ||||
if (wiiuStream == IntPtr.Zero) | ||||
{ | ||||
FNALoggerEXT.LogError("Failed to alloc GamePad stream!"); | ||||
return; | ||||
} | ||||
if (DRC.drc_start_streamer(wiiuStream) < 1) // ??? | ||||
{ | ||||
FNALoggerEXT.LogError("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) | ||||
{ | ||||
// We're about to dispose, notify the application. | ||||
if (Disposing != null) | ||||
{ | ||||
Disposing(this, EventArgs.Empty); | ||||
} | ||||
/* Dispose of all remaining graphics resources before | ||||
* disposing of the GraphicsDevice. | ||||
*/ | ||||
lock (resourcesLock) | ||||
{ | ||||
foreach (WeakReference resource in resources.ToArray()) | ||||
{ | ||||
object target = resource.Target; | ||||
if (target != null) | ||||
{ | ||||
(target as IDisposable).Dispose(); | ||||
} | ||||
} | ||||
resources.Clear(); | ||||
} | ||||
// Dispose of the GL Device/Context | ||||
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 | ||||
) { | ||||
if (overrideWindowHandle == IntPtr.Zero) | ||||
{ | ||||
overrideWindowHandle = PresentationParameters.DeviceWindowHandle; | ||||
} | ||||
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"); | ||||
} | ||||
PresentationParameters = presentationParameters; | ||||
Adapter = graphicsAdapter; | ||||
// Verify MSAA before we really start... | ||||
PresentationParameters.MultiSampleCount = Math.Min( | ||||
MathHelper.ClosestMSAAPower( | ||||
PresentationParameters.MultiSampleCount | ||||
), | ||||
GLDevice.MaxMultiSampleCount | ||||
); | ||||
// We're about to reset, let the application know. | ||||
if (DeviceResetting != null) | ||||
{ | ||||
DeviceResetting(this, EventArgs.Empty); | ||||
} | ||||
/* FIXME: Why are we not doing this...? -flibit | ||||
lock (resourcesLock) | ||||
{ | ||||
foreach (WeakReference resource in resources) | ||||
{ | ||||
object target = resource.Target; | ||||
if (target != null) | ||||
{ | ||||
(target as GraphicsResource).GraphicsDeviceResetting(); | ||||
} | ||||
} | ||||
// Remove references to resources that have been garbage collected. | ||||
resources.RemoveAll(wr => !wr.IsAlive); | ||||
} | ||||
*/ | ||||
/* Reset the backbuffer first, before doing anything else. | ||||
* The GLDevice needs to know what we're up to right away. | ||||
* -flibit | ||||
*/ | ||||
GLDevice.ResetBackbuffer(PresentationParameters); | ||||
// The mouse needs to know this for faux-backbuffer mouse scaling. | ||||
Input.Mouse.INTERNAL_BackBufferWidth = PresentationParameters.BackBufferWidth; | ||||
Input.Mouse.INTERNAL_BackBufferHeight = PresentationParameters.BackBufferHeight; | ||||
// The Touch Panel needs this too, for the same reason. | ||||
Input.Touch.TouchPanel.DisplayWidth = PresentationParameters.BackBufferWidth; | ||||
Input.Touch.TouchPanel.DisplayHeight = PresentationParameters.BackBufferHeight; | ||||
#if WIIU_GAMEPAD | ||||
wiiuPixelData = new byte[ | ||||
PresentationParameters.BackBufferWidth * | ||||
PresentationParameters.BackBufferHeight * | ||||
4 | ||||
]; | ||||
#endif | ||||
// Now, update the viewport | ||||
Viewport = new Viewport( | ||||
0, | ||||
0, | ||||
PresentationParameters.BackBufferWidth, | ||||
PresentationParameters.BackBufferHeight | ||||
); | ||||
// Update the scissor rectangle to our new default target size | ||||
ScissorRectangle = new Rectangle( | ||||
0, | ||||
0, | ||||
PresentationParameters.BackBufferWidth, | ||||
PresentationParameters.BackBufferHeight | ||||
); | ||||
// Finally, update the swap interval | ||||
GLDevice.SetPresentationInterval( | ||||
PresentationParameters.PresentationInterval | ||||
); | ||||
// We just reset, let the application know. | ||||
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) | ||||
{ | ||||
/* FIXME: PresentationParameters.DepthStencilFormat is probably | ||||
* a more accurate value here, but the Backbuffer may disagree. | ||||
* -flibit | ||||
*/ | ||||
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 | ||||
{ | ||||
GetBackBufferData(null, data, 0, data.Length); | ||||
} | ||||
public void GetBackBufferData<T>( | ||||
T[] data, | ||||
int startIndex, | ||||
int elementCount | ||||
) where T : struct { | ||||
GetBackBufferData(null, data, startIndex, elementCount); | ||||
} | ||||
public void GetBackBufferData<T>( | ||||
Rectangle? rect, | ||||
T[] data, | ||||
int startIndex, | ||||
int elementCount | ||||
) where T : struct { | ||||
int x, y, w, h; | ||||
if (rect == null) | ||||
{ | ||||
x = 0; | ||||
y = 0; | ||||
w = GLDevice.Backbuffer.Width; | ||||
h = GLDevice.Backbuffer.Height; | ||||
} | ||||
else | ||||
{ | ||||
x = rect.Value.X; | ||||
y = rect.Value.Y; | ||||
w = rect.Value.Width; | ||||
h = rect.Value.Height; | ||||
} | ||||
int elementSizeInBytes = Marshal.SizeOf(typeof(T)); | ||||
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned); | ||||
GLDevice.ReadBackbuffer( | ||||
handle.AddrOfPinnedObject(), | ||||
data.Length * elementSizeInBytes, | ||||
startIndex, | ||||
elementCount, | ||||
elementSizeInBytes, | ||||
x, | ||||
y, | ||||
w, | ||||
h | ||||
); | ||||
handle.Free(); | ||||
} | ||||
#endregion | ||||
#region Public RenderTarget Methods | ||||
public void SetRenderTarget(RenderTarget2D renderTarget) | ||||
{ | ||||
if (renderTarget == null) | ||||
{ | ||||
SetRenderTargets(null); | ||||
} | ||||
else | ||||
{ | ||||
singleTargetCache[0] = new RenderTargetBinding(renderTarget); | ||||
SetRenderTargets(singleTargetCache); | ||||
} | ||||
} | ||||
public void SetRenderTarget(RenderTargetCube renderTarget, CubeMapFace cubeMapFace) | ||||
{ | ||||
if (renderTarget == null) | ||||
{ | ||||
SetRenderTargets(null); | ||||
} | ||||
else | ||||
{ | ||||
singleTargetCache[0] = new RenderTargetBinding(renderTarget, cubeMapFace); | ||||
SetRenderTargets(singleTargetCache); | ||||
} | ||||
} | ||||
public void SetRenderTargets(params RenderTargetBinding[] renderTargets) | ||||
{ | ||||
// Checking for redundant SetRenderTargets... | ||||
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; | ||||
break; | ||||
} | ||||
} | ||||
if (isRedundant) | ||||
{ | ||||
return; | ||||
} | ||||
} | ||||
int newWidth; | ||||
int newHeight; | ||||
RenderTargetUsage clearTarget; | ||||
if (renderTargets == null || renderTargets.Length == 0) | ||||
{ | ||||
GLDevice.SetRenderTargets(null, null, DepthFormat.None); | ||||
// Set the viewport/scissor to the size of the backbuffer. | ||||
newWidth = PresentationParameters.BackBufferWidth; | ||||
newHeight = PresentationParameters.BackBufferHeight; | ||||
clearTarget = PresentationParameters.RenderTargetUsage; | ||||
// Resolve previous targets, if needed | ||||
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 | ||||
); | ||||
// Set the viewport/scissor to the size of the first render target. | ||||
newWidth = target.Width; | ||||
newHeight = target.Height; | ||||
clearTarget = target.RenderTargetUsage; | ||||
// Resolve previous targets, if needed | ||||
for (int i = 0; i < renderTargetCount; i += 1) | ||||
{ | ||||
// We only need to resolve if the target is no longer bound. | ||||
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; | ||||
} | ||||
// Apply new GL state, clear target if requested | ||||
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() | ||||
{ | ||||
// Return a correctly sized copy our internal array. | ||||
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(); | ||||
// Set up the vertex buffers | ||||
GLDevice.ApplyVertexAttributes( | ||||
vertexBufferBindings, | ||||
vertexBufferCount, | ||||
vertexBuffersUpdated, | ||||
baseVertex | ||||
); | ||||
vertexBuffersUpdated = false; | ||||
GLDevice.DrawIndexedPrimitives( | ||||
primitiveType, | ||||
baseVertex, | ||||
minVertexIndex, | ||||
numVertices, | ||||
startIndex, | ||||
primitiveCount, | ||||
Indices.buffer, | ||||
Indices.IndexElementSize | ||||
); | ||||
} | ||||
public void DrawInstancedPrimitives( | ||||
PrimitiveType primitiveType, | ||||
int baseVertex, | ||||
int minVertexIndex, | ||||
int numVertices, | ||||
int startIndex, | ||||
int primitiveCount, | ||||
int instanceCount | ||||
) { | ||||
// If this device doesn't have the support, just explode now before it's too late. | ||||
if (!GLDevice.SupportsHardwareInstancing) | ||||
{ | ||||
throw new NoSuitableGraphicsDeviceException("Your hardware does not support hardware instancing!"); | ||||
} | ||||
ApplyState(); | ||||
// Set up the vertex buffers | ||||
GLDevice.ApplyVertexAttributes( | ||||
vertexBufferBindings, | ||||
vertexBufferCount, | ||||
vertexBuffersUpdated, | ||||
baseVertex | ||||
); | ||||
vertexBuffersUpdated = false; | ||||
GLDevice.DrawInstancedPrimitives( | ||||
primitiveType, | ||||
baseVertex, | ||||
minVertexIndex, | ||||
numVertices, | ||||
startIndex, | ||||
primitiveCount, | ||||
instanceCount, | ||||
Indices.buffer, | ||||
Indices.IndexElementSize | ||||
); | ||||
} | ||||
#endregion | ||||
#region DrawPrimitives: VertexBuffer, No Indices | ||||
public void DrawPrimitives( | ||||
PrimitiveType primitiveType, | ||||
int vertexStart, | ||||
int primitiveCount | ||||
) { | ||||
ApplyState(); | ||||
// Set up the vertex buffers | ||||
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(); | ||||
// Pin the buffers. | ||||
GCHandle vbHandle = GCHandle.Alloc(vertexData, GCHandleType.Pinned); | ||||
GCHandle ibHandle = GCHandle.Alloc(indexData, GCHandleType.Pinned); | ||||
IntPtr vbPtr = vbHandle.AddrOfPinnedObject(); | ||||
IntPtr ibPtr = ibHandle.AddrOfPinnedObject(); | ||||
// Setup the vertex declaration to point at the vertex data. | ||||
VertexDeclaration vertexDeclaration = VertexDeclarationCache<T>.VertexDeclaration; | ||||
vertexDeclaration.GraphicsDevice = this; | ||||
GLDevice.ApplyVertexAttributes( | ||||
vertexDeclaration, | ||||
vbPtr, | ||||
vertexOffset | ||||
); | ||||
GLDevice.DrawUserIndexedPrimitives( | ||||
primitiveType, | ||||
vbPtr, | ||||
vertexOffset, | ||||
numVertices, | ||||
ibPtr, | ||||
indexOffset, | ||||
IndexElementSize.SixteenBits, | ||||
primitiveCount | ||||
); | ||||
// Release the handles. | ||||
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(); | ||||
// Pin the buffers. | ||||
GCHandle vbHandle = GCHandle.Alloc(vertexData, GCHandleType.Pinned); | ||||
GCHandle ibHandle = GCHandle.Alloc(indexData, GCHandleType.Pinned); | ||||
IntPtr vbPtr = vbHandle.AddrOfPinnedObject(); | ||||
IntPtr ibPtr = ibHandle.AddrOfPinnedObject(); | ||||
// Setup the vertex declaration to point at the vertex data. | ||||
vertexDeclaration.GraphicsDevice = this; | ||||
GLDevice.ApplyVertexAttributes( | ||||
vertexDeclaration, | ||||
vbPtr, | ||||
vertexOffset | ||||
); | ||||
GLDevice.DrawUserIndexedPrimitives( | ||||
primitiveType, | ||||
vbPtr, | ||||
vertexOffset, | ||||
numVertices, | ||||
ibPtr, | ||||
indexOffset, | ||||
IndexElementSize.SixteenBits, | ||||
primitiveCount | ||||
); | ||||
// Release the handles. | ||||
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(); | ||||
// Pin the buffers. | ||||
GCHandle vbHandle = GCHandle.Alloc(vertexData, GCHandleType.Pinned); | ||||
GCHandle ibHandle = GCHandle.Alloc(indexData, GCHandleType.Pinned); | ||||
IntPtr vbPtr = vbHandle.AddrOfPinnedObject(); | ||||
IntPtr ibPtr = ibHandle.AddrOfPinnedObject(); | ||||
// Setup the vertex declaration to point at the vertex data. | ||||
VertexDeclaration vertexDeclaration = VertexDeclarationCache<T>.VertexDeclaration; | ||||
vertexDeclaration.GraphicsDevice = this; | ||||
GLDevice.ApplyVertexAttributes( | ||||
vertexDeclaration, | ||||
vbPtr, | ||||
vertexOffset | ||||
); | ||||
GLDevice.DrawUserIndexedPrimitives( | ||||
primitiveType, | ||||
vbPtr, | ||||
vertexOffset, | ||||
numVertices, | ||||
ibPtr, | ||||
indexOffset, | ||||
IndexElementSize.ThirtyTwoBits, | ||||
primitiveCount | ||||
); | ||||
// Release the handles. | ||||
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 { | ||||
ApplyState(); | ||||
// Pin the buffers. | ||||
GCHandle vbHandle = GCHandle.Alloc(vertexData, GCHandleType.Pinned); | ||||
GCHandle ibHandle = GCHandle.Alloc(indexData, GCHandleType.Pinned); | ||||
IntPtr vbPtr = vbHandle.AddrOfPinnedObject(); | ||||
IntPtr ibPtr = ibHandle.AddrOfPinnedObject(); | ||||
// Setup the vertex declaration to point at the vertex data. | ||||
vertexDeclaration.GraphicsDevice = this; | ||||
GLDevice.ApplyVertexAttributes( | ||||
vertexDeclaration, | ||||
vbPtr, | ||||
vertexOffset | ||||
); | ||||
GLDevice.DrawUserIndexedPrimitives( | ||||
primitiveType, | ||||
vbPtr, | ||||
vertexOffset, | ||||
numVertices, | ||||
ibPtr, | ||||
indexOffset, | ||||
IndexElementSize.ThirtyTwoBits, | ||||
primitiveCount | ||||
); | ||||
// Release the handles. | ||||
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(); | ||||
// Pin the buffers. | ||||
GCHandle vbHandle = GCHandle.Alloc(vertexData, GCHandleType.Pinned); | ||||
IntPtr vbPtr = vbHandle.AddrOfPinnedObject(); | ||||
// Setup the vertex declaration to point at the vertex data. | ||||
VertexDeclaration vertexDeclaration = VertexDeclarationCache<T>.VertexDeclaration; | ||||
vertexDeclaration.GraphicsDevice = this; | ||||
GLDevice.ApplyVertexAttributes( | ||||
vertexDeclaration, | ||||
vbPtr, | ||||
0 | ||||
); | ||||
GLDevice.DrawUserPrimitives( | ||||
primitiveType, | ||||
vbPtr, | ||||
vertexOffset, | ||||
primitiveCount | ||||
); | ||||
// Release the handles. | ||||
vbHandle.Free(); | ||||
} | ||||
public void DrawUserPrimitives<T>( | ||||
PrimitiveType primitiveType, | ||||
T[] vertexData, | ||||
int vertexOffset, | ||||
int primitiveCount, | ||||
VertexDeclaration vertexDeclaration | ||||
) where T : struct { | ||||
ApplyState(); | ||||
// Pin the buffers. | ||||
GCHandle vbHandle = GCHandle.Alloc(vertexData, GCHandleType.Pinned); | ||||
IntPtr vbPtr = vbHandle.AddrOfPinnedObject(); | ||||
// Setup the vertex declaration to point at the vertex data. | ||||
vertexDeclaration.GraphicsDevice = this; | ||||
GLDevice.ApplyVertexAttributes( | ||||
vertexDeclaration, | ||||
vbPtr, | ||||
0 | ||||
); | ||||
GLDevice.DrawUserPrimitives( | ||||
primitiveType, | ||||
vbPtr, | ||||
vertexOffset, | ||||
primitiveCount | ||||
); | ||||
// Release the handles. | ||||
vbHandle.Free(); | ||||
} | ||||
#endregion | ||||
#region FNA Extensions | ||||
public void SetStringMarkerEXT(string text) | ||||
{ | ||||
GLDevice.SetStringMarker(text); | ||||
} | ||||
#endregion | ||||
#region Private State Flush Methods | ||||
private void ApplyState() | ||||
{ | ||||
// Update Blend/DepthStencil, if applicable | ||||
if (currentBlend != nextBlend) | ||||
{ | ||||
GLDevice.SetBlendState(nextBlend); | ||||
currentBlend = nextBlend; | ||||
} | ||||
if (currentDepthStencil != nextDepthStencil) | ||||
{ | ||||
GLDevice.SetDepthStencilState(nextDepthStencil); | ||||
currentDepthStencil = nextDepthStencil; | ||||
} | ||||
// Always update RasterizerState, as it depends on other device states | ||||
GLDevice.ApplyRasterizerState(RasterizerState); | ||||
for (int sampler = 0; sampler < modifiedSamplers.Length; sampler += 1) | ||||
{ | ||||
if (!modifiedSamplers[sampler]) | ||||
{ | ||||
continue; | ||||
} | ||||
modifiedSamplers[sampler] = false; | ||||
GLDevice.VerifySampler( | ||||
sampler, | ||||
Textures[sampler], | ||||
SamplerStates[sampler] | ||||
); | ||||
} | ||||
for (int sampler = 0; sampler < modifiedVertexSamplers.Length; sampler += 1) | ||||
{ | ||||
if (!modifiedVertexSamplers[sampler]) | ||||
{ | ||||
continue; | ||||
} | ||||
modifiedVertexSamplers[sampler] = false; | ||||
/* Believe it or not, this is actually how VertexTextures are | ||||
* stored in XNA4! Their D3D9 renderer just uses the last 4 | ||||
* slots available in the device's sampler array. So that's what | ||||
* we get to do. | ||||
* -flibit | ||||
*/ | ||||
GLDevice.VerifySampler( | ||||
vertexSamplerStart + sampler, | ||||
VertexTextures[sampler], | ||||
VertexSamplerStates[sampler] | ||||
); | ||||
} | ||||
} | ||||
#endregion | ||||
#region Wii U GamePad Support, libdrc Interop | ||||
#if WIIU_GAMEPAD | ||||
private static class DRC | ||||
{ | ||||
// FIXME: Deal with Mac/Windows LibName later. | ||||
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 | ||||
} | ||||
/* IntPtr refers to a drc_streamer* */ | ||||
[DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] | ||||
public static extern IntPtr drc_new_streamer(); | ||||
/* self refers to a drc_streamer* */ | ||||
[DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] | ||||
public static extern void drc_delete_streamer(IntPtr self); | ||||
/* self refers to a drc_streamer* */ | ||||
[DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] | ||||
public static extern int drc_start_streamer(IntPtr self); | ||||
/* self refers to a drc_streamer* */ | ||||
[DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] | ||||
public static extern void drc_stop_streamer(IntPtr self); | ||||
/* self refers to a drc_streamer* */ | ||||
[DllImport(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 | ||||
); | ||||
/* self refers to a drc_streamer* */ | ||||
[DllImport(nativeLibName, CallingConvention = CallingConvention.Cdecl)] | ||||
public static extern void drc_enable_system_input_feeder(IntPtr self); | ||||
} | ||||
private IntPtr wiiuStream; | ||||
private byte[] wiiuPixelData; | ||||
#endif | ||||
#endregion | ||||
} | ||||
} | ||||