Show More
Commit Description:
Add timers for Simulation and various engines...
Commit Description:
Add timers for Simulation and various engines Starting to add additional timers for different stages of the process of updating in order to get more insight into what is slowing it down. The update takes 9ms, which is much longer than it used to. Engine-specific timers are coming later.
File last commit:
Show/Diff file:
Action:
FNA/src/FNAPlatform/OpenGLDevice_GL.cs
1862 lines | 46.8 KiB | text/x-csharp | CSharpLexer
Early working version (including all dependencies, lol).
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;
using SDL2;
#endregion
namespace Microsoft.Xna.Framework.Graphics
{
internal partial class OpenGLDevice : IGLDevice
{
#region Private OpenGL Entry Points
internal enum GLenum : int
{
// Hint Enum Value
GL_DONT_CARE = 0x1100,
// 0/1
GL_ZERO = 0x0000,
GL_ONE = 0x0001,
// Types
GL_BYTE = 0x1400,
GL_UNSIGNED_BYTE = 0x1401,
GL_SHORT = 0x1402,
GL_UNSIGNED_SHORT = 0x1403,
GL_UNSIGNED_INT = 0x1405,
GL_FLOAT = 0x1406,
GL_HALF_FLOAT = 0x140B,
GL_UNSIGNED_SHORT_4_4_4_4_REV = 0x8365,
GL_UNSIGNED_SHORT_5_5_5_1_REV = 0x8366,
GL_UNSIGNED_INT_2_10_10_10_REV = 0x8368,
GL_UNSIGNED_SHORT_5_6_5 = 0x8363,
GL_UNSIGNED_INT_24_8 = 0x84FA,
// Strings
GL_VENDOR = 0x1F00,
GL_RENDERER = 0x1F01,
GL_VERSION = 0x1F02,
GL_EXTENSIONS = 0x1F03,
// Clear Mask
GL_COLOR_BUFFER_BIT = 0x4000,
GL_DEPTH_BUFFER_BIT = 0x0100,
GL_STENCIL_BUFFER_BIT = 0x0400,
// Enable Caps
GL_SCISSOR_TEST = 0x0C11,
GL_DEPTH_TEST = 0x0B71,
GL_STENCIL_TEST = 0x0B90,
// Points
GL_POINT_SPRITE = 0x8861,
GL_COORD_REPLACE = 0x8862,
// Polygons
GL_LINE = 0x1B01,
GL_FILL = 0x1B02,
GL_CW = 0x0900,
GL_CCW = 0x0901,
GL_FRONT = 0x0404,
GL_BACK = 0x0405,
GL_FRONT_AND_BACK = 0x0408,
GL_CULL_FACE = 0x0B44,
GL_POLYGON_OFFSET_FILL = 0x8037,
// Texture Type
GL_TEXTURE_2D = 0x0DE1,
GL_TEXTURE_3D = 0x806F,
GL_TEXTURE_CUBE_MAP = 0x8513,
GL_TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515,
// Blend Mode
GL_BLEND = 0x0BE2,
GL_SRC_COLOR = 0x0300,
GL_ONE_MINUS_SRC_COLOR = 0x0301,
GL_SRC_ALPHA = 0x0302,
GL_ONE_MINUS_SRC_ALPHA = 0x0303,
GL_DST_ALPHA = 0x0304,
GL_ONE_MINUS_DST_ALPHA = 0x0305,
GL_DST_COLOR = 0x0306,
GL_ONE_MINUS_DST_COLOR = 0x0307,
GL_SRC_ALPHA_SATURATE = 0x0308,
GL_CONSTANT_COLOR = 0x8001,
GL_ONE_MINUS_CONSTANT_COLOR = 0x8002,
// Equations
GL_MIN = 0x8007,
GL_MAX = 0x8008,
GL_FUNC_ADD = 0x8006,
GL_FUNC_SUBTRACT = 0x800A,
GL_FUNC_REVERSE_SUBTRACT = 0x800B,
// Comparisons
GL_NEVER = 0x0200,
GL_LESS = 0x0201,
GL_EQUAL = 0x0202,
GL_LEQUAL = 0x0203,
GL_GREATER = 0x0204,
GL_NOTEQUAL = 0x0205,
GL_GEQUAL = 0x0206,
GL_ALWAYS = 0x0207,
// Stencil Operations
GL_INVERT = 0x150A,
GL_KEEP = 0x1E00,
GL_REPLACE = 0x1E01,
GL_INCR = 0x1E02,
GL_DECR = 0x1E03,
GL_INCR_WRAP = 0x8507,
GL_DECR_WRAP = 0x8508,
// Wrap Modes
GL_REPEAT = 0x2901,
GL_CLAMP_TO_EDGE = 0x812F,
GL_MIRRORED_REPEAT = 0x8370,
// Filters
GL_NEAREST = 0x2600,
GL_LINEAR = 0x2601,
GL_NEAREST_MIPMAP_NEAREST = 0x2700,
GL_NEAREST_MIPMAP_LINEAR = 0x2702,
GL_LINEAR_MIPMAP_NEAREST = 0x2701,
GL_LINEAR_MIPMAP_LINEAR = 0x2703,
// Attachments
GL_COLOR_ATTACHMENT0 = 0x8CE0,
GL_DEPTH_ATTACHMENT = 0x8D00,
GL_STENCIL_ATTACHMENT = 0x8D20,
GL_DEPTH_STENCIL_ATTACHMENT = 0x821A,
// Texture Formats
GL_RED = 0x1903,
GL_ALPHA = 0x1906,
GL_RGB = 0x1907,
GL_RGBA = 0x1908,
GL_RGB8 = 0x8051,
GL_RGBA8 = 0x8058,
GL_RGBA4 = 0x8056,
GL_RGB5_A1 = 0x8057,
GL_RGB10_A2_EXT = 0x8059,
GL_RGBA16 = 0x805B,
GL_BGRA = 0x80E1,
GL_DEPTH_COMPONENT16 = 0x81A5,
GL_DEPTH_COMPONENT24 = 0x81A6,
GL_RG = 0x8227,
GL_RG8 = 0x822B,
GL_RG16 = 0x822C,
GL_R16F = 0x822D,
GL_R32F = 0x822E,
GL_RG16F = 0x822F,
GL_RG32F = 0x8230,
GL_RGBA32F = 0x8814,
GL_RGBA16F = 0x881A,
GL_DEPTH24_STENCIL8 = 0x88F0,
GL_COMPRESSED_TEXTURE_FORMATS = 0x86A3,
GL_COMPRESSED_RGBA_S3TC_DXT1_EXT = 0x83F1,
GL_COMPRESSED_RGBA_S3TC_DXT3_EXT = 0x83F2,
GL_COMPRESSED_RGBA_S3TC_DXT5_EXT = 0x83F3,
// Texture Internal Formats
GL_DEPTH_COMPONENT = 0x1902,
GL_DEPTH_STENCIL = 0x84F9,
// Textures
GL_TEXTURE_WRAP_S = 0x2802,
GL_TEXTURE_WRAP_T = 0x2803,
GL_TEXTURE_WRAP_R = 0x8072,
GL_TEXTURE_MAG_FILTER = 0x2800,
GL_TEXTURE_MIN_FILTER = 0x2801,
GL_TEXTURE_MAX_ANISOTROPY_EXT = 0x84FE,
GL_TEXTURE_BASE_LEVEL = 0x813C,
GL_TEXTURE_MAX_LEVEL = 0x813D,
GL_TEXTURE_LOD_BIAS = 0x8501,
GL_UNPACK_ALIGNMENT = 0x0CF5,
// Multitexture
GL_TEXTURE0 = 0x84C0,
GL_MAX_TEXTURE_IMAGE_UNITS = 0x8872,
GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C,
// Buffer objects
GL_ARRAY_BUFFER = 0x8892,
GL_ELEMENT_ARRAY_BUFFER = 0x8893,
GL_STREAM_DRAW = 0x88E0,
GL_STATIC_DRAW = 0x88E4,
GL_MAX_VERTEX_ATTRIBS = 0x8869,
// Render targets
GL_FRAMEBUFFER = 0x8D40,
GL_READ_FRAMEBUFFER = 0x8CA8,
GL_DRAW_FRAMEBUFFER = 0x8CA9,
GL_RENDERBUFFER = 0x8D41,
GL_MAX_DRAW_BUFFERS = 0x8824,
// Draw Primitives
GL_POINTS = 0x0000,
GL_LINES = 0x0001,
GL_LINE_STRIP = 0x0003,
GL_TRIANGLES = 0x0004,
GL_TRIANGLE_STRIP = 0x0005,
// Query Objects
GL_QUERY_RESULT = 0x8866,
GL_QUERY_RESULT_AVAILABLE = 0x8867,
GL_SAMPLES_PASSED = 0x8914,
// Multisampling
GL_MULTISAMPLE = 0x809D,
GL_MAX_SAMPLES = 0x8D57,
GL_SAMPLE_MASK = 0x8E51,
// 3.2 Core Profile
GL_NUM_EXTENSIONS = 0x821D,
// Source Enum Values
GL_DEBUG_SOURCE_API = 0x8246,
GL_DEBUG_SOURCE_WINDOW_SYSTEM = 0x8247,
GL_DEBUG_SOURCE_SHADER_COMPILER = 0x8248,
GL_DEBUG_SOURCE_THIRD_PARTY = 0x8249,
GL_DEBUG_SOURCE_APPLICATION = 0x824A,
GL_DEBUG_SOURCE_OTHER = 0x824B,
// Type Enum Values
GL_DEBUG_TYPE_ERROR = 0x824C,
GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR = 0x824D,
GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR = 0x824E,
GL_DEBUG_TYPE_PORTABILITY = 0x824F,
GL_DEBUG_TYPE_PERFORMANCE = 0x8250,
GL_DEBUG_TYPE_OTHER = 0x8251,
// Severity Enum Values
GL_DEBUG_SEVERITY_HIGH = 0x9146,
GL_DEBUG_SEVERITY_MEDIUM = 0x9147,
GL_DEBUG_SEVERITY_LOW = 0x9148,
GL_DEBUG_SEVERITY_NOTIFICATION = 0x826B
}
// Entry Points
/* BEGIN GET FUNCTIONS */
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate IntPtr GetString(GLenum pname);
private GetString INTERNAL_glGetString;
private string glGetString(GLenum pname)
{
unsafe
{
return new string((sbyte*) INTERNAL_glGetString(pname));
}
}
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void GetIntegerv(GLenum pname, out int param);
private GetIntegerv glGetIntegerv;
/* END GET FUNCTIONS */
/* BEGIN ENABLE/DISABLE FUNCTIONS */
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void Enable(GLenum cap);
private Enable glEnable;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void Disable(GLenum cap);
private Disable glDisable;
/* END ENABLE/DISABLE FUNCTIONS */
/* BEGIN VIEWPORT/SCISSOR FUNCTIONS */
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void G_Viewport(
int x,
int y,
int width,
int height
);
private G_Viewport glViewport;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void DepthRange(
double near_val,
double far_val
);
private DepthRange glDepthRange;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void DepthRangef(
float near_val,
float far_val
);
private DepthRangef glDepthRangef;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void Scissor(
int x,
int y,
int width,
int height
);
private Scissor glScissor;
/* END VIEWPORT/SCISSOR FUNCTIONS */
/* BEGIN BLEND STATE FUNCTIONS */
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void BlendColor(
float red,
float green,
float blue,
float alpha
);
private BlendColor glBlendColor;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void BlendFuncSeparate(
GLenum srcRGB,
GLenum dstRGB,
GLenum srcAlpha,
GLenum dstAlpha
);
private BlendFuncSeparate glBlendFuncSeparate;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void BlendEquationSeparate(
GLenum modeRGB,
GLenum modeAlpha
);
private BlendEquationSeparate glBlendEquationSeparate;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void ColorMask(
bool red,
bool green,
bool blue,
bool alpha
);
private ColorMask glColorMask;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void ColorMaski(
uint buf,
bool red,
bool green,
bool blue,
bool alpha
);
private ColorMaski glColorMaski;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void SampleMaski(uint maskNumber, uint mask);
private SampleMaski glSampleMaski;
/* END BLEND STATE FUNCTIONS */
/* BEGIN DEPTH/STENCIL STATE FUNCTIONS */
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void DepthMask(bool flag);
private DepthMask glDepthMask;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void DepthFunc(GLenum func);
private DepthFunc glDepthFunc;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void StencilMask(int mask);
private StencilMask glStencilMask;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void StencilFuncSeparate(
GLenum face,
GLenum func,
int reference,
int mask
);
private StencilFuncSeparate glStencilFuncSeparate;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void StencilOpSeparate(
GLenum face,
GLenum sfail,
GLenum dpfail,
GLenum dppass
);
private StencilOpSeparate glStencilOpSeparate;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void StencilFunc(
GLenum fail,
int reference,
int mask
);
private StencilFunc glStencilFunc;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void StencilOp(
GLenum fail,
GLenum zfail,
GLenum zpass
);
private StencilOp glStencilOp;
/* END DEPTH/STENCIL STATE FUNCTIONS */
/* BEGIN RASTERIZER STATE FUNCTIONS */
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void FrontFace(GLenum mode);
private FrontFace glFrontFace;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void PolygonMode(GLenum face, GLenum mode);
private PolygonMode glPolygonMode;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void PolygonOffset(float factor, float units);
private PolygonOffset glPolygonOffset;
/* END RASTERIZER STATE FUNCTIONS */
/* BEGIN TEXTURE FUNCTIONS */
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void GenTextures(int n, out uint textures);
private GenTextures glGenTextures;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void DeleteTextures(
int n,
ref uint textures
);
private DeleteTextures glDeleteTextures;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void G_BindTexture(GLenum target, uint texture);
private G_BindTexture glBindTexture;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void TexImage2D(
GLenum target,
int level,
int internalFormat,
int width,
int height,
int border,
GLenum format,
GLenum type,
IntPtr pixels
);
private TexImage2D glTexImage2D;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void TexSubImage2D(
GLenum target,
int level,
int xoffset,
int yoffset,
int width,
int height,
GLenum format,
GLenum type,
IntPtr pixels
);
private TexSubImage2D glTexSubImage2D;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void CompressedTexImage2D(
GLenum target,
int level,
int internalFormat,
int width,
int height,
int border,
int imageSize,
IntPtr pixels
);
private CompressedTexImage2D glCompressedTexImage2D;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void CompressedTexSubImage2D(
GLenum target,
int level,
int xoffset,
int yoffset,
int width,
int height,
GLenum format,
int imageSize,
IntPtr pixels
);
private CompressedTexSubImage2D glCompressedTexSubImage2D;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void TexImage3D(
GLenum target,
int level,
int internalFormat,
int width,
int height,
int depth,
int border,
GLenum format,
GLenum type,
IntPtr pixels
);
private TexImage3D glTexImage3D;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void TexSubImage3D(
GLenum target,
int level,
int xoffset,
int yoffset,
int zoffset,
int width,
int height,
int depth,
GLenum format,
GLenum type,
IntPtr pixels
);
private TexSubImage3D glTexSubImage3D;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void GetTexImage(
GLenum target,
int level,
GLenum format,
GLenum type,
IntPtr pixels
);
private GetTexImage glGetTexImage;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void TexParameteri(
GLenum target,
GLenum pname,
int param
);
private TexParameteri glTexParameteri;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void TexParameterf(
GLenum target,
GLenum pname,
float param
);
private TexParameterf glTexParameterf;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void TexEnvi(
GLenum target,
GLenum pname,
int param
);
private TexEnvi glTexEnvi;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void ActiveTexture(GLenum texture);
private ActiveTexture glActiveTexture;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void PixelStorei(GLenum pname, int param);
private PixelStorei glPixelStorei;
/* END TEXTURE FUNCTIONS */
/* BEGIN BUFFER FUNCTIONS */
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void GenBuffers(int n, out uint buffers);
private GenBuffers glGenBuffers;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void DeleteBuffers(
int n,
ref uint buffers
);
private DeleteBuffers glDeleteBuffers;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void BindBuffer(GLenum target, uint buffer);
private BindBuffer glBindBuffer;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void BufferData(
GLenum target,
IntPtr size,
IntPtr data,
GLenum usage
);
private BufferData glBufferData;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void BufferSubData(
GLenum target,
IntPtr offset,
IntPtr size,
IntPtr data
);
private BufferSubData glBufferSubData;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void GetBufferSubData(
GLenum target,
IntPtr offset,
IntPtr size,
IntPtr data
);
private GetBufferSubData glGetBufferSubData;
/* END BUFFER FUNCTIONS */
/* BEGIN CLEAR FUNCTIONS */
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void ClearColor(
float red,
float green,
float blue,
float alpha
);
private ClearColor glClearColor;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void ClearDepth(double depth);
private ClearDepth glClearDepth;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void ClearDepthf(float depth);
private ClearDepthf glClearDepthf;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void ClearStencil(int s);
private ClearStencil glClearStencil;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void G_Clear(GLenum mask);
private G_Clear glClear;
/* END CLEAR FUNCTIONS */
/* BEGIN FRAMEBUFFER FUNCTIONS */
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void DrawBuffers(int n, IntPtr bufs);
private DrawBuffers glDrawBuffers;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void ReadPixels(
int x,
int y,
int width,
int height,
GLenum format,
GLenum type,
IntPtr pixels
);
private ReadPixels glReadPixels;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void GenerateMipmap(GLenum target);
private GenerateMipmap glGenerateMipmap;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void GenFramebuffers(
int n,
out uint framebuffers
);
private GenFramebuffers glGenFramebuffers;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void DeleteFramebuffers(
int n,
ref uint framebuffers
);
private DeleteFramebuffers glDeleteFramebuffers;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void G_BindFramebuffer(
GLenum target,
uint framebuffer
);
private G_BindFramebuffer glBindFramebuffer;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void FramebufferTexture2D(
GLenum target,
GLenum attachment,
GLenum textarget,
uint texture,
int level
);
private FramebufferTexture2D glFramebufferTexture2D;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void FramebufferRenderbuffer(
GLenum target,
GLenum attachment,
GLenum renderbuffertarget,
uint renderbuffer
);
private FramebufferRenderbuffer glFramebufferRenderbuffer;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void BlitFramebuffer(
int srcX0,
int srcY0,
int srcX1,
int srcY1,
int dstX0,
int dstY0,
int dstX1,
int dstY1,
GLenum mask,
GLenum filter
);
private BlitFramebuffer glBlitFramebuffer;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void InvalidateFramebuffer(
GLenum target,
int numAttachments,
IntPtr attachments
);
InvalidateFramebuffer glInvalidateFramebuffer;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void GenRenderbuffers(
int n,
out uint renderbuffers
);
private GenRenderbuffers glGenRenderbuffers;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void DeleteRenderbuffers(
int n,
ref uint renderbuffers
);
private DeleteRenderbuffers glDeleteRenderbuffers;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void BindRenderbuffer(
GLenum target,
uint renderbuffer
);
private BindRenderbuffer glBindRenderbuffer;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void RenderbufferStorage(
GLenum target,
GLenum internalformat,
int width,
int height
);
private RenderbufferStorage glRenderbufferStorage;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void RenderbufferStorageMultisample(
GLenum target,
int samples,
GLenum internalformat,
int width,
int height
);
private RenderbufferStorageMultisample glRenderbufferStorageMultisample;
/* END FRAMEBUFFER FUNCTIONS */
/* BEGIN VERTEX ATTRIBUTE FUNCTIONS */
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void VertexAttribPointer(
int index,
int size,
GLenum type,
bool normalized,
int stride,
IntPtr pointer
);
private VertexAttribPointer glVertexAttribPointer;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void VertexAttribDivisor(
int index,
int divisor
);
private VertexAttribDivisor glVertexAttribDivisor;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void EnableVertexAttribArray(int index);
private EnableVertexAttribArray glEnableVertexAttribArray;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void DisableVertexAttribArray(int index);
private DisableVertexAttribArray glDisableVertexAttribArray;
/* END VERTEX ATTRIBUTE FUNCTIONS */
/* BEGIN DRAWING FUNCTIONS */
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void DrawElementsInstanced(
GLenum mode,
int count,
GLenum type,
IntPtr indices,
int instanceCount
);
private DrawElementsInstanced glDrawElementsInstanced;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void DrawRangeElements(
GLenum mode,
int start,
int end,
int count,
GLenum type,
IntPtr indices
);
private DrawRangeElements glDrawRangeElements;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void DrawElementsInstancedBaseVertex(
GLenum mode,
int count,
GLenum type,
IntPtr indices,
int instanceCount,
int baseVertex
);
private DrawElementsInstancedBaseVertex glDrawElementsInstancedBaseVertex;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void DrawRangeElementsBaseVertex(
GLenum mode,
int start,
int end,
int count,
GLenum type,
IntPtr indices,
int baseVertex
);
private DrawRangeElementsBaseVertex glDrawRangeElementsBaseVertex;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void DrawElements(
GLenum mode,
int count,
GLenum type,
IntPtr indices
);
private DrawElements glDrawElements;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void DrawArrays(
GLenum mode,
int first,
int count
);
private DrawArrays glDrawArrays;
/* END DRAWING FUNCTIONS */
/* BEGIN QUERY FUNCTIONS */
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void GenQueries(int n, out uint ids);
private GenQueries glGenQueries;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void DeleteQueries(int n, ref uint ids);
private DeleteQueries glDeleteQueries;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void BeginQuery(GLenum target, uint id);
private BeginQuery glBeginQuery;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void EndQuery(GLenum target);
private EndQuery glEndQuery;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void GetQueryObjectuiv(
uint id,
GLenum pname,
out uint param
);
private GetQueryObjectuiv glGetQueryObjectuiv;
/* END QUERY FUNCTIONS */
/* BEGIN 3.2 CORE PROFILE FUNCTIONS */
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate IntPtr GetStringi(GLenum pname, uint index);
private GetStringi INTERNAL_glGetStringi;
private string glGetStringi(GLenum pname, uint index)
{
unsafe
{
return new string((sbyte*) INTERNAL_glGetStringi(pname, index));
}
}
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void GenVertexArrays(int n, out uint arrays);
private GenVertexArrays glGenVertexArrays;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void DeleteVertexArrays(int n, ref uint arrays);
private DeleteVertexArrays glDeleteVertexArrays;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void BindVertexArray(uint array);
private BindVertexArray glBindVertexArray;
/* END 3.2 CORE PROFILE FUNCTIONS */
#if DEBUG
/* BEGIN DEBUG OUTPUT FUNCTIONS */
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void DebugMessageCallback(
IntPtr debugCallback,
IntPtr userParam
);
private DebugMessageCallback glDebugMessageCallback;
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void DebugMessageControl(
GLenum source,
GLenum type,
GLenum severity,
int count,
IntPtr ids, // const GLuint*
bool enabled
);
private DebugMessageControl glDebugMessageControl;
// ARB_debug_output/KHR_debug callback
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void DebugProc(
GLenum source,
GLenum type,
uint id,
GLenum severity,
int length,
IntPtr message, // const GLchar*
IntPtr userParam // const GLvoid*
);
private DebugProc DebugCall = DebugCallback;
private static void DebugCallback(
GLenum source,
GLenum type,
uint id,
GLenum severity,
int length,
IntPtr message, // const GLchar*
IntPtr userParam // const GLvoid*
) {
string err = (
Marshal.PtrToStringAnsi(message) +
"\n\tSource: " +
source.ToString() +
"\n\tType: " +
type.ToString() +
"\n\tSeverity: " +
severity.ToString()
);
if (type == GLenum.GL_DEBUG_TYPE_ERROR)
{
FNALoggerEXT.LogError(err);
throw new InvalidOperationException(err);
}
FNALoggerEXT.LogWarn(err);
}
/* END DEBUG OUTPUT FUNCTIONS */
/* BEGIN STRING MARKER FUNCTIONS */
[UnmanagedFunctionPointer(CallingConvention.StdCall)]
private delegate void StringMarkerGREMEDY(int length, IntPtr chars);
private StringMarkerGREMEDY glStringMarkerGREMEDY;
/* END STRING MARKER FUNCTIONS */
#endif
private void LoadGLGetString()
{
try
{
INTERNAL_glGetString = (GetString) Marshal.GetDelegateForFunctionPointer(
SDL.SDL_GL_GetProcAddress("glGetString"),
typeof(GetString)
);
}
catch
{
throw new NoSuitableGraphicsDeviceException("GRAPHICS DRIVER IS EXTREMELY BROKEN!");
}
}
private void LoadGLEntryPoints(string driver)
{
string baseErrorString;
if (useES3)
{
baseErrorString = "OpenGL ES 3.0";
}
else
{
baseErrorString = "OpenGL 2.1";
}
baseErrorString += " support is required!";
/* Basic entry points. If you don't have these, you're screwed. */
try
{
glGetIntegerv = (GetIntegerv) GetProcAddress(
"glGetIntegerv",
typeof(GetIntegerv)
);
glEnable = (Enable) GetProcAddress(
"glEnable",
typeof(Enable)
);
glDisable = (Disable) GetProcAddress(
"glDisable",
typeof(Disable)
);
glViewport = (G_Viewport) GetProcAddress(
"glViewport",
typeof(G_Viewport)
);
glScissor = (Scissor) GetProcAddress(
"glScissor",
typeof(Scissor)
);
glBlendColor = (BlendColor) GetProcAddress(
"glBlendColor",
typeof(BlendColor)
);
glBlendFuncSeparate = (BlendFuncSeparate) GetProcAddress(
"glBlendFuncSeparate",
typeof(BlendFuncSeparate)
);
glBlendEquationSeparate = (BlendEquationSeparate) GetProcAddress(
"glBlendEquationSeparate",
typeof(BlendEquationSeparate)
);
glColorMask = (ColorMask) GetProcAddress(
"glColorMask",
typeof(ColorMask)
);
glDepthMask = (DepthMask) GetProcAddress(
"glDepthMask",
typeof(DepthMask)
);
glDepthFunc = (DepthFunc) GetProcAddress(
"glDepthFunc",
typeof(DepthFunc)
);
glStencilMask = (StencilMask) GetProcAddress(
"glStencilMask",
typeof(StencilMask)
);
glStencilFuncSeparate = (StencilFuncSeparate) GetProcAddress(
"glStencilFuncSeparate",
typeof(StencilFuncSeparate)
);
glStencilOpSeparate = (StencilOpSeparate) GetProcAddress(
"glStencilOpSeparate",
typeof(StencilOpSeparate)
);
glStencilFunc = (StencilFunc) GetProcAddress(
"glStencilFunc",
typeof(StencilFunc)
);
glStencilOp = (StencilOp) GetProcAddress(
"glStencilOp",
typeof(StencilOp)
);
glFrontFace = (FrontFace) GetProcAddress(
"glFrontFace",
typeof(FrontFace)
);
glPolygonOffset = (PolygonOffset) GetProcAddress(
"glPolygonOffset",
typeof(PolygonOffset)
);
glGenTextures = (GenTextures) GetProcAddress(
"glGenTextures",
typeof(GenTextures)
);
glDeleteTextures = (DeleteTextures) GetProcAddress(
"glDeleteTextures",
typeof(DeleteTextures)
);
glBindTexture = (G_BindTexture) GetProcAddress(
"glBindTexture",
typeof(G_BindTexture)
);
glTexImage2D = (TexImage2D) GetProcAddress(
"glTexImage2D",
typeof(TexImage2D)
);
glTexSubImage2D = (TexSubImage2D) GetProcAddress(
"glTexSubImage2D",
typeof(TexSubImage2D)
);
glCompressedTexImage2D = (CompressedTexImage2D) GetProcAddress(
"glCompressedTexImage2D",
typeof(CompressedTexImage2D)
);
glCompressedTexSubImage2D = (CompressedTexSubImage2D) GetProcAddress(
"glCompressedTexSubImage2D",
typeof(CompressedTexSubImage2D)
);
glTexParameteri = (TexParameteri) GetProcAddress(
"glTexParameteri",
typeof(TexParameteri)
);
glTexParameterf = (TexParameterf) GetProcAddress(
"glTexParameterf",
typeof(TexParameterf)
);
glActiveTexture = (ActiveTexture) GetProcAddress(
"glActiveTexture",
typeof(ActiveTexture)
);
glPixelStorei = (PixelStorei) GetProcAddress(
"glPixelStorei",
typeof(PixelStorei)
);
glGenBuffers = (GenBuffers) GetProcAddress(
"glGenBuffers",
typeof(GenBuffers)
);
glDeleteBuffers = (DeleteBuffers) GetProcAddress(
"glDeleteBuffers",
typeof(DeleteBuffers)
);
glBindBuffer = (BindBuffer) GetProcAddress(
"glBindBuffer",
typeof(BindBuffer)
);
glBufferData = (BufferData) GetProcAddress(
"glBufferData",
typeof(BufferData)
);
glBufferSubData = (BufferSubData) GetProcAddress(
"glBufferSubData",
typeof(BufferSubData)
);
glClearColor = (ClearColor) GetProcAddress(
"glClearColor",
typeof(ClearColor)
);
glClearStencil = (ClearStencil) GetProcAddress(
"glClearStencil",
typeof(ClearStencil)
);
glClear = (G_Clear) GetProcAddress(
"glClear",
typeof(G_Clear)
);
glDrawBuffers = (DrawBuffers) GetProcAddress(
"glDrawBuffers",
typeof(DrawBuffers)
);
glReadPixels = (ReadPixels) GetProcAddress(
"glReadPixels",
typeof(ReadPixels)
);
glVertexAttribPointer = (VertexAttribPointer) GetProcAddress(
"glVertexAttribPointer",
typeof(VertexAttribPointer)
);
glEnableVertexAttribArray = (EnableVertexAttribArray) GetProcAddress(
"glEnableVertexAttribArray",
typeof(EnableVertexAttribArray)
);
glDisableVertexAttribArray = (DisableVertexAttribArray) GetProcAddress(
"glDisableVertexAttribArray",
typeof(DisableVertexAttribArray)
);
glDrawArrays = (DrawArrays) GetProcAddress(
"glDrawArrays",
typeof(DrawArrays)
);
}
catch (Exception e)
{
throw new NoSuitableGraphicsDeviceException(
baseErrorString +
"\nEntry Point: " + e.Message +
"\n" + driver
);
}
/* ARB_draw_elements_base_vertex is ideal! */
IntPtr ep = SDL.SDL_GL_GetProcAddress("glDrawRangeElementsBaseVertex");
if (ep == IntPtr.Zero)
{
ep = SDL.SDL_GL_GetProcAddress("glDrawRangeElementsBaseVertexOES");
}
supportsBaseVertex = ep != IntPtr.Zero && BUG_HACK_NOTANGLE;
if (supportsBaseVertex)
{
glDrawRangeElementsBaseVertex = (DrawRangeElementsBaseVertex) Marshal.GetDelegateForFunctionPointer(
ep,
typeof(DrawRangeElementsBaseVertex)
);
glDrawRangeElements = (DrawRangeElements) GetProcAddress(
"glDrawRangeElements",
typeof(DrawRangeElements)
);
}
else
{
/* DrawRangeElements is better, and ES3+ should have this */
ep = SDL.SDL_GL_GetProcAddress("glDrawRangeElements");
if (ep != IntPtr.Zero)
{
glDrawRangeElements = (DrawRangeElements) Marshal.GetDelegateForFunctionPointer(
ep,
typeof(DrawRangeElements)
);
glDrawRangeElementsBaseVertex = DrawRangeElementsNoBase;
}
else
{
try
{
glDrawElements = (DrawElements) GetProcAddress(
"glDrawElements",
typeof(DrawElements)
);
}
catch (Exception e)
{
throw new NoSuitableGraphicsDeviceException(
baseErrorString +
"\nEntry Point: " + e.Message +
"\n" + driver
);
}
glDrawRangeElements = DrawRangeElementsUnchecked;
glDrawRangeElementsBaseVertex = DrawRangeElementsNoBaseUnchecked;
}
}
/* These functions are NOT supported in ES.
* NVIDIA or desktop ES might, but real scenarios where you need ES
* will certainly not have these.
* -flibit
*/
if (useES3)
{
ep = SDL.SDL_GL_GetProcAddress("glPolygonMode");
if (ep != IntPtr.Zero)
{
glPolygonMode = (PolygonMode) Marshal.GetDelegateForFunctionPointer(
ep,
typeof(PolygonMode)
);
}
else
{
glPolygonMode = PolygonModeESError;
}
ep = SDL.SDL_GL_GetProcAddress("glGetTexImage");
if (ep != IntPtr.Zero)
{
glGetTexImage = (GetTexImage) Marshal.GetDelegateForFunctionPointer(
ep,
typeof(GetTexImage)
);
}
else
{
glGetTexImage = GetTexImageESError;
}
ep = SDL.SDL_GL_GetProcAddress("glTexEnvi");
if (ep != IntPtr.Zero)
{
glTexEnvi = (TexEnvi) Marshal.GetDelegateForFunctionPointer(
ep,
typeof(TexEnvi)
);
}
ep = SDL.SDL_GL_GetProcAddress("glGetBufferSubData");
if (ep != IntPtr.Zero)
{
glGetBufferSubData = (GetBufferSubData) Marshal.GetDelegateForFunctionPointer(
ep,
typeof(GetBufferSubData)
);
}
else
{
glGetBufferSubData = GetBufferSubDataESError;
}
}
else
{
try
{
glPolygonMode = (PolygonMode) GetProcAddress(
"glPolygonMode",
typeof(PolygonMode)
);
glGetTexImage = (GetTexImage) GetProcAddress(
"glGetTexImage",
typeof(GetTexImage)
);
glTexEnvi = (TexEnvi) GetProcAddress(
"glTexEnvi",
typeof(TexEnvi)
);
glGetBufferSubData = (GetBufferSubData) GetProcAddress(
"glGetBufferSubData",
typeof(GetBufferSubData)
);
}
catch(Exception e)
{
throw new NoSuitableGraphicsDeviceException(
baseErrorString +
"\nEntry Point: " + e.Message +
"\n" + driver
);
}
}
/* We need _some_ form of depth range, ES... */
IntPtr drPtr = SDL.SDL_GL_GetProcAddress("glDepthRange");
if (drPtr != IntPtr.Zero)
{
glDepthRange = (DepthRange) Marshal.GetDelegateForFunctionPointer(
drPtr,
typeof(DepthRange)
);
}
else
{
try
{
glDepthRangef = (DepthRangef) GetProcAddress(
"glDepthRangef",
typeof(DepthRangef)
);
}
catch(Exception e)
{
throw new NoSuitableGraphicsDeviceException(
baseErrorString +
"\nEntry Point: " + e.Message +
"\n" + driver
);
}
glDepthRange = DepthRangeFloat;
}
drPtr = SDL.SDL_GL_GetProcAddress("glClearDepth");
if (drPtr != IntPtr.Zero)
{
glClearDepth = (ClearDepth) Marshal.GetDelegateForFunctionPointer(
drPtr,
typeof(ClearDepth)
);
}
else
{
try
{
glClearDepthf = (ClearDepthf) GetProcAddress(
"glClearDepthf",
typeof(ClearDepthf)
);
}
catch (Exception e)
{
throw new NoSuitableGraphicsDeviceException(
baseErrorString +
"\nEntry Point: " + e.Message +
"\n" + driver
);
}
glClearDepth = ClearDepthFloat;
}
/* Silently fail if using GLES. You didn't need these, right...? >_> */
try
{
glTexImage3D = (TexImage3D) GetProcAddressEXT(
"glTexImage3D",
typeof(TexImage3D),
"OES"
);
glTexSubImage3D = (TexSubImage3D) GetProcAddressEXT(
"glTexSubImage3D",
typeof(TexSubImage3D),
"OES"
);
glGenQueries = (GenQueries) GetProcAddress(
"glGenQueries",
typeof(GenQueries)
);
glDeleteQueries = (DeleteQueries) GetProcAddress(
"glDeleteQueries",
typeof(DeleteQueries)
);
glBeginQuery = (BeginQuery) GetProcAddress(
"glBeginQuery",
typeof(BeginQuery)
);
glEndQuery = (EndQuery) GetProcAddress(
"glEndQuery",
typeof(EndQuery)
);
glGetQueryObjectuiv = (GetQueryObjectuiv) GetProcAddress(
"glGetQueryObjectuiv",
typeof(GetQueryObjectuiv)
);
}
catch
{
if (useES3)
{
FNALoggerEXT.LogWarn("Some non-ES functions failed to load. Beware...");
}
else
{
throw new NoSuitableGraphicsDeviceException(
baseErrorString +
"\nFailed on Tex3D/Query entries\n" +
driver
);
}
}
/* ARB_framebuffer_object. We're flexible, but not _that_ flexible. */
try
{
glGenFramebuffers = (GenFramebuffers) GetProcAddressEXT(
"glGenFramebuffers",
typeof(GenFramebuffers)
);
glDeleteFramebuffers = (DeleteFramebuffers) GetProcAddressEXT(
"glDeleteFramebuffers",
typeof(DeleteFramebuffers)
);
glBindFramebuffer = (G_BindFramebuffer) GetProcAddressEXT(
"glBindFramebuffer",
typeof(G_BindFramebuffer)
);
glFramebufferTexture2D = (FramebufferTexture2D) GetProcAddressEXT(
"glFramebufferTexture2D",
typeof(FramebufferTexture2D)
);
glFramebufferRenderbuffer = (FramebufferRenderbuffer) GetProcAddressEXT(
"glFramebufferRenderbuffer",
typeof(FramebufferRenderbuffer)
);
glGenerateMipmap = (GenerateMipmap) GetProcAddressEXT(
"glGenerateMipmap",
typeof(GenerateMipmap)
);
glGenRenderbuffers = (GenRenderbuffers) GetProcAddressEXT(
"glGenRenderbuffers",
typeof(GenRenderbuffers)
);
glDeleteRenderbuffers = (DeleteRenderbuffers) GetProcAddressEXT(
"glDeleteRenderbuffers",
typeof(DeleteRenderbuffers)
);
glBindRenderbuffer = (BindRenderbuffer) GetProcAddressEXT(
"glBindRenderbuffer",
typeof(BindRenderbuffer)
);
glRenderbufferStorage = (RenderbufferStorage) GetProcAddressEXT(
"glRenderbufferStorage",
typeof(RenderbufferStorage)
);
}
catch
{
throw new NoSuitableGraphicsDeviceException("OpenGL framebuffer support is required!");
}
/* EXT_framebuffer_blit (or ARB_framebuffer_object) is needed by the faux-backbuffer. */
supportsFauxBackbuffer = true;
try
{
glBlitFramebuffer = (BlitFramebuffer) GetProcAddressEXT(
"glBlitFramebuffer",
typeof(BlitFramebuffer)
);
}
catch
{
supportsFauxBackbuffer = false;
}
/* EXT_framebuffer_multisample (or ARB_framebuffer_object) is glitter */
supportsMultisampling = true;
try
{
glRenderbufferStorageMultisample = (RenderbufferStorageMultisample) GetProcAddressEXT(
"glRenderbufferStorageMultisample",
typeof(RenderbufferStorageMultisample)
);
}
catch
{
supportsMultisampling = false;
}
/* ARB_instanced_arrays/ARB_draw_instanced are almost optional. */
SupportsHardwareInstancing = true;
try
{
glVertexAttribDivisor = (VertexAttribDivisor) GetProcAddress(
"glVertexAttribDivisor",
typeof(VertexAttribDivisor)
);
/* The likelihood of someone having BaseVertex but not Instanced is 0...? */
if (supportsBaseVertex)
{
glDrawElementsInstancedBaseVertex = (DrawElementsInstancedBaseVertex) Marshal.GetDelegateForFunctionPointer(
SDL.SDL_GL_GetProcAddress("glDrawElementsInstancedBaseVertex"),
typeof(DrawElementsInstancedBaseVertex)
);
}
else
{
glDrawElementsInstanced = (DrawElementsInstanced) Marshal.GetDelegateForFunctionPointer(
SDL.SDL_GL_GetProcAddress("glDrawElementsInstanced"),
typeof(DrawElementsInstanced)
);
glDrawElementsInstancedBaseVertex = DrawElementsInstancedNoBase;
}
}
catch
{
SupportsHardwareInstancing = false;
}
/* ARB_invalidate_subdata makes target swaps faster on mobile targets */
supportsFBOInvalidation = useES3; // FIXME: Does desktop benefit from this?
try
{
IntPtr ifbo = SDL.SDL_GL_GetProcAddress("glInvalidateFramebuffer");
if (ifbo == IntPtr.Zero && useES3)
{
/* ES2 has EXT_discard_framebuffer as a fallback */
ifbo = SDL.SDL_GL_GetProcAddress("glDiscardFramebufferEXT");
}
glInvalidateFramebuffer = (InvalidateFramebuffer) Marshal.GetDelegateForFunctionPointer(
ifbo,
typeof(InvalidateFramebuffer)
);
}
catch
{
supportsFBOInvalidation = false;
}
/* Indexed color mask is a weird thing.
* IndexedEXT was introduced in EXT_draw_buffers2, then
* it was introduced in GL 3.0 as "ColorMaski" with no
* extension at all, and OpenGL ES introduced it as
* ColorMaskiEXT via EXT_draw_buffers_indexed and AGAIN
* as ColorMaskiOES via OES_draw_buffers_indexed at the
* exact same time. WTF.
* -flibit
*/
IntPtr cm = SDL.SDL_GL_GetProcAddress("glColorMaski");
if (cm == IntPtr.Zero)
{
cm = SDL.SDL_GL_GetProcAddress("glColorMaskIndexedEXT");
}
if (cm == IntPtr.Zero)
{
cm = SDL.SDL_GL_GetProcAddress("glColorMaskiOES");
}
if (cm == IntPtr.Zero)
{
cm = SDL.SDL_GL_GetProcAddress("glColorMaskiEXT");
}
try
{
glColorMaski = (ColorMaski) Marshal.GetDelegateForFunctionPointer(
cm,
typeof(ColorMaski)
);
}
catch
{
// FIXME: SupportsIndependentWriteMasks? -flibit
}
/* ARB_texture_multisample is probably used by nobody. */
try
{
glSampleMaski = (SampleMaski) GetProcAddress(
"glSampleMaski",
typeof(SampleMaski)
);
}
catch
{
// FIXME: SupportsMultisampleMasks? -flibit
}
if (useCoreProfile)
{
try
{
INTERNAL_glGetStringi = (GetStringi) GetProcAddress(
"glGetStringi",
typeof(GetStringi)
);
glGenVertexArrays = (GenVertexArrays) GetProcAddress(
"glGenVertexArrays",
typeof(GenVertexArrays)
);
glDeleteVertexArrays = (DeleteVertexArrays) GetProcAddress(
"glDeleteVertexArrays",
typeof(DeleteVertexArrays)
);
glBindVertexArray = (BindVertexArray) GetProcAddress(
"glBindVertexArray",
typeof(BindVertexArray)
);
}
catch
{
throw new NoSuitableGraphicsDeviceException("OpenGL 3.2 support is required!");
}
}
#if DEBUG
/* ARB_debug_output/KHR_debug, for debug contexts */
bool supportsDebug = true;
IntPtr messageCallback;
IntPtr messageControl;
/* Try KHR_debug first...
*
* "NOTE: when implemented in an OpenGL ES context, all entry points defined
* by this extension must have a "KHR" suffix. When implemented in an
* OpenGL context, all entry points must have NO suffix, as shown below."
* https://www.khronos.org/registry/OpenGL/extensions/KHR/KHR_debug.txt
*/
if (useES3)
{
messageCallback = SDL.SDL_GL_GetProcAddress("glDebugMessageCallbackKHR");
messageControl = SDL.SDL_GL_GetProcAddress("glDebugMessageControlKHR");
}
else
{
messageCallback = SDL.SDL_GL_GetProcAddress("glDebugMessageCallback");
messageControl = SDL.SDL_GL_GetProcAddress("glDebugMessageControl");
}
if (messageCallback == IntPtr.Zero || messageControl == IntPtr.Zero)
{
/* ... then try ARB_debug_output. */
messageCallback = SDL.SDL_GL_GetProcAddress("glDebugMessageCallbackARB");
messageControl = SDL.SDL_GL_GetProcAddress("glDebugMessageControlARB");
}
if (messageCallback == IntPtr.Zero || messageControl == IntPtr.Zero)
{
supportsDebug = false;
}
/* Android developers are incredibly stupid and export stub functions */
if (useES3)
{
if ( SDL.SDL_GL_ExtensionSupported("GL_KHR_debug") == SDL.SDL_bool.SDL_FALSE &&
SDL.SDL_GL_ExtensionSupported("GL_ARB_debug_output") == SDL.SDL_bool.SDL_FALSE )
{
supportsDebug = false;
}
}
/* Set the callback, finally. */
if (!supportsDebug)
{
FNALoggerEXT.LogWarn("ARB_debug_output/KHR_debug not supported!");
}
else
{
glDebugMessageCallback = (DebugMessageCallback) Marshal.GetDelegateForFunctionPointer(
messageCallback,
typeof(DebugMessageCallback)
);
glDebugMessageControl = (DebugMessageControl) Marshal.GetDelegateForFunctionPointer(
messageControl,
typeof(DebugMessageControl)
);
glDebugMessageControl(
GLenum.GL_DONT_CARE,
GLenum.GL_DONT_CARE,
GLenum.GL_DONT_CARE,
0,
IntPtr.Zero,
true
);
glDebugMessageControl(
GLenum.GL_DONT_CARE,
GLenum.GL_DEBUG_TYPE_OTHER,
GLenum.GL_DEBUG_SEVERITY_LOW,
0,
IntPtr.Zero,
false
);
glDebugMessageControl(
GLenum.GL_DONT_CARE,
GLenum.GL_DEBUG_TYPE_OTHER,
GLenum.GL_DEBUG_SEVERITY_NOTIFICATION,
0,
IntPtr.Zero,
false
);
glDebugMessageCallback(Marshal.GetFunctionPointerForDelegate(DebugCall), IntPtr.Zero);
}
/* GREMEDY_string_marker, for apitrace */
IntPtr stringMarkerCallback = SDL.SDL_GL_GetProcAddress("glStringMarkerGREMEDY");
if (stringMarkerCallback == IntPtr.Zero)
{
FNALoggerEXT.LogWarn("GREMEDY_string_marker not supported!");
}
else
{
glStringMarkerGREMEDY = (StringMarkerGREMEDY) Marshal.GetDelegateForFunctionPointer(
stringMarkerCallback,
typeof(StringMarkerGREMEDY)
);
}
#endif
}
private Delegate GetProcAddress(string name, Type type)
{
IntPtr addr = SDL.SDL_GL_GetProcAddress(name);
if (addr == IntPtr.Zero)
{
throw new Exception(name);
}
return Marshal.GetDelegateForFunctionPointer(addr, type);
}
private Delegate GetProcAddressEXT(string name, Type type, string ext = "EXT")
{
IntPtr addr = SDL.SDL_GL_GetProcAddress(name);
if (addr == IntPtr.Zero)
{
addr = SDL.SDL_GL_GetProcAddress(name + ext);
}
if (addr == IntPtr.Zero)
{
throw new Exception(name);
}
return Marshal.GetDelegateForFunctionPointer(addr, type);
}
private void DrawRangeElementsNoBase(
GLenum mode,
int start,
int end,
int count,
GLenum type,
IntPtr indices,
int baseVertex
) {
glDrawRangeElements(
mode,
start,
end,
count,
type,
indices
);
}
private void DrawRangeElementsNoBaseUnchecked(
GLenum mode,
int start,
int end,
int count,
GLenum type,
IntPtr indices,
int baseVertex
) {
glDrawElements(
mode,
count,
type,
indices
);
}
private void DrawRangeElementsUnchecked(
GLenum mode,
int start,
int end,
int count,
GLenum type,
IntPtr indices
) {
glDrawElements(
mode,
count,
type,
indices
);
}
private void DrawElementsInstancedNoBase(
GLenum mode,
int count,
GLenum type,
IntPtr indices,
int instanceCount,
int baseVertex
) {
glDrawElementsInstanced(
mode,
count,
type,
indices,
instanceCount
);
}
private void DepthRangeFloat(double near, double far)
{
glDepthRangef((float) near, (float) far);
}
private void ClearDepthFloat(double depth)
{
glClearDepthf((float) depth);
}
private void PolygonModeESError(GLenum face, GLenum mode)
{
throw new NotSupportedException("glPolygonMode is not available in ES!");
}
private void GetTexImageESError(
GLenum target,
int level,
GLenum format,
GLenum type,
IntPtr pixels
) {
throw new NotSupportedException("glGetTexImage is not available in ES!");
}
private void GetBufferSubDataESError(
GLenum target,
IntPtr offset,
IntPtr size,
IntPtr data
) {
throw new NotSupportedException("glGetBufferSubData is not available in ES!");
}
#endregion
}
}