Show More
Commit Description:
Various UI improvements.
Commit Description:
Various UI improvements.
File last commit:
Show/Diff file:
Action:
FNA/src/FNAPlatform/OpenGLDevice_GL.cs
1862 lines | 46.8 KiB | text/x-csharp | CSharpLexer
#region License
/* FNA - XNA4 Reimplementation for Desktop Platforms
* Copyright 2009-2020 Ethan Lee and the MonoGame Team
*
* Released under the Microsoft Public License.
* See LICENSE for details.
*/
#endregion
#region Using Statements
using System;
using System.Runtime.InteropServices;
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
}
}