#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 } }