Show More
Commit Description:
Various UI improvements.
Commit Description:
Various UI improvements.
References:
File last commit:
Show/Diff file:
Action:
FNA/src/FNAPlatform/OpenGLDevice_GL.cs
1862 lines | 46.8 KiB | text/x-csharp | CSharpLexer
1862 lines | 46.8 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 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 | ||||
} | ||||
} | ||||