diff --git a/Avalonia.sln b/Avalonia.sln index 76d8a145244..f71a94888d5 100644 --- a/Avalonia.sln +++ b/Avalonia.sln @@ -186,6 +186,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Designer.HostApp.N EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Avalonia.Skia.UnitTests", "tests\Avalonia.Skia.UnitTests\Avalonia.Skia.UnitTests.csproj", "{E1240B49-7B4B-4371-A00E-068778C5CF0B}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Avalonia.OpenGL", "src\Avalonia.OpenGL\Avalonia.OpenGL.csproj", "{7CCAEFC4-135D-401D-BDDD-896B9B7D3569}" +EndProject Global GlobalSection(SharedMSBuildProjectFiles) = preSolution src\Shared\RenderHelpers\RenderHelpers.projitems*{3c4c0cb4-0c0f-4450-a37b-148c84ff905f}*SharedItemsImports = 13 @@ -1663,6 +1665,30 @@ Global {E1240B49-7B4B-4371-A00E-068778C5CF0B}.Release|iPhone.Build.0 = Release|Any CPU {E1240B49-7B4B-4371-A00E-068778C5CF0B}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU {E1240B49-7B4B-4371-A00E-068778C5CF0B}.Release|iPhoneSimulator.Build.0 = Release|Any CPU + {7CCAEFC4-135D-401D-BDDD-896B9B7D3569}.Ad-Hoc|Any CPU.ActiveCfg = Debug|Any CPU + {7CCAEFC4-135D-401D-BDDD-896B9B7D3569}.Ad-Hoc|Any CPU.Build.0 = Debug|Any CPU + {7CCAEFC4-135D-401D-BDDD-896B9B7D3569}.Ad-Hoc|iPhone.ActiveCfg = Debug|Any CPU + {7CCAEFC4-135D-401D-BDDD-896B9B7D3569}.Ad-Hoc|iPhone.Build.0 = Debug|Any CPU + {7CCAEFC4-135D-401D-BDDD-896B9B7D3569}.Ad-Hoc|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {7CCAEFC4-135D-401D-BDDD-896B9B7D3569}.Ad-Hoc|iPhoneSimulator.Build.0 = Debug|Any CPU + {7CCAEFC4-135D-401D-BDDD-896B9B7D3569}.AppStore|Any CPU.ActiveCfg = Debug|Any CPU + {7CCAEFC4-135D-401D-BDDD-896B9B7D3569}.AppStore|Any CPU.Build.0 = Debug|Any CPU + {7CCAEFC4-135D-401D-BDDD-896B9B7D3569}.AppStore|iPhone.ActiveCfg = Debug|Any CPU + {7CCAEFC4-135D-401D-BDDD-896B9B7D3569}.AppStore|iPhone.Build.0 = Debug|Any CPU + {7CCAEFC4-135D-401D-BDDD-896B9B7D3569}.AppStore|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {7CCAEFC4-135D-401D-BDDD-896B9B7D3569}.AppStore|iPhoneSimulator.Build.0 = Debug|Any CPU + {7CCAEFC4-135D-401D-BDDD-896B9B7D3569}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7CCAEFC4-135D-401D-BDDD-896B9B7D3569}.Debug|Any CPU.Build.0 = Debug|Any CPU + {7CCAEFC4-135D-401D-BDDD-896B9B7D3569}.Debug|iPhone.ActiveCfg = Debug|Any CPU + {7CCAEFC4-135D-401D-BDDD-896B9B7D3569}.Debug|iPhone.Build.0 = Debug|Any CPU + {7CCAEFC4-135D-401D-BDDD-896B9B7D3569}.Debug|iPhoneSimulator.ActiveCfg = Debug|Any CPU + {7CCAEFC4-135D-401D-BDDD-896B9B7D3569}.Debug|iPhoneSimulator.Build.0 = Debug|Any CPU + {7CCAEFC4-135D-401D-BDDD-896B9B7D3569}.Release|Any CPU.ActiveCfg = Release|Any CPU + {7CCAEFC4-135D-401D-BDDD-896B9B7D3569}.Release|Any CPU.Build.0 = Release|Any CPU + {7CCAEFC4-135D-401D-BDDD-896B9B7D3569}.Release|iPhone.ActiveCfg = Release|Any CPU + {7CCAEFC4-135D-401D-BDDD-896B9B7D3569}.Release|iPhone.Build.0 = Release|Any CPU + {7CCAEFC4-135D-401D-BDDD-896B9B7D3569}.Release|iPhoneSimulator.ActiveCfg = Release|Any CPU + {7CCAEFC4-135D-401D-BDDD-896B9B7D3569}.Release|iPhoneSimulator.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/packages.cake b/packages.cake index 9defa3004cd..fea45153f19 100644 --- a/packages.cake +++ b/packages.cake @@ -167,6 +167,7 @@ public class Packages new [] { "./src/", "Avalonia.Logging.Serilog"}, new [] { "./src/", "Avalonia.Visuals"}, new [] { "./src/", "Avalonia.Styling"}, + new [] { "./src/", "Avalonia.OpenGL"}, new [] { "./src/", "Avalonia.Themes.Default"}, new [] { "./src/Markup/", "Avalonia.Markup"}, new [] { "./src/Markup/", "Avalonia.Markup.Xaml"}, diff --git a/src/Avalonia.Base/Avalonia.Base.csproj b/src/Avalonia.Base/Avalonia.Base.csproj index bc068857ff1..3d13169aa81 100644 --- a/src/Avalonia.Base/Avalonia.Base.csproj +++ b/src/Avalonia.Base/Avalonia.Base.csproj @@ -3,6 +3,7 @@ netstandard2.0 Avalonia.Base Avalonia + True diff --git a/src/Avalonia.Base/Platform/Interop/IDynamicLibraryLoader.cs b/src/Avalonia.Base/Platform/Interop/IDynamicLibraryLoader.cs new file mode 100644 index 00000000000..8124ce6bc4c --- /dev/null +++ b/src/Avalonia.Base/Platform/Interop/IDynamicLibraryLoader.cs @@ -0,0 +1,18 @@ +using System; + +namespace Avalonia.Platform.Interop +{ + public interface IDynamicLibraryLoader + { + IntPtr LoadLibrary(string dll); + IntPtr GetProcAddress(IntPtr dll, string proc, bool optional); + } + + public class DynamicLibraryLoaderException : Exception + { + public DynamicLibraryLoaderException(string message) : base(message) + { + + } + } +} diff --git a/src/Gtk/Avalonia.Gtk3/Interop/Utf8Buffer.cs b/src/Avalonia.Base/Platform/Interop/Utf8Buffer.cs similarity index 94% rename from src/Gtk/Avalonia.Gtk3/Interop/Utf8Buffer.cs rename to src/Avalonia.Base/Platform/Interop/Utf8Buffer.cs index c932aac9503..dc7a3e5634d 100644 --- a/src/Gtk/Avalonia.Gtk3/Interop/Utf8Buffer.cs +++ b/src/Avalonia.Base/Platform/Interop/Utf8Buffer.cs @@ -2,9 +2,9 @@ using System.Runtime.InteropServices; using System.Text; -namespace Avalonia.Gtk3.Interop +namespace Avalonia.Platform.Interop { - class Utf8Buffer : SafeHandle + public class Utf8Buffer : SafeHandle { private GCHandle _gchandle; private byte[] _data; diff --git a/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj b/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj new file mode 100644 index 00000000000..310d0c8dba2 --- /dev/null +++ b/src/Avalonia.OpenGL/Avalonia.OpenGL.csproj @@ -0,0 +1,12 @@ + + + + netstandard2.0 + + + + + + + + diff --git a/src/Avalonia.OpenGL/EglConsts.cs b/src/Avalonia.OpenGL/EglConsts.cs new file mode 100644 index 00000000000..62fb3faef67 --- /dev/null +++ b/src/Avalonia.OpenGL/EglConsts.cs @@ -0,0 +1,196 @@ +// ReSharper disable UnusedMember.Global +// ReSharper disable IdentifierTypo +namespace Avalonia.OpenGL +{ + public static class EglConsts + { + public const int EGL_ALPHA_SIZE = 0x3021; + public const int EGL_BAD_ACCESS = 0x3002; + public const int EGL_BAD_ALLOC = 0x3003; + public const int EGL_BAD_ATTRIBUTE = 0x3004; + public const int EGL_BAD_CONFIG = 0x3005; + public const int EGL_BAD_CONTEXT = 0x3006; + public const int EGL_BAD_CURRENT_SURFACE = 0x3007; + public const int EGL_BAD_DISPLAY = 0x3008; + public const int EGL_BAD_MATCH = 0x3009; + public const int EGL_BAD_NATIVE_PIXMAP = 0x300A; + public const int EGL_BAD_NATIVE_WINDOW = 0x300B; + public const int EGL_BAD_PARAMETER = 0x300C; + public const int EGL_BAD_SURFACE = 0x300D; + public const int EGL_BLUE_SIZE = 0x3022; + public const int EGL_BUFFER_SIZE = 0x3020; + public const int EGL_CONFIG_CAVEAT = 0x3027; + public const int EGL_CONFIG_ID = 0x3028; + public const int EGL_CORE_NATIVE_ENGINE = 0x305B; + public const int EGL_DEPTH_SIZE = 0x3025; + public const int EGL_DONT_CARE = -1; + public const int EGL_DRAW = 0x3059; + public const int EGL_EXTENSIONS = 0x3055; + public const int EGL_FALSE = 0; + public const int EGL_GREEN_SIZE = 0x3023; + public const int EGL_HEIGHT = 0x3056; + public const int EGL_LARGEST_PBUFFER = 0x3058; + public const int EGL_LEVEL = 0x3029; + public const int EGL_MAX_PBUFFER_HEIGHT = 0x302A; + public const int EGL_MAX_PBUFFER_PIXELS = 0x302B; + public const int EGL_MAX_PBUFFER_WIDTH = 0x302C; + public const int EGL_NATIVE_RENDERABLE = 0x302D; + public const int EGL_NATIVE_VISUAL_ID = 0x302E; + public const int EGL_NATIVE_VISUAL_TYPE = 0x302F; + public const int EGL_NONE = 0x3038; + public const int EGL_NON_CONFORMANT_CONFIG = 0x3051; + public const int EGL_NOT_INITIALIZED = 0x3001; + public const int EGL_NO_CONTEXT = 0; + public const int EGL_NO_DISPLAY = 0; + public const int EGL_NO_SURFACE = 0; + public const int EGL_PBUFFER_BIT = 0x0001; + public const int EGL_PIXMAP_BIT = 0x0002; + public const int EGL_READ = 0x305A; + public const int EGL_RED_SIZE = 0x3024; + public const int EGL_SAMPLES = 0x3031; + public const int EGL_SAMPLE_BUFFERS = 0x3032; + public const int EGL_SLOW_CONFIG = 0x3050; + public const int EGL_STENCIL_SIZE = 0x3026; + public const int EGL_SUCCESS = 0x3000; + public const int EGL_SURFACE_TYPE = 0x3033; + public const int EGL_TRANSPARENT_BLUE_VALUE = 0x3035; + public const int EGL_TRANSPARENT_GREEN_VALUE = 0x3036; + public const int EGL_TRANSPARENT_RED_VALUE = 0x3037; + public const int EGL_TRANSPARENT_RGB = 0x3052; + public const int EGL_TRANSPARENT_TYPE = 0x3034; + public const int EGL_TRUE = 1; + public const int EGL_VENDOR = 0x3053; + public const int EGL_VERSION = 0x3054; + public const int EGL_WIDTH = 0x3057; + public const int EGL_WINDOW_BIT = 0x0004; + + public const int EGL_BACK_BUFFER = 0x3084; + public const int EGL_BIND_TO_TEXTURE_RGB = 0x3039; + public const int EGL_BIND_TO_TEXTURE_RGBA = 0x303A; + public const int EGL_CONTEXT_LOST = 0x300E; + public const int EGL_MIN_SWAP_INTERVAL = 0x303B; + public const int EGL_MAX_SWAP_INTERVAL = 0x303C; + public const int EGL_MIPMAP_TEXTURE = 0x3082; + public const int EGL_MIPMAP_LEVEL = 0x3083; + public const int EGL_NO_TEXTURE = 0x305C; + public const int EGL_TEXTURE_2D = 0x305F; + public const int EGL_TEXTURE_FORMAT = 0x3080; + public const int EGL_TEXTURE_RGB = 0x305D; + public const int EGL_TEXTURE_RGBA = 0x305E; + public const int EGL_TEXTURE_TARGET = 0x3081; + + public const int EGL_ALPHA_FORMAT = 0x3088; + public const int EGL_ALPHA_FORMAT_NONPRE = 0x308B; + public const int EGL_ALPHA_FORMAT_PRE = 0x308C; + public const int EGL_ALPHA_MASK_SIZE = 0x303E; + public const int EGL_BUFFER_PRESERVED = 0x3094; + public const int EGL_BUFFER_DESTROYED = 0x3095; + public const int EGL_CLIENT_APIS = 0x308D; + public const int EGL_COLORSPACE = 0x3087; + public const int EGL_COLORSPACE_sRGB = 0x3089; + public const int EGL_COLORSPACE_LINEAR = 0x308A; + public const int EGL_COLOR_BUFFER_TYPE = 0x303F; + public const int EGL_CONTEXT_CLIENT_TYPE = 0x3097; + public const int EGL_DISPLAY_SCALING = 10000; + public const int EGL_HORIZONTAL_RESOLUTION = 0x3090; + public const int EGL_LUMINANCE_BUFFER = 0x308F; + public const int EGL_LUMINANCE_SIZE = 0x303D; + public const int EGL_OPENGL_ES_BIT = 0x0001; + public const int EGL_OPENVG_BIT = 0x0002; + public const int EGL_OPENGL_ES_API = 0x30A0; + public const int EGL_OPENVG_API = 0x30A1; + public const int EGL_OPENVG_IMAGE = 0x3096; + public const int EGL_PIXEL_ASPECT_RATIO = 0x3092; + public const int EGL_RENDERABLE_TYPE = 0x3040; + public const int EGL_RENDER_BUFFER = 0x3086; + public const int EGL_RGB_BUFFER = 0x308E; + public const int EGL_SINGLE_BUFFER = 0x3085; + public const int EGL_SWAP_BEHAVIOR = 0x3093; + public const int EGL_UNKNOWN = -1; + public const int EGL_VERTICAL_RESOLUTION = 0x3091; + public const int EGL_CONFORMANT = 0x3042; + public const int EGL_CONTEXT_CLIENT_VERSION = 0x3098; + public const int EGL_MATCH_NATIVE_PIXMAP = 0x3041; + public const int EGL_OPENGL_ES2_BIT = 0x0004; + public const int EGL_VG_ALPHA_FORMAT = 0x3088; + public const int EGL_VG_ALPHA_FORMAT_NONPRE = 0x308B; + public const int EGL_VG_ALPHA_FORMAT_PRE = 0x308C; + public const int EGL_VG_ALPHA_FORMAT_PRE_BIT = 0x0040; + public const int EGL_VG_COLORSPACE = 0x3087; + public const int EGL_VG_COLORSPACE_sRGB = 0x3089; + public const int EGL_VG_COLORSPACE_LINEAR = 0x308A; + public const int EGL_VG_COLORSPACE_LINEAR_BIT = 0x0020; + public const int EGL_DEFAULT_DISPLAY = 0; + public const int EGL_MULTISAMPLE_RESOLVE_BOX_BIT = 0x0200; + public const int EGL_MULTISAMPLE_RESOLVE = 0x3099; + public const int EGL_MULTISAMPLE_RESOLVE_DEFAULT = 0x309A; + public const int EGL_MULTISAMPLE_RESOLVE_BOX = 0x309B; + public const int EGL_OPENGL_API = 0x30A2; + public const int EGL_OPENGL_BIT = 0x0008; + public const int EGL_SWAP_BEHAVIOR_PRESERVED_BIT = 0x0400; + public const int EGL_CONTEXT_MAJOR_VERSION = 0x3098; + public const int EGL_CONTEXT_MINOR_VERSION = 0x30FB; + public const int EGL_CONTEXT_OPENGL_PROFILE_MASK = 0x30FD; + public const int EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY = 0x31BD; + public const int EGL_NO_RESET_NOTIFICATION = 0x31BE; + public const int EGL_LOSE_CONTEXT_ON_RESET = 0x31BF; + public const int EGL_CONTEXT_OPENGL_CORE_PROFILE_BIT = 0x00000001; + public const int EGL_CONTEXT_OPENGL_COMPATIBILITY_PROFILE_BIT = 0x00000002; + public const int EGL_CONTEXT_OPENGL_DEBUG = 0x31B0; + public const int EGL_CONTEXT_OPENGL_FORWARD_COMPATIBLE = 0x31B1; + public const int EGL_CONTEXT_OPENGL_ROBUST_ACCESS = 0x31B2; + public const int EGL_OPENGL_ES3_BIT = 0x00000040; + public const int EGL_CL_EVENT_HANDLE = 0x309C; + public const int EGL_SYNC_CL_EVENT = 0x30FE; + public const int EGL_SYNC_CL_EVENT_COMPLETE = 0x30FF; + public const int EGL_SYNC_PRIOR_COMMANDS_COMPLETE = 0x30F0; + public const int EGL_SYNC_TYPE = 0x30F7; + public const int EGL_SYNC_STATUS = 0x30F1; + public const int EGL_SYNC_CONDITION = 0x30F8; + public const int EGL_SIGNALED = 0x30F2; + public const int EGL_UNSIGNALED = 0x30F3; + + public const int EGL_SYNC_FLUSH_COMMANDS_BIT = 0x0001; + + public const int EGL_TIMEOUT_EXPIRED = 0x30F5; + public const int EGL_CONDITION_SATISFIED = 0x30F6; + public const int EGL_NO_SYNC = 0; + public const int EGL_SYNC_FENCE = 0x30F9; + public const int EGL_GL_COLORSPACE = 0x309D; + public const int EGL_GL_COLORSPACE_SRGB = 0x3089; + public const int EGL_GL_COLORSPACE_LINEAR = 0x308A; + public const int EGL_GL_RENDERBUFFER = 0x30B9; + public const int EGL_GL_TEXTURE_2D = 0x30B1; + public const int EGL_GL_TEXTURE_LEVEL = 0x30BC; + public const int EGL_GL_TEXTURE_3D = 0x30B2; + public const int EGL_GL_TEXTURE_ZOFFSET = 0x30BD; + public const int EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_X = 0x30B3; + public const int EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_X = 0x30B4; + public const int EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Y = 0x30B5; + public const int EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x30B6; + public const int EGL_GL_TEXTURE_CUBE_MAP_POSITIVE_Z = 0x30B7; + public const int EGL_GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x30B8; + public const int EGL_IMAGE_PRESERVED = 0x30D2; + public const int EGL_NO_IMAGE = 0; + + + public const int EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE = 0x3207; + public const int EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE = 0x3208; + + //EGL_ANGLE_platform_angle + public const int EGL_PLATFORM_ANGLE_ANGLE = 0x3202; + public const int EGL_PLATFORM_ANGLE_TYPE_ANGLE = 0x3203; + public const int EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE = 0x3204; + public const int EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE = 0x3205; + public const int EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED = 0x3451; + public const int EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE = 0x3206; + public const int EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE = 0x320A; + public const int EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE = 0x345E; + + //EGL_ANGLE_platform_angle_d3d + public const int EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE = 0x3209; + public const int EGL_PLATFORM_ANGLE_ENABLE_AUTOMATIC_TRIM_ANGLE = 0x320F; + public const int EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_WARP_ANGLE = 0x320B; + public const int EGL_PLATFORM_ANGLE_DEVICE_TYPE_D3D_REFERENCE_ANGLE = 0x320C; + } +} diff --git a/src/Avalonia.OpenGL/EglDisplay.cs b/src/Avalonia.OpenGL/EglDisplay.cs new file mode 100644 index 00000000000..ea0a9bf0875 --- /dev/null +++ b/src/Avalonia.OpenGL/EglDisplay.cs @@ -0,0 +1,205 @@ +using System; +using System.ComponentModel; +using System.Runtime.InteropServices; +using Avalonia.Platform.Interop; +using static Avalonia.OpenGL.EglConsts; + +namespace Avalonia.OpenGL +{ + public class EglDisplay : IGlDisplay + { + private readonly EglInterface _egl; + private readonly IntPtr _display; + private readonly IntPtr _config; + private readonly int[] _contextAttributes; + + public EglDisplay(EglInterface egl) + { + _egl = egl; + + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows) && _egl.GetPlatformDisplayEXT != null) + { + foreach (var dapi in new[] {EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE, EGL_PLATFORM_ANGLE_TYPE_D3D9_ANGLE}) + { + _display = _egl.GetPlatformDisplayEXT(EGL_PLATFORM_ANGLE_ANGLE, IntPtr.Zero, new[] + { + EGL_PLATFORM_ANGLE_TYPE_ANGLE, dapi, EGL_NONE + }); + if(_display != IntPtr.Zero) + break; + } + } + + if (_display == IntPtr.Zero) + _display = _egl.GetDisplay(IntPtr.Zero); + + if(_display == IntPtr.Zero) + throw new OpenGlException("eglGetDisplay failed"); + + if (!_egl.Initialize(_display, out var major, out var minor)) + throw new OpenGlException("eglInitialize failed"); + + foreach (var cfg in new[] + { + new + { + Attributes = new[] {EGL_NONE}, + Api = EGL_OPENGL_API, + RenderableTypeBit = EGL_OPENGL_BIT, + Type = GlDisplayType.OpenGL2 + }, + new + { + Attributes = new[] + { + EGL_CONTEXT_CLIENT_VERSION, 2, + EGL_NONE + }, + Api = EGL_OPENGL_ES_API, + RenderableTypeBit = EGL_OPENGL_ES2_BIT, + Type = GlDisplayType.OpenGLES2 + } + }) + { + if (!_egl.BindApi(cfg.Api)) + continue; + + var attribs = new[] + { + EGL_SURFACE_TYPE, EGL_PBUFFER_BIT, + EGL_RENDERABLE_TYPE, cfg.RenderableTypeBit, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 8, + EGL_STENCIL_SIZE, 8, + EGL_DEPTH_SIZE, 8, + EGL_NONE + }; + if (!_egl.ChooseConfig(_display, attribs, out _config, 1, out int numConfigs)) + continue; + if (numConfigs == 0) + continue; + _contextAttributes = cfg.Attributes; + Type = cfg.Type; + } + + if (_contextAttributes == null) + throw new OpenGlException("No suitable EGL config was found"); + + GlInterface = new GlInterface((proc, optional) => + { + + using (var u = new Utf8Buffer(proc)) + { + var rv = _egl.GetProcAddress(u); + if (rv == IntPtr.Zero && !optional) + throw new OpenGlException("Missing function " + proc); + return rv; + } + }); + } + + public EglDisplay() : this(new EglInterface()) + { + + } + + public GlDisplayType Type { get; } + public GlInterface GlInterface { get; } + public IGlContext CreateContext(IGlContext share) + { + var shareCtx = (EglContext)share; + var ctx = _egl.CreateContext(_display, _config, shareCtx?.Context ?? IntPtr.Zero, _contextAttributes); + if (ctx == IntPtr.Zero) + throw new OpenGlException("eglCreateContext failed"); + var surf = _egl.CreatePBufferSurface(_display, _config, new[] + { + EGL_WIDTH, 1, + EGL_HEIGHT, 1, + EGL_NONE + }); + if (surf == IntPtr.Zero) + throw new OpenGlException("eglCreatePbufferSurface failed"); + var rv = new EglContext(this, ctx, surf); + rv.MakeCurrent(null); + return rv; + } + + public void ClearContext() + { + if (!_egl.MakeCurrent(_display, IntPtr.Zero, IntPtr.Zero, IntPtr.Zero)) + throw new OpenGlException("eglMakeCurrent failed"); + } + + public IGlSurface CreateWindowSurface(IntPtr window) + { + var s = _egl.CreateWindowSurface(_display, _config, window, new[] {EGL_NONE, EGL_NONE}); + if (s == IntPtr.Zero) + throw new OpenGlException("eglCreateWindowSurface failed"); + return new EglSurface(this, s); + } + + public int SampleCount + { + get + { + _egl.GetConfigAttrib(_display, _config, EGL_SAMPLES, out var rv); + return rv; + } + } + + public int StencilSize + { + get + { + _egl.GetConfigAttrib(_display, _config, EGL_STENCIL_SIZE, out var rv); + return rv; + } + } + + class EglSurface : SafeHandle, IGlSurface + { + private readonly EglDisplay _display; + + public EglSurface(EglDisplay display, IntPtr surface) : base(surface, true) + { + _display = display; + } + + protected override bool ReleaseHandle() + { + _display._egl.DestroySurface(_display._display, handle); + return true; + } + + public override bool IsInvalid => handle == IntPtr.Zero; + + public IGlDisplay Display => _display; + public void SwapBuffers() => _display._egl.SwapBuffers(_display._display, handle); + } + + class EglContext : IGlContext + { + private readonly EglDisplay _disp; + + public EglContext(EglDisplay display, IntPtr ctx, IntPtr offscreenSurface) + { + _disp = display; + Context = ctx; + OffscreenSurface = offscreenSurface; + } + + public IntPtr Context { get; } + public IntPtr OffscreenSurface { get; } + public IGlDisplay Display => _disp; + + public void MakeCurrent(IGlSurface surface) + { + var surf = ((EglSurface)surface)?.DangerousGetHandle() ?? OffscreenSurface; + if (!_disp._egl.MakeCurrent(_disp._display, surf, surf, Context)) + throw new OpenGlException("eglMakeCurrent failed"); + } + } + } +} diff --git a/src/Avalonia.OpenGL/EglGlPlatformFeature.cs b/src/Avalonia.OpenGL/EglGlPlatformFeature.cs new file mode 100644 index 00000000000..535e32924e3 --- /dev/null +++ b/src/Avalonia.OpenGL/EglGlPlatformFeature.cs @@ -0,0 +1,39 @@ +using System; +using Avalonia.Logging; + +namespace Avalonia.OpenGL +{ + public class EglGlPlatformFeature : IWindowingPlatformGlFeature + { + public IGlDisplay Display { get; set; } + public IGlContext ImmediateContext { get; set; } + public IGlContext DeferredContext { get; set; } + + public static void TryInitialize() + { + var feature = TryCreate(); + if (feature != null) + AvaloniaLocator.CurrentMutable.Bind().ToConstant(feature); + } + + public static EglGlPlatformFeature TryCreate() + { + try + { + var disp = new EglDisplay(); + var ctx = disp.CreateContext(null); + return new EglGlPlatformFeature + { + Display = disp, + ImmediateContext = ctx, + DeferredContext = disp.CreateContext(ctx) + }; + } + catch(Exception e) + { + Logger.Error("OpenGL", null, "Unable to initialize EGL-based rendering: {0}", e); + return null; + } + } + } +} diff --git a/src/Avalonia.OpenGL/EglGlPlatformSurface.cs b/src/Avalonia.OpenGL/EglGlPlatformSurface.cs new file mode 100644 index 00000000000..19894e4ec5b --- /dev/null +++ b/src/Avalonia.OpenGL/EglGlPlatformSurface.cs @@ -0,0 +1,80 @@ +using System; + +namespace Avalonia.OpenGL +{ + public class EglGlPlatformSurface : IGlPlatformSurface + { + public interface IEglWindowGlPlatformSurfaceInfo + { + IntPtr Handle { get; } + // TODO: Change to PixelSize struct once https://github.com/AvaloniaUI/Avalonia/pull/1889 is merged + System.Drawing.Size PixelSize { get; } + double Scaling { get; } + } + + private readonly EglDisplay _display; + private readonly IGlContext _context; + private readonly IEglWindowGlPlatformSurfaceInfo _info; + + public EglGlPlatformSurface(EglDisplay display, IGlContext context, IEglWindowGlPlatformSurfaceInfo info) + { + _display = display; + _context = context; + _info = info; + } + + public IGlPlatformSurfaceRenderTarget CreateGlRenderTarget() + { + var glSurface = _display.CreateWindowSurface(_info.Handle); + return new RenderTarget(_context, glSurface, _info); + } + + class RenderTarget : IGlPlatformSurfaceRenderTarget + { + private readonly IGlContext _context; + private readonly IGlSurface _glSurface; + private readonly IEglWindowGlPlatformSurfaceInfo _info; + + public RenderTarget(IGlContext context, IGlSurface glSurface, IEglWindowGlPlatformSurfaceInfo info) + { + _context = context; + _glSurface = glSurface; + _info = info; + } + + public void Dispose() => _glSurface.Dispose(); + + public IGlPlatformSurfaceRenderingSession BeginDraw() + { + _context.MakeCurrent(_glSurface); + return new Session(_context, _glSurface, _info); + } + + class Session : IGlPlatformSurfaceRenderingSession + { + private readonly IGlContext _context; + private readonly IGlSurface _glSurface; + private readonly IEglWindowGlPlatformSurfaceInfo _info; + + public Session(IGlContext context, IGlSurface glSurface, IEglWindowGlPlatformSurfaceInfo info) + { + _context = context; + _glSurface = glSurface; + _info = info; + } + + public void Dispose() + { + _context.Display.GlInterface.Flush(); + _glSurface.SwapBuffers(); + _context.Display.ClearContext(); + } + + public IGlDisplay Display => _context.Display; + public System.Drawing.Size PixelSize => _info.PixelSize; + public double Scaling => _info.Scaling; + } + } + } +} + diff --git a/src/Avalonia.OpenGL/EglInterface.cs b/src/Avalonia.OpenGL/EglInterface.cs new file mode 100644 index 00000000000..535f66ee1f5 --- /dev/null +++ b/src/Avalonia.OpenGL/EglInterface.cs @@ -0,0 +1,93 @@ +using System; +using Avalonia.Platform; +using Avalonia.Platform.Interop; +using static Avalonia.OpenGL.EglConsts; + +namespace Avalonia.OpenGL +{ + public class EglInterface : GlInterfaceBase + { + public EglInterface() : base(Load()) + { + + } + + public EglInterface(string library) : base(Load(library)) + { + } + + static Func Load() + { + var os = AvaloniaLocator.Current.GetService().GetRuntimeInfo().OperatingSystem; + if(os == OperatingSystemType.Linux || os == OperatingSystemType.Android) + return Load("libEGL.so.1"); + if (os == OperatingSystemType.WinNT) + return Load(@"libegl.dll"); + throw new PlatformNotSupportedException(); + } + + static Func Load(string library) + { + var dyn = AvaloniaLocator.Current.GetService(); + var lib = dyn.LoadLibrary(library); + return (s, o) => dyn.GetProcAddress(lib, s, o); + } + + // ReSharper disable UnassignedGetOnlyAutoProperty + public delegate IntPtr EglGetDisplay(IntPtr nativeDisplay); + [EntryPoint("eglGetDisplay")] + public EglGetDisplay GetDisplay { get; } + + public delegate IntPtr EglGetPlatformDisplayEXT(int platform, IntPtr nativeDisplay, int[] attrs); + [EntryPoint("eglGetPlatformDisplayEXT", true)] + public EglGetPlatformDisplayEXT GetPlatformDisplayEXT { get; } + + public delegate bool EglInitialize(IntPtr display, out int major, out int minor); + [EntryPoint("eglInitialize")] + public EglInitialize Initialize { get; } + + public delegate IntPtr EglGetProcAddress(Utf8Buffer proc); + [EntryPoint("eglGetProcAddress")] + public EglGetProcAddress GetProcAddress { get; } + + public delegate bool EglBindApi(int api); + [EntryPoint("eglBindAPI")] + public EglBindApi BindApi { get; } + + public delegate bool EglChooseConfig(IntPtr display, int[] attribs, + out IntPtr surfaceConfig, int numConfigs, out int choosenConfig); + [EntryPoint("eglChooseConfig")] + public EglChooseConfig ChooseConfig { get; } + + public delegate IntPtr EglCreateContext(IntPtr display, IntPtr config, + IntPtr share, int[] attrs); + [EntryPoint("eglCreateContext")] + public EglCreateContext CreateContext { get; } + + public delegate IntPtr EglCreatePBufferSurface(IntPtr display, IntPtr config, int[] attrs); + [EntryPoint("eglCreatePbufferSurface")] + public EglCreatePBufferSurface CreatePBufferSurface { get; } + + public delegate bool EglMakeCurrent(IntPtr display, IntPtr draw, IntPtr read, IntPtr context); + [EntryPoint("eglMakeCurrent")] + public EglMakeCurrent MakeCurrent { get; } + + public delegate void EglDisplaySurfaceVoidDelegate(IntPtr display, IntPtr surface); + [EntryPoint("eglDestroySurface")] + public EglDisplaySurfaceVoidDelegate DestroySurface { get; } + + [EntryPoint("eglSwapBuffers")] + public EglDisplaySurfaceVoidDelegate SwapBuffers { get; } + + public delegate IntPtr + EglCreateWindowSurface(IntPtr display, IntPtr config, IntPtr window, int[] attrs); + [EntryPoint("eglCreateWindowSurface")] + public EglCreateWindowSurface CreateWindowSurface { get; } + + public delegate bool EglGetConfigAttrib(IntPtr display, IntPtr config, int attr, out int rv); + [EntryPoint("eglGetConfigAttrib")] + public EglGetConfigAttrib GetConfigAttrib { get; } + + // ReSharper restore UnassignedGetOnlyAutoProperty + } +} diff --git a/src/Avalonia.OpenGL/EntryPointAttribute.cs b/src/Avalonia.OpenGL/EntryPointAttribute.cs new file mode 100644 index 00000000000..241f517df9a --- /dev/null +++ b/src/Avalonia.OpenGL/EntryPointAttribute.cs @@ -0,0 +1,16 @@ +using System; + +namespace Avalonia.OpenGL +{ + class EntryPointAttribute : Attribute + { + public string EntryPoint { get; } + public bool Optional { get; } + + public EntryPointAttribute(string entryPoint, bool optional = false) + { + EntryPoint = entryPoint; + Optional = optional; + } + } +} diff --git a/src/Avalonia.OpenGL/GlConsts.cs b/src/Avalonia.OpenGL/GlConsts.cs new file mode 100644 index 00000000000..3084a6f9588 --- /dev/null +++ b/src/Avalonia.OpenGL/GlConsts.cs @@ -0,0 +1,789 @@ +// ReSharper disable UnusedMember.Global +// ReSharper disable IdentifierTypo +namespace Avalonia.OpenGL +{ + public static class GlConsts + { + public const int GL_BYTE = 0x1400; + public const int GL_UNSIGNED_BYTE = 0x1401; + public const int GL_SHORT = 0x1402; + public const int GL_UNSIGNED_SHORT = 0x1403; + public const int GL_INT = 0x1404; + public const int GL_UNSIGNED_INT = 0x1405; + public const int GL_FLOAT = 0x1406; + public const int GL_2_BYTES = 0x1407; + public const int GL_3_BYTES = 0x1408; + public const int GL_4_BYTES = 0x1409; + public const int GL_DOUBLE = 0x140A; + public const int GL_POINTS = 0x0000; + public const int GL_LINES = 0x0001; + public const int GL_LINE_LOOP = 0x0002; + public const int GL_LINE_STRIP = 0x0003; + public const int GL_TRIANGLES = 0x0004; + public const int GL_TRIANGLE_STRIP = 0x0005; + public const int GL_TRIANGLE_FAN = 0x0006; + public const int GL_QUADS = 0x0007; + public const int GL_QUAD_STRIP = 0x0008; + public const int GL_POLYGON = 0x0009; + public const int GL_VERTEX_ARRAY = 0x8074; + public const int GL_NORMAL_ARRAY = 0x8075; + public const int GL_COLOR_ARRAY = 0x8076; + public const int GL_INDEX_ARRAY = 0x8077; + public const int GL_TEXTURE_COORD_ARRAY = 0x8078; + public const int GL_EDGE_FLAG_ARRAY = 0x8079; + public const int GL_VERTEX_ARRAY_SIZE = 0x807A; + public const int GL_VERTEX_ARRAY_TYPE = 0x807B; + public const int GL_VERTEX_ARRAY_STRIDE = 0x807C; + public const int GL_NORMAL_ARRAY_TYPE = 0x807E; + public const int GL_NORMAL_ARRAY_STRIDE = 0x807F; + public const int GL_COLOR_ARRAY_SIZE = 0x8081; + public const int GL_COLOR_ARRAY_TYPE = 0x8082; + public const int GL_COLOR_ARRAY_STRIDE = 0x8083; + public const int GL_INDEX_ARRAY_TYPE = 0x8085; + public const int GL_INDEX_ARRAY_STRIDE = 0x8086; + public const int GL_TEXTURE_COORD_ARRAY_SIZE = 0x8088; + public const int GL_TEXTURE_COORD_ARRAY_TYPE = 0x8089; + public const int GL_TEXTURE_COORD_ARRAY_STRIDE = 0x808A; + public const int GL_EDGE_FLAG_ARRAY_STRIDE = 0x808C; + public const int GL_VERTEX_ARRAY_POINTER = 0x808E; + public const int GL_NORMAL_ARRAY_POINTER = 0x808F; + public const int GL_COLOR_ARRAY_POINTER = 0x8090; + public const int GL_INDEX_ARRAY_POINTER = 0x8091; + public const int GL_TEXTURE_COORD_ARRAY_POINTER = 0x8092; + public const int GL_EDGE_FLAG_ARRAY_POINTER = 0x8093; + public const int GL_V2F = 0x2A20; + public const int GL_V3F = 0x2A21; + public const int GL_C4UB_V2F = 0x2A22; + public const int GL_C4UB_V3F = 0x2A23; + public const int GL_C3F_V3F = 0x2A24; + public const int GL_N3F_V3F = 0x2A25; + public const int GL_C4F_N3F_V3F = 0x2A26; + public const int GL_T2F_V3F = 0x2A27; + public const int GL_T4F_V4F = 0x2A28; + public const int GL_T2F_C4UB_V3F = 0x2A29; + public const int GL_T2F_C3F_V3F = 0x2A2A; + public const int GL_T2F_N3F_V3F = 0x2A2B; + public const int GL_T2F_C4F_N3F_V3F = 0x2A2C; + public const int GL_T4F_C4F_N3F_V4F = 0x2A2D; + public const int GL_MATRIX_MODE = 0x0BA0; + public const int GL_MODELVIEW = 0x1700; + public const int GL_PROJECTION = 0x1701; + public const int GL_TEXTURE = 0x1702; + public const int GL_POINT_SMOOTH = 0x0B10; + public const int GL_POINT_SIZE = 0x0B11; + public const int GL_POINT_SIZE_GRANULARITY = 0x0B13; + public const int GL_POINT_SIZE_RANGE = 0x0B12; + public const int GL_LINE_SMOOTH = 0x0B20; + public const int GL_LINE_STIPPLE = 0x0B24; + public const int GL_LINE_STIPPLE_PATTERN = 0x0B25; + public const int GL_LINE_STIPPLE_REPEAT = 0x0B26; + public const int GL_LINE_WIDTH = 0x0B21; + public const int GL_LINE_WIDTH_GRANULARITY = 0x0B23; + public const int GL_LINE_WIDTH_RANGE = 0x0B22; + public const int GL_POINT = 0x1B00; + public const int GL_LINE = 0x1B01; + public const int GL_FILL = 0x1B02; + public const int GL_CW = 0x0900; + public const int GL_CCW = 0x0901; + public const int GL_FRONT = 0x0404; + public const int GL_BACK = 0x0405; + public const int GL_POLYGON_MODE = 0x0B40; + public const int GL_POLYGON_SMOOTH = 0x0B41; + public const int GL_POLYGON_STIPPLE = 0x0B42; + public const int GL_EDGE_FLAG = 0x0B43; + public const int GL_CULL_FACE = 0x0B44; + public const int GL_CULL_FACE_MODE = 0x0B45; + public const int GL_FRONT_FACE = 0x0B46; + public const int GL_POLYGON_OFFSET_FACTOR = 0x8038; + public const int GL_POLYGON_OFFSET_UNITS = 0x2A00; + public const int GL_POLYGON_OFFSET_POINT = 0x2A01; + public const int GL_POLYGON_OFFSET_LINE = 0x2A02; + public const int GL_POLYGON_OFFSET_FILL = 0x8037; + public const int GL_COMPILE = 0x1300; + public const int GL_COMPILE_AND_EXECUTE = 0x1301; + public const int GL_LIST_BASE = 0x0B32; + public const int GL_LIST_INDEX = 0x0B33; + public const int GL_LIST_MODE = 0x0B30; + public const int GL_NEVER = 0x0200; + public const int GL_LESS = 0x0201; + public const int GL_EQUAL = 0x0202; + public const int GL_LEQUAL = 0x0203; + public const int GL_GREATER = 0x0204; + public const int GL_NOTEQUAL = 0x0205; + public const int GL_GEQUAL = 0x0206; + public const int GL_ALWAYS = 0x0207; + public const int GL_DEPTH_TEST = 0x0B71; + public const int GL_DEPTH_BITS = 0x0D56; + public const int GL_DEPTH_CLEAR_VALUE = 0x0B73; + public const int GL_DEPTH_FUNC = 0x0B74; + public const int GL_DEPTH_RANGE = 0x0B70; + public const int GL_DEPTH_WRITEMASK = 0x0B72; + public const int GL_DEPTH_COMPONENT = 0x1902; + public const int GL_LIGHTING = 0x0B50; + public const int GL_LIGHT0 = 0x4000; + public const int GL_LIGHT1 = 0x4001; + public const int GL_LIGHT2 = 0x4002; + public const int GL_LIGHT3 = 0x4003; + public const int GL_LIGHT4 = 0x4004; + public const int GL_LIGHT5 = 0x4005; + public const int GL_LIGHT6 = 0x4006; + public const int GL_LIGHT7 = 0x4007; + public const int GL_SPOT_EXPONENT = 0x1205; + public const int GL_SPOT_CUTOFF = 0x1206; + public const int GL_CONSTANT_ATTENUATION = 0x1207; + public const int GL_LINEAR_ATTENUATION = 0x1208; + public const int GL_QUADRATIC_ATTENUATION = 0x1209; + public const int GL_AMBIENT = 0x1200; + public const int GL_DIFFUSE = 0x1201; + public const int GL_SPECULAR = 0x1202; + public const int GL_SHININESS = 0x1601; + public const int GL_EMISSION = 0x1600; + public const int GL_POSITION = 0x1203; + public const int GL_SPOT_DIRECTION = 0x1204; + public const int GL_AMBIENT_AND_DIFFUSE = 0x1602; + public const int GL_COLOR_INDEXES = 0x1603; + public const int GL_LIGHT_MODEL_TWO_SIDE = 0x0B52; + public const int GL_LIGHT_MODEL_LOCAL_VIEWER = 0x0B51; + public const int GL_LIGHT_MODEL_AMBIENT = 0x0B53; + public const int GL_FRONT_AND_BACK = 0x0408; + public const int GL_SHADE_MODEL = 0x0B54; + public const int GL_FLAT = 0x1D00; + public const int GL_SMOOTH = 0x1D01; + public const int GL_COLOR_MATERIAL = 0x0B57; + public const int GL_COLOR_MATERIAL_FACE = 0x0B55; + public const int GL_COLOR_MATERIAL_PARAMETER = 0x0B56; + public const int GL_NORMALIZE = 0x0BA1; + public const int GL_CLIP_PLANE0 = 0x3000; + public const int GL_CLIP_PLANE1 = 0x3001; + public const int GL_CLIP_PLANE2 = 0x3002; + public const int GL_CLIP_PLANE3 = 0x3003; + public const int GL_CLIP_PLANE4 = 0x3004; + public const int GL_CLIP_PLANE5 = 0x3005; + public const int GL_ACCUM_RED_BITS = 0x0D58; + public const int GL_ACCUM_GREEN_BITS = 0x0D59; + public const int GL_ACCUM_BLUE_BITS = 0x0D5A; + public const int GL_ACCUM_ALPHA_BITS = 0x0D5B; + public const int GL_ACCUM_CLEAR_VALUE = 0x0B80; + public const int GL_ACCUM = 0x0100; + public const int GL_ADD = 0x0104; + public const int GL_LOAD = 0x0101; + public const int GL_MULT = 0x0103; + public const int GL_RETURN = 0x0102; + public const int GL_ALPHA_TEST = 0x0BC0; + public const int GL_ALPHA_TEST_REF = 0x0BC2; + public const int GL_ALPHA_TEST_FUNC = 0x0BC1; + public const int GL_BLEND = 0x0BE2; + public const int GL_BLEND_SRC = 0x0BE1; + public const int GL_BLEND_DST = 0x0BE0; + public const int GL_SRC_COLOR = 0x0300; + public const int GL_ONE_MINUS_SRC_COLOR = 0x0301; + public const int GL_SRC_ALPHA = 0x0302; + public const int GL_ONE_MINUS_SRC_ALPHA = 0x0303; + public const int GL_DST_ALPHA = 0x0304; + public const int GL_ONE_MINUS_DST_ALPHA = 0x0305; + public const int GL_DST_COLOR = 0x0306; + public const int GL_ONE_MINUS_DST_COLOR = 0x0307; + public const int GL_SRC_ALPHA_SATURATE = 0x0308; + public const int GL_FEEDBACK = 0x1C01; + public const int GL_RENDER = 0x1C00; + public const int GL_SELECT = 0x1C02; + public const int GL_2D = 0x0600; + public const int GL_3D = 0x0601; + public const int GL_3D_COLOR = 0x0602; + public const int GL_3D_COLOR_TEXTURE = 0x0603; + public const int GL_4D_COLOR_TEXTURE = 0x0604; + public const int GL_POINT_TOKEN = 0x0701; + public const int GL_LINE_TOKEN = 0x0702; + public const int GL_LINE_RESET_TOKEN = 0x0707; + public const int GL_POLYGON_TOKEN = 0x0703; + public const int GL_BITMAP_TOKEN = 0x0704; + public const int GL_DRAW_PIXEL_TOKEN = 0x0705; + public const int GL_COPY_PIXEL_TOKEN = 0x0706; + public const int GL_PASS_THROUGH_TOKEN = 0x0700; + public const int GL_FEEDBACK_BUFFER_POINTER = 0x0DF0; + public const int GL_FEEDBACK_BUFFER_SIZE = 0x0DF1; + public const int GL_FEEDBACK_BUFFER_TYPE = 0x0DF2; + public const int GL_SELECTION_BUFFER_POINTER = 0x0DF3; + public const int GL_SELECTION_BUFFER_SIZE = 0x0DF4; + public const int GL_FOG = 0x0B60; + public const int GL_FOG_MODE = 0x0B65; + public const int GL_FOG_DENSITY = 0x0B62; + public const int GL_FOG_COLOR = 0x0B66; + public const int GL_FOG_INDEX = 0x0B61; + public const int GL_FOG_START = 0x0B63; + public const int GL_FOG_END = 0x0B64; + public const int GL_LINEAR = 0x2601; + public const int GL_EXP = 0x0800; + public const int GL_EXP2 = 0x0801; + public const int GL_LOGIC_OP = 0x0BF1; + public const int GL_INDEX_LOGIC_OP = 0x0BF1; + public const int GL_COLOR_LOGIC_OP = 0x0BF2; + public const int GL_LOGIC_OP_MODE = 0x0BF0; + public const int GL_CLEAR = 0x1500; + public const int GL_SET = 0x150F; + public const int GL_COPY = 0x1503; + public const int GL_COPY_INVERTED = 0x150C; + public const int GL_NOOP = 0x1505; + public const int GL_INVERT = 0x150A; + public const int GL_AND = 0x1501; + public const int GL_NAND = 0x150E; + public const int GL_OR = 0x1507; + public const int GL_NOR = 0x1508; + public const int GL_XOR = 0x1506; + public const int GL_EQUIV = 0x1509; + public const int GL_AND_REVERSE = 0x1502; + public const int GL_AND_INVERTED = 0x1504; + public const int GL_OR_REVERSE = 0x150B; + public const int GL_OR_INVERTED = 0x150D; + public const int GL_STENCIL_BITS = 0x0D57; + public const int GL_STENCIL_TEST = 0x0B90; + public const int GL_STENCIL_CLEAR_VALUE = 0x0B91; + public const int GL_STENCIL_FUNC = 0x0B92; + public const int GL_STENCIL_VALUE_MASK = 0x0B93; + public const int GL_STENCIL_FAIL = 0x0B94; + public const int GL_STENCIL_PASS_DEPTH_FAIL = 0x0B95; + public const int GL_STENCIL_PASS_DEPTH_PASS = 0x0B96; + public const int GL_STENCIL_REF = 0x0B97; + public const int GL_STENCIL_WRITEMASK = 0x0B98; + public const int GL_STENCIL_INDEX = 0x1901; + public const int GL_KEEP = 0x1E00; + public const int GL_REPLACE = 0x1E01; + public const int GL_INCR = 0x1E02; + public const int GL_DECR = 0x1E03; + public const int GL_LEFT = 0x0406; + public const int GL_RIGHT = 0x0407; + public const int GL_FRONT_LEFT = 0x0400; + public const int GL_FRONT_RIGHT = 0x0401; + public const int GL_BACK_LEFT = 0x0402; + public const int GL_BACK_RIGHT = 0x0403; + public const int GL_AUX0 = 0x0409; + public const int GL_AUX1 = 0x040A; + public const int GL_AUX2 = 0x040B; + public const int GL_AUX3 = 0x040C; + public const int GL_COLOR_INDEX = 0x1900; + public const int GL_RED = 0x1903; + public const int GL_GREEN = 0x1904; + public const int GL_BLUE = 0x1905; + public const int GL_ALPHA = 0x1906; + public const int GL_LUMINANCE = 0x1909; + public const int GL_LUMINANCE_ALPHA = 0x190A; + public const int GL_ALPHA_BITS = 0x0D55; + public const int GL_RED_BITS = 0x0D52; + public const int GL_GREEN_BITS = 0x0D53; + public const int GL_BLUE_BITS = 0x0D54; + public const int GL_INDEX_BITS = 0x0D51; + public const int GL_SUBPIXEL_BITS = 0x0D50; + public const int GL_AUX_BUFFERS = 0x0C00; + public const int GL_READ_BUFFER = 0x0C02; + public const int GL_DRAW_BUFFER = 0x0C01; + public const int GL_DOUBLEBUFFER = 0x0C32; + public const int GL_STEREO = 0x0C33; + public const int GL_BITMAP = 0x1A00; + public const int GL_COLOR = 0x1800; + public const int GL_DEPTH = 0x1801; + public const int GL_STENCIL = 0x1802; + public const int GL_DITHER = 0x0BD0; + public const int GL_RGB = 0x1907; + public const int GL_RGBA = 0x1908; + public const int GL_MAX_LIST_NESTING = 0x0B31; + public const int GL_MAX_EVAL_ORDER = 0x0D30; + public const int GL_MAX_LIGHTS = 0x0D31; + public const int GL_MAX_CLIP_PLANES = 0x0D32; + public const int GL_MAX_TEXTURE_SIZE = 0x0D33; + public const int GL_MAX_PIXEL_MAP_TABLE = 0x0D34; + public const int GL_MAX_ATTRIB_STACK_DEPTH = 0x0D35; + public const int GL_MAX_MODELVIEW_STACK_DEPTH = 0x0D36; + public const int GL_MAX_NAME_STACK_DEPTH = 0x0D37; + public const int GL_MAX_PROJECTION_STACK_DEPTH = 0x0D38; + public const int GL_MAX_TEXTURE_STACK_DEPTH = 0x0D39; + public const int GL_MAX_VIEWPORT_DIMS = 0x0D3A; + public const int GL_MAX_CLIENT_ATTRIB_STACK_DEPTH = 0x0D3B; + public const int GL_ATTRIB_STACK_DEPTH = 0x0BB0; + public const int GL_CLIENT_ATTRIB_STACK_DEPTH = 0x0BB1; + public const int GL_COLOR_CLEAR_VALUE = 0x0C22; + public const int GL_COLOR_WRITEMASK = 0x0C23; + public const int GL_CURRENT_INDEX = 0x0B01; + public const int GL_CURRENT_COLOR = 0x0B00; + public const int GL_CURRENT_NORMAL = 0x0B02; + public const int GL_CURRENT_RASTER_COLOR = 0x0B04; + public const int GL_CURRENT_RASTER_DISTANCE = 0x0B09; + public const int GL_CURRENT_RASTER_INDEX = 0x0B05; + public const int GL_CURRENT_RASTER_POSITION = 0x0B07; + public const int GL_CURRENT_RASTER_TEXTURE_COORDS = 0x0B06; + public const int GL_CURRENT_RASTER_POSITION_VALID = 0x0B08; + public const int GL_CURRENT_TEXTURE_COORDS = 0x0B03; + public const int GL_INDEX_CLEAR_VALUE = 0x0C20; + public const int GL_INDEX_MODE = 0x0C30; + public const int GL_INDEX_WRITEMASK = 0x0C21; + public const int GL_MODELVIEW_MATRIX = 0x0BA6; + public const int GL_MODELVIEW_STACK_DEPTH = 0x0BA3; + public const int GL_NAME_STACK_DEPTH = 0x0D70; + public const int GL_PROJECTION_MATRIX = 0x0BA7; + public const int GL_PROJECTION_STACK_DEPTH = 0x0BA4; + public const int GL_RENDER_MODE = 0x0C40; + public const int GL_RGBA_MODE = 0x0C31; + public const int GL_TEXTURE_MATRIX = 0x0BA8; + public const int GL_TEXTURE_STACK_DEPTH = 0x0BA5; + public const int GL_VIEWPORT = 0x0BA2; + public const int GL_AUTO_NORMAL = 0x0D80; + public const int GL_MAP1_COLOR_4 = 0x0D90; + public const int GL_MAP1_INDEX = 0x0D91; + public const int GL_MAP1_NORMAL = 0x0D92; + public const int GL_MAP1_TEXTURE_COORD_1 = 0x0D93; + public const int GL_MAP1_TEXTURE_COORD_2 = 0x0D94; + public const int GL_MAP1_TEXTURE_COORD_3 = 0x0D95; + public const int GL_MAP1_TEXTURE_COORD_4 = 0x0D96; + public const int GL_MAP1_VERTEX_3 = 0x0D97; + public const int GL_MAP1_VERTEX_4 = 0x0D98; + public const int GL_MAP2_COLOR_4 = 0x0DB0; + public const int GL_MAP2_INDEX = 0x0DB1; + public const int GL_MAP2_NORMAL = 0x0DB2; + public const int GL_MAP2_TEXTURE_COORD_1 = 0x0DB3; + public const int GL_MAP2_TEXTURE_COORD_2 = 0x0DB4; + public const int GL_MAP2_TEXTURE_COORD_3 = 0x0DB5; + public const int GL_MAP2_TEXTURE_COORD_4 = 0x0DB6; + public const int GL_MAP2_VERTEX_3 = 0x0DB7; + public const int GL_MAP2_VERTEX_4 = 0x0DB8; + public const int GL_MAP1_GRID_DOMAIN = 0x0DD0; + public const int GL_MAP1_GRID_SEGMENTS = 0x0DD1; + public const int GL_MAP2_GRID_DOMAIN = 0x0DD2; + public const int GL_MAP2_GRID_SEGMENTS = 0x0DD3; + public const int GL_COEFF = 0x0A00; + public const int GL_ORDER = 0x0A01; + public const int GL_DOMAIN = 0x0A02; + public const int GL_PERSPECTIVE_CORRECTION_HINT = 0x0C50; + public const int GL_POINT_SMOOTH_HINT = 0x0C51; + public const int GL_LINE_SMOOTH_HINT = 0x0C52; + public const int GL_POLYGON_SMOOTH_HINT = 0x0C53; + public const int GL_FOG_HINT = 0x0C54; + public const int GL_DONT_CARE = 0x1100; + public const int GL_FASTEST = 0x1101; + public const int GL_NICEST = 0x1102; + public const int GL_SCISSOR_BOX = 0x0C10; + public const int GL_SCISSOR_TEST = 0x0C11; + public const int GL_MAP_COLOR = 0x0D10; + public const int GL_MAP_STENCIL = 0x0D11; + public const int GL_INDEX_SHIFT = 0x0D12; + public const int GL_INDEX_OFFSET = 0x0D13; + public const int GL_RED_SCALE = 0x0D14; + public const int GL_RED_BIAS = 0x0D15; + public const int GL_GREEN_SCALE = 0x0D18; + public const int GL_GREEN_BIAS = 0x0D19; + public const int GL_BLUE_SCALE = 0x0D1A; + public const int GL_BLUE_BIAS = 0x0D1B; + public const int GL_ALPHA_SCALE = 0x0D1C; + public const int GL_ALPHA_BIAS = 0x0D1D; + public const int GL_DEPTH_SCALE = 0x0D1E; + public const int GL_DEPTH_BIAS = 0x0D1F; + public const int GL_PIXEL_MAP_S_TO_S_SIZE = 0x0CB1; + public const int GL_PIXEL_MAP_I_TO_I_SIZE = 0x0CB0; + public const int GL_PIXEL_MAP_I_TO_R_SIZE = 0x0CB2; + public const int GL_PIXEL_MAP_I_TO_G_SIZE = 0x0CB3; + public const int GL_PIXEL_MAP_I_TO_B_SIZE = 0x0CB4; + public const int GL_PIXEL_MAP_I_TO_A_SIZE = 0x0CB5; + public const int GL_PIXEL_MAP_R_TO_R_SIZE = 0x0CB6; + public const int GL_PIXEL_MAP_G_TO_G_SIZE = 0x0CB7; + public const int GL_PIXEL_MAP_B_TO_B_SIZE = 0x0CB8; + public const int GL_PIXEL_MAP_A_TO_A_SIZE = 0x0CB9; + public const int GL_PIXEL_MAP_S_TO_S = 0x0C71; + public const int GL_PIXEL_MAP_I_TO_I = 0x0C70; + public const int GL_PIXEL_MAP_I_TO_R = 0x0C72; + public const int GL_PIXEL_MAP_I_TO_G = 0x0C73; + public const int GL_PIXEL_MAP_I_TO_B = 0x0C74; + public const int GL_PIXEL_MAP_I_TO_A = 0x0C75; + public const int GL_PIXEL_MAP_R_TO_R = 0x0C76; + public const int GL_PIXEL_MAP_G_TO_G = 0x0C77; + public const int GL_PIXEL_MAP_B_TO_B = 0x0C78; + public const int GL_PIXEL_MAP_A_TO_A = 0x0C79; + public const int GL_PACK_ALIGNMENT = 0x0D05; + public const int GL_PACK_LSB_FIRST = 0x0D01; + public const int GL_PACK_ROW_LENGTH = 0x0D02; + public const int GL_PACK_SKIP_PIXELS = 0x0D04; + public const int GL_PACK_SKIP_ROWS = 0x0D03; + public const int GL_PACK_SWAP_BYTES = 0x0D00; + public const int GL_UNPACK_ALIGNMENT = 0x0CF5; + public const int GL_UNPACK_LSB_FIRST = 0x0CF1; + public const int GL_UNPACK_ROW_LENGTH = 0x0CF2; + public const int GL_UNPACK_SKIP_PIXELS = 0x0CF4; + public const int GL_UNPACK_SKIP_ROWS = 0x0CF3; + public const int GL_UNPACK_SWAP_BYTES = 0x0CF0; + public const int GL_ZOOM_X = 0x0D16; + public const int GL_ZOOM_Y = 0x0D17; + public const int GL_TEXTURE_ENV = 0x2300; + public const int GL_TEXTURE_ENV_MODE = 0x2200; + public const int GL_TEXTURE_1D = 0x0DE0; + public const int GL_TEXTURE_2D = 0x0DE1; + public const int GL_TEXTURE_WRAP_S = 0x2802; + public const int GL_TEXTURE_WRAP_T = 0x2803; + public const int GL_TEXTURE_MAG_FILTER = 0x2800; + public const int GL_TEXTURE_MIN_FILTER = 0x2801; + public const int GL_TEXTURE_ENV_COLOR = 0x2201; + public const int GL_TEXTURE_GEN_S = 0x0C60; + public const int GL_TEXTURE_GEN_T = 0x0C61; + public const int GL_TEXTURE_GEN_R = 0x0C62; + public const int GL_TEXTURE_GEN_Q = 0x0C63; + public const int GL_TEXTURE_GEN_MODE = 0x2500; + public const int GL_TEXTURE_BORDER_COLOR = 0x1004; + public const int GL_TEXTURE_WIDTH = 0x1000; + public const int GL_TEXTURE_HEIGHT = 0x1001; + public const int GL_TEXTURE_BORDER = 0x1005; + public const int GL_TEXTURE_COMPONENTS = 0x1003; + public const int GL_TEXTURE_RED_SIZE = 0x805C; + public const int GL_TEXTURE_GREEN_SIZE = 0x805D; + public const int GL_TEXTURE_BLUE_SIZE = 0x805E; + public const int GL_TEXTURE_ALPHA_SIZE = 0x805F; + public const int GL_TEXTURE_LUMINANCE_SIZE = 0x8060; + public const int GL_TEXTURE_INTENSITY_SIZE = 0x8061; + public const int GL_NEAREST_MIPMAP_NEAREST = 0x2700; + public const int GL_NEAREST_MIPMAP_LINEAR = 0x2702; + public const int GL_LINEAR_MIPMAP_NEAREST = 0x2701; + public const int GL_LINEAR_MIPMAP_LINEAR = 0x2703; + public const int GL_OBJECT_LINEAR = 0x2401; + public const int GL_OBJECT_PLANE = 0x2501; + public const int GL_EYE_LINEAR = 0x2400; + public const int GL_EYE_PLANE = 0x2502; + public const int GL_SPHERE_MAP = 0x2402; + public const int GL_DECAL = 0x2101; + public const int GL_MODULATE = 0x2100; + public const int GL_NEAREST = 0x2600; + public const int GL_REPEAT = 0x2901; + public const int GL_CLAMP = 0x2900; + public const int GL_S = 0x2000; + public const int GL_T = 0x2001; + public const int GL_R = 0x2002; + public const int GL_Q = 0x2003; + public const int GL_VENDOR = 0x1F00; + public const int GL_RENDERER = 0x1F01; + public const int GL_VERSION = 0x1F02; + public const int GL_EXTENSIONS = 0x1F03; + public const int GL_INVALID_ENUM = 0x0500; + public const int GL_INVALID_VALUE = 0x0501; + public const int GL_INVALID_OPERATION = 0x0502; + public const int GL_STACK_OVERFLOW = 0x0503; + public const int GL_STACK_UNDERFLOW = 0x0504; + public const int GL_OUT_OF_MEMORY = 0x0505; + public const int GL_CURRENT_BIT = 0x00000001; + public const int GL_POINT_BIT = 0x00000002; + public const int GL_LINE_BIT = 0x00000004; + public const int GL_POLYGON_BIT = 0x00000008; + public const int GL_POLYGON_STIPPLE_BIT = 0x00000010; + public const int GL_PIXEL_MODE_BIT = 0x00000020; + public const int GL_LIGHTING_BIT = 0x00000040; + public const int GL_FOG_BIT = 0x00000080; + public const int GL_DEPTH_BUFFER_BIT = 0x00000100; + public const int GL_ACCUM_BUFFER_BIT = 0x00000200; + public const int GL_STENCIL_BUFFER_BIT = 0x00000400; + public const int GL_VIEWPORT_BIT = 0x00000800; + public const int GL_TRANSFORM_BIT = 0x00001000; + public const int GL_ENABLE_BIT = 0x00002000; + public const int GL_COLOR_BUFFER_BIT = 0x00004000; + public const int GL_HINT_BIT = 0x00008000; + public const int GL_EVAL_BIT = 0x00010000; + public const int GL_LIST_BIT = 0x00020000; + public const int GL_TEXTURE_BIT = 0x00040000; + public const int GL_SCISSOR_BIT = 0x00080000; + public const int GL_ALL_ATTRIB_BITS = -1; + public const int GL_PROXY_TEXTURE_1D = 0x8063; + public const int GL_PROXY_TEXTURE_2D = 0x8064; + public const int GL_TEXTURE_PRIORITY = 0x8066; + public const int GL_TEXTURE_RESIDENT = 0x8067; + public const int GL_TEXTURE_BINDING_1D = 0x8068; + public const int GL_TEXTURE_BINDING_2D = 0x8069; + public const int GL_TEXTURE_INTERNAL_FORMAT = 0x1003; + public const int GL_ALPHA4 = 0x803B; + public const int GL_ALPHA8 = 0x803C; + public const int GL_ALPHA12 = 0x803D; + public const int GL_ALPHA16 = 0x803E; + public const int GL_LUMINANCE4 = 0x803F; + public const int GL_LUMINANCE8 = 0x8040; + public const int GL_LUMINANCE12 = 0x8041; + public const int GL_LUMINANCE16 = 0x8042; + public const int GL_LUMINANCE4_ALPHA4 = 0x8043; + public const int GL_LUMINANCE6_ALPHA2 = 0x8044; + public const int GL_LUMINANCE8_ALPHA8 = 0x8045; + public const int GL_LUMINANCE12_ALPHA4 = 0x8046; + public const int GL_LUMINANCE12_ALPHA12 = 0x8047; + public const int GL_LUMINANCE16_ALPHA16 = 0x8048; + public const int GL_INTENSITY = 0x8049; + public const int GL_INTENSITY4 = 0x804A; + public const int GL_INTENSITY8 = 0x804B; + public const int GL_INTENSITY12 = 0x804C; + public const int GL_INTENSITY16 = 0x804D; + public const int GL_R3_G3_B2 = 0x2A10; + public const int GL_RGB4 = 0x804F; + public const int GL_RGB5 = 0x8050; + public const int GL_RGB8 = 0x8051; + public const int GL_RGB10 = 0x8052; + public const int GL_RGB12 = 0x8053; + public const int GL_RGB16 = 0x8054; + public const int GL_RGBA2 = 0x8055; + public const int GL_RGBA4 = 0x8056; + public const int GL_RGB5_A1 = 0x8057; + public const int GL_RGBA8 = 0x8058; + public const int GL_RGB10_A2 = 0x8059; + public const int GL_RGBA12 = 0x805A; + public const int GL_RGBA16 = 0x805B; + public const int GL_CLIENT_PIXEL_STORE_BIT = 0x00000001; + public const int GL_CLIENT_VERTEX_ARRAY_BIT = 0x00000002; + public const int GL_ALL_CLIENT_ATTRIB_BITS = -1; + public const int GL_CLIENT_ALL_ATTRIB_BITS = -1; + public const int GL_RESCALE_NORMAL = 0x803A; + public const int GL_CLAMP_TO_EDGE = 0x812F; + public const int GL_MAX_ELEMENTS_VERTICES = 0x80E8; + public const int GL_MAX_ELEMENTS_INDICES = 0x80E9; + public const int GL_BGR = 0x80E0; + public const int GL_BGRA = 0x80E1; + public const int GL_UNSIGNED_BYTE_3_3_2 = 0x8032; + public const int GL_UNSIGNED_BYTE_2_3_3_REV = 0x8362; + public const int GL_UNSIGNED_SHORT_5_6_5 = 0x8363; + public const int GL_UNSIGNED_SHORT_5_6_5_REV = 0x8364; + public const int GL_UNSIGNED_SHORT_4_4_4_4 = 0x8033; + public const int GL_UNSIGNED_SHORT_4_4_4_4_REV = 0x8365; + public const int GL_UNSIGNED_SHORT_5_5_5_1 = 0x8034; + public const int GL_UNSIGNED_SHORT_1_5_5_5_REV = 0x8366; + public const int GL_UNSIGNED_INT_8_8_8_8 = 0x8035; + public const int GL_UNSIGNED_INT_8_8_8_8_REV = 0x8367; + public const int GL_UNSIGNED_INT_10_10_10_2 = 0x8036; + public const int GL_UNSIGNED_INT_2_10_10_10_REV = 0x8368; + public const int GL_LIGHT_MODEL_COLOR_CONTROL = 0x81F8; + public const int GL_SINGLE_COLOR = 0x81F9; + public const int GL_SEPARATE_SPECULAR_COLOR = 0x81FA; + public const int GL_TEXTURE_MIN_LOD = 0x813A; + public const int GL_TEXTURE_MAX_LOD = 0x813B; + public const int GL_TEXTURE_BASE_LEVEL = 0x813C; + public const int GL_TEXTURE_MAX_LEVEL = 0x813D; + public const int GL_SMOOTH_POINT_SIZE_RANGE = 0x0B12; + public const int GL_SMOOTH_POINT_SIZE_GRANULARITY = 0x0B13; + public const int GL_SMOOTH_LINE_WIDTH_RANGE = 0x0B22; + public const int GL_SMOOTH_LINE_WIDTH_GRANULARITY = 0x0B23; + public const int GL_ALIASED_POINT_SIZE_RANGE = 0x846D; + public const int GL_ALIASED_LINE_WIDTH_RANGE = 0x846E; + public const int GL_PACK_SKIP_IMAGES = 0x806B; + public const int GL_PACK_IMAGE_HEIGHT = 0x806C; + public const int GL_UNPACK_SKIP_IMAGES = 0x806D; + public const int GL_UNPACK_IMAGE_HEIGHT = 0x806E; + public const int GL_TEXTURE_3D = 0x806F; + public const int GL_PROXY_TEXTURE_3D = 0x8070; + public const int GL_TEXTURE_DEPTH = 0x8071; + public const int GL_TEXTURE_WRAP_R = 0x8072; + public const int GL_MAX_3D_TEXTURE_SIZE = 0x8073; + public const int GL_TEXTURE_BINDING_3D = 0x806A; + public const int GL_CONSTANT_COLOR = 0x8001; + public const int GL_ONE_MINUS_CONSTANT_COLOR = 0x8002; + public const int GL_CONSTANT_ALPHA = 0x8003; + public const int GL_ONE_MINUS_CONSTANT_ALPHA = 0x8004; + public const int GL_COLOR_TABLE = 0x80D0; + public const int GL_POST_CONVOLUTION_COLOR_TABLE = 0x80D1; + public const int GL_POST_COLOR_MATRIX_COLOR_TABLE = 0x80D2; + public const int GL_PROXY_COLOR_TABLE = 0x80D3; + public const int GL_PROXY_POST_CONVOLUTION_COLOR_TABLE = 0x80D4; + public const int GL_PROXY_POST_COLOR_MATRIX_COLOR_TABLE = 0x80D5; + public const int GL_COLOR_TABLE_SCALE = 0x80D6; + public const int GL_COLOR_TABLE_BIAS = 0x80D7; + public const int GL_COLOR_TABLE_FORMAT = 0x80D8; + public const int GL_COLOR_TABLE_WIDTH = 0x80D9; + public const int GL_COLOR_TABLE_RED_SIZE = 0x80DA; + public const int GL_COLOR_TABLE_GREEN_SIZE = 0x80DB; + public const int GL_COLOR_TABLE_BLUE_SIZE = 0x80DC; + public const int GL_COLOR_TABLE_ALPHA_SIZE = 0x80DD; + public const int GL_COLOR_TABLE_LUMINANCE_SIZE = 0x80DE; + public const int GL_COLOR_TABLE_INTENSITY_SIZE = 0x80DF; + public const int GL_CONVOLUTION_1D = 0x8010; + public const int GL_CONVOLUTION_2D = 0x8011; + public const int GL_SEPARABLE_2D = 0x8012; + public const int GL_CONVOLUTION_BORDER_MODE = 0x8013; + public const int GL_CONVOLUTION_FILTER_SCALE = 0x8014; + public const int GL_CONVOLUTION_FILTER_BIAS = 0x8015; + public const int GL_REDUCE = 0x8016; + public const int GL_CONVOLUTION_FORMAT = 0x8017; + public const int GL_CONVOLUTION_WIDTH = 0x8018; + public const int GL_CONVOLUTION_HEIGHT = 0x8019; + public const int GL_MAX_CONVOLUTION_WIDTH = 0x801A; + public const int GL_MAX_CONVOLUTION_HEIGHT = 0x801B; + public const int GL_POST_CONVOLUTION_RED_SCALE = 0x801C; + public const int GL_POST_CONVOLUTION_GREEN_SCALE = 0x801D; + public const int GL_POST_CONVOLUTION_BLUE_SCALE = 0x801E; + public const int GL_POST_CONVOLUTION_ALPHA_SCALE = 0x801F; + public const int GL_POST_CONVOLUTION_RED_BIAS = 0x8020; + public const int GL_POST_CONVOLUTION_GREEN_BIAS = 0x8021; + public const int GL_POST_CONVOLUTION_BLUE_BIAS = 0x8022; + public const int GL_POST_CONVOLUTION_ALPHA_BIAS = 0x8023; + public const int GL_CONSTANT_BORDER = 0x8151; + public const int GL_REPLICATE_BORDER = 0x8153; + public const int GL_CONVOLUTION_BORDER_COLOR = 0x8154; + public const int GL_COLOR_MATRIX = 0x80B1; + public const int GL_COLOR_MATRIX_STACK_DEPTH = 0x80B2; + public const int GL_MAX_COLOR_MATRIX_STACK_DEPTH = 0x80B3; + public const int GL_POST_COLOR_MATRIX_RED_SCALE = 0x80B4; + public const int GL_POST_COLOR_MATRIX_GREEN_SCALE = 0x80B5; + public const int GL_POST_COLOR_MATRIX_BLUE_SCALE = 0x80B6; + public const int GL_POST_COLOR_MATRIX_ALPHA_SCALE = 0x80B7; + public const int GL_POST_COLOR_MATRIX_RED_BIAS = 0x80B8; + public const int GL_POST_COLOR_MATRIX_GREEN_BIAS = 0x80B9; + public const int GL_POST_COLOR_MATRIX_BLUE_BIAS = 0x80BA; + public const int GL_POST_COLOR_MATRIX_ALPHA_BIAS = 0x80BB; + public const int GL_HISTOGRAM = 0x8024; + public const int GL_PROXY_HISTOGRAM = 0x8025; + public const int GL_HISTOGRAM_WIDTH = 0x8026; + public const int GL_HISTOGRAM_FORMAT = 0x8027; + public const int GL_HISTOGRAM_RED_SIZE = 0x8028; + public const int GL_HISTOGRAM_GREEN_SIZE = 0x8029; + public const int GL_HISTOGRAM_BLUE_SIZE = 0x802A; + public const int GL_HISTOGRAM_ALPHA_SIZE = 0x802B; + public const int GL_HISTOGRAM_LUMINANCE_SIZE = 0x802C; + public const int GL_HISTOGRAM_SINK = 0x802D; + public const int GL_MINMAX = 0x802E; + public const int GL_MINMAX_FORMAT = 0x802F; + public const int GL_MINMAX_SINK = 0x8030; + public const int GL_TABLE_TOO_LARGE = 0x8031; + public const int GL_BLEND_EQUATION = 0x8009; + public const int GL_MIN = 0x8007; + public const int GL_MAX = 0x8008; + public const int GL_FUNC_ADD = 0x8006; + public const int GL_FUNC_SUBTRACT = 0x800A; + public const int GL_FUNC_REVERSE_SUBTRACT = 0x800B; + public const int GL_BLEND_COLOR = 0x8005; + public const int GL_TEXTURE0 = 0x84C0; + public const int GL_TEXTURE1 = 0x84C1; + public const int GL_TEXTURE2 = 0x84C2; + public const int GL_TEXTURE3 = 0x84C3; + public const int GL_TEXTURE4 = 0x84C4; + public const int GL_TEXTURE5 = 0x84C5; + public const int GL_TEXTURE6 = 0x84C6; + public const int GL_TEXTURE7 = 0x84C7; + public const int GL_TEXTURE8 = 0x84C8; + public const int GL_TEXTURE9 = 0x84C9; + public const int GL_TEXTURE10 = 0x84CA; + public const int GL_TEXTURE11 = 0x84CB; + public const int GL_TEXTURE12 = 0x84CC; + public const int GL_TEXTURE13 = 0x84CD; + public const int GL_TEXTURE14 = 0x84CE; + public const int GL_TEXTURE15 = 0x84CF; + public const int GL_TEXTURE16 = 0x84D0; + public const int GL_TEXTURE17 = 0x84D1; + public const int GL_TEXTURE18 = 0x84D2; + public const int GL_TEXTURE19 = 0x84D3; + public const int GL_TEXTURE20 = 0x84D4; + public const int GL_TEXTURE21 = 0x84D5; + public const int GL_TEXTURE22 = 0x84D6; + public const int GL_TEXTURE23 = 0x84D7; + public const int GL_TEXTURE24 = 0x84D8; + public const int GL_TEXTURE25 = 0x84D9; + public const int GL_TEXTURE26 = 0x84DA; + public const int GL_TEXTURE27 = 0x84DB; + public const int GL_TEXTURE28 = 0x84DC; + public const int GL_TEXTURE29 = 0x84DD; + public const int GL_TEXTURE30 = 0x84DE; + public const int GL_TEXTURE31 = 0x84DF; + public const int GL_ACTIVE_TEXTURE = 0x84E0; + public const int GL_CLIENT_ACTIVE_TEXTURE = 0x84E1; + public const int GL_MAX_TEXTURE_UNITS = 0x84E2; + public const int GL_NORMAL_MAP = 0x8511; + public const int GL_REFLECTION_MAP = 0x8512; + public const int GL_TEXTURE_CUBE_MAP = 0x8513; + public const int GL_TEXTURE_BINDING_CUBE_MAP = 0x8514; + public const int GL_TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515; + public const int GL_TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516; + public const int GL_TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517; + public const int GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518; + public const int GL_TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519; + public const int GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A; + public const int GL_PROXY_TEXTURE_CUBE_MAP = 0x851B; + public const int GL_MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C; + public const int GL_COMPRESSED_ALPHA = 0x84E9; + public const int GL_COMPRESSED_LUMINANCE = 0x84EA; + public const int GL_COMPRESSED_LUMINANCE_ALPHA = 0x84EB; + public const int GL_COMPRESSED_INTENSITY = 0x84EC; + public const int GL_COMPRESSED_RGB = 0x84ED; + public const int GL_COMPRESSED_RGBA = 0x84EE; + public const int GL_TEXTURE_COMPRESSION_HINT = 0x84EF; + public const int GL_TEXTURE_COMPRESSED_IMAGE_SIZE = 0x86A0; + public const int GL_TEXTURE_COMPRESSED = 0x86A1; + public const int GL_NUM_COMPRESSED_TEXTURE_FORMATS = 0x86A2; + public const int GL_COMPRESSED_TEXTURE_FORMATS = 0x86A3; + public const int GL_MULTISAMPLE = 0x809D; + public const int GL_SAMPLE_ALPHA_TO_COVERAGE = 0x809E; + public const int GL_SAMPLE_ALPHA_TO_ONE = 0x809F; + public const int GL_SAMPLE_COVERAGE = 0x80A0; + public const int GL_SAMPLE_BUFFERS = 0x80A8; + public const int GL_SAMPLES = 0x80A9; + public const int GL_SAMPLE_COVERAGE_VALUE = 0x80AA; + public const int GL_SAMPLE_COVERAGE_INVERT = 0x80AB; + public const int GL_MULTISAMPLE_BIT = 0x20000000; + public const int GL_TRANSPOSE_MODELVIEW_MATRIX = 0x84E3; + public const int GL_TRANSPOSE_PROJECTION_MATRIX = 0x84E4; + public const int GL_TRANSPOSE_TEXTURE_MATRIX = 0x84E5; + public const int GL_TRANSPOSE_COLOR_MATRIX = 0x84E6; + public const int GL_COMBINE = 0x8570; + public const int GL_COMBINE_RGB = 0x8571; + public const int GL_COMBINE_ALPHA = 0x8572; + public const int GL_SOURCE0_RGB = 0x8580; + public const int GL_SOURCE1_RGB = 0x8581; + public const int GL_SOURCE2_RGB = 0x8582; + public const int GL_SOURCE0_ALPHA = 0x8588; + public const int GL_SOURCE1_ALPHA = 0x8589; + public const int GL_SOURCE2_ALPHA = 0x858A; + public const int GL_OPERAND0_RGB = 0x8590; + public const int GL_OPERAND1_RGB = 0x8591; + public const int GL_OPERAND2_RGB = 0x8592; + public const int GL_OPERAND0_ALPHA = 0x8598; + public const int GL_OPERAND1_ALPHA = 0x8599; + public const int GL_OPERAND2_ALPHA = 0x859A; + public const int GL_RGB_SCALE = 0x8573; + public const int GL_ADD_SIGNED = 0x8574; + public const int GL_INTERPOLATE = 0x8575; + public const int GL_SUBTRACT = 0x84E7; + public const int GL_CONSTANT = 0x8576; + public const int GL_PRIMARY_COLOR = 0x8577; + public const int GL_PREVIOUS = 0x8578; + public const int GL_DOT3_RGB = 0x86AE; + public const int GL_DOT3_RGBA = 0x86AF; + public const int GL_CLAMP_TO_BORDER = 0x812D; + public const int GL_TEXTURE0_ARB = 0x84C0; + public const int GL_TEXTURE1_ARB = 0x84C1; + public const int GL_TEXTURE2_ARB = 0x84C2; + public const int GL_TEXTURE3_ARB = 0x84C3; + public const int GL_TEXTURE4_ARB = 0x84C4; + public const int GL_TEXTURE5_ARB = 0x84C5; + public const int GL_TEXTURE6_ARB = 0x84C6; + public const int GL_TEXTURE7_ARB = 0x84C7; + public const int GL_TEXTURE8_ARB = 0x84C8; + public const int GL_TEXTURE9_ARB = 0x84C9; + public const int GL_TEXTURE10_ARB = 0x84CA; + public const int GL_TEXTURE11_ARB = 0x84CB; + public const int GL_TEXTURE12_ARB = 0x84CC; + public const int GL_TEXTURE13_ARB = 0x84CD; + public const int GL_TEXTURE14_ARB = 0x84CE; + public const int GL_TEXTURE15_ARB = 0x84CF; + public const int GL_TEXTURE16_ARB = 0x84D0; + public const int GL_TEXTURE17_ARB = 0x84D1; + public const int GL_TEXTURE18_ARB = 0x84D2; + public const int GL_TEXTURE19_ARB = 0x84D3; + public const int GL_TEXTURE20_ARB = 0x84D4; + public const int GL_TEXTURE21_ARB = 0x84D5; + public const int GL_TEXTURE22_ARB = 0x84D6; + public const int GL_TEXTURE23_ARB = 0x84D7; + public const int GL_TEXTURE24_ARB = 0x84D8; + public const int GL_TEXTURE25_ARB = 0x84D9; + public const int GL_TEXTURE26_ARB = 0x84DA; + public const int GL_TEXTURE27_ARB = 0x84DB; + public const int GL_TEXTURE28_ARB = 0x84DC; + public const int GL_TEXTURE29_ARB = 0x84DD; + public const int GL_TEXTURE30_ARB = 0x84DE; + public const int GL_TEXTURE31_ARB = 0x84DF; + public const int GL_ACTIVE_TEXTURE_ARB = 0x84E0; + public const int GL_CLIENT_ACTIVE_TEXTURE_ARB = 0x84E1; + public const int GL_MAX_TEXTURE_UNITS_ARB = 0x84E2; + public const int GL_DEPTH_STENCIL_MESA = 0x8750; + public const int GL_UNSIGNED_INT_24_8_MESA = 0x8751; + public const int GL_UNSIGNED_INT_8_24_REV_MESA = 0x8752; + public const int GL_UNSIGNED_SHORT_15_1_MESA = 0x8753; + public const int GL_UNSIGNED_SHORT_1_15_REV_MESA = 0x8754; + public const int GL_ALPHA_BLEND_EQUATION_ATI = 0x883D; + + + // glext.h + + public const int GL_FRAMEBUFFER_BINDING = 0x8CA6; + } +} diff --git a/src/Avalonia.OpenGL/GlDisplayType.cs b/src/Avalonia.OpenGL/GlDisplayType.cs new file mode 100644 index 00000000000..2e5178bc37a --- /dev/null +++ b/src/Avalonia.OpenGL/GlDisplayType.cs @@ -0,0 +1,8 @@ +namespace Avalonia.OpenGL +{ + public enum GlDisplayType + { + OpenGL2, + OpenGLES2 + } +} \ No newline at end of file diff --git a/src/Avalonia.OpenGL/GlInterface.cs b/src/Avalonia.OpenGL/GlInterface.cs new file mode 100644 index 00000000000..60dc5381d4c --- /dev/null +++ b/src/Avalonia.OpenGL/GlInterface.cs @@ -0,0 +1,48 @@ +using System; +using System.Runtime.InteropServices; + +namespace Avalonia.OpenGL +{ + public delegate IntPtr GlGetProcAddressDelegate(string procName); + + public class GlInterface : GlInterfaceBase + { + private readonly Func _getProcAddress; + + public GlInterface(Func getProcAddress) : base(getProcAddress) + { + _getProcAddress = getProcAddress; + } + + public IntPtr GetProcAddress(string proc) => _getProcAddress(proc, true); + + public T GetProcAddress(string proc) => Marshal.GetDelegateForFunctionPointer(GetProcAddress(proc)); + + // ReSharper disable UnassignedGetOnlyAutoProperty + + public delegate void GlClearStencil(int s); + [EntryPoint("glClearStencil")] + public GlClearStencil ClearStencil { get; } + + public delegate void GlClearColor(int r, int g, int b, int a); + [EntryPoint("glClearColor")] + public GlClearColor ClearColor { get; } + + public delegate void GlClear(int bits); + [EntryPoint("glClear")] + public GlClear Clear { get; } + + public delegate void GlViewport(int x, int y, int width, int height); + [EntryPoint("glViewport")] + public GlViewport Viewport { get; } + + [EntryPoint("glFlush")] + public Action Flush { get; } + + public delegate void GlGetIntegerv(int name, out int rv); + [EntryPoint("glGetIntegerv")] + public GlGetIntegerv GetIntegerv { get; } + + // ReSharper restore UnassignedGetOnlyAutoProperty + } +} diff --git a/src/Avalonia.OpenGL/GlInterfaceBase.cs b/src/Avalonia.OpenGL/GlInterfaceBase.cs new file mode 100644 index 00000000000..33191a65678 --- /dev/null +++ b/src/Avalonia.OpenGL/GlInterfaceBase.cs @@ -0,0 +1,28 @@ +using System; +using System.Reflection; +using System.Runtime.InteropServices; + +namespace Avalonia.OpenGL +{ + public class GlInterfaceBase + { + public GlInterfaceBase(Func getProcAddress) + { + foreach (var prop in this.GetType().GetProperties()) + { + var a = prop.GetCustomAttribute(); + if (a != null) + { + var fieldName = $"<{prop.Name}>k__BackingField"; + var field = prop.DeclaringType.GetField(fieldName, + BindingFlags.Instance | BindingFlags.NonPublic); + if (field == null) + throw new InvalidProgramException($"Expected property {prop.Name} to have {fieldName}"); + var proc = getProcAddress(a.EntryPoint, a.Optional); + if (proc != IntPtr.Zero) + field.SetValue(this, Marshal.GetDelegateForFunctionPointer(proc, prop.PropertyType)); + } + } + } + } +} diff --git a/src/Avalonia.OpenGL/IGlContext.cs b/src/Avalonia.OpenGL/IGlContext.cs new file mode 100644 index 00000000000..954567fe2e5 --- /dev/null +++ b/src/Avalonia.OpenGL/IGlContext.cs @@ -0,0 +1,8 @@ +namespace Avalonia.OpenGL +{ + public interface IGlContext + { + IGlDisplay Display { get; } + void MakeCurrent(IGlSurface surface); + } +} \ No newline at end of file diff --git a/src/Avalonia.OpenGL/IGlDisplay.cs b/src/Avalonia.OpenGL/IGlDisplay.cs new file mode 100644 index 00000000000..e7568bd5e7f --- /dev/null +++ b/src/Avalonia.OpenGL/IGlDisplay.cs @@ -0,0 +1,11 @@ +namespace Avalonia.OpenGL +{ + public interface IGlDisplay + { + GlDisplayType Type { get; } + GlInterface GlInterface { get; } + void ClearContext(); + int SampleCount { get; } + int StencilSize { get; } + } +} diff --git a/src/Avalonia.OpenGL/IGlPlatformSurface.cs b/src/Avalonia.OpenGL/IGlPlatformSurface.cs new file mode 100644 index 00000000000..22d36b44724 --- /dev/null +++ b/src/Avalonia.OpenGL/IGlPlatformSurface.cs @@ -0,0 +1,7 @@ +namespace Avalonia.OpenGL +{ + public interface IGlPlatformSurface + { + IGlPlatformSurfaceRenderTarget CreateGlRenderTarget(); + } +} diff --git a/src/Avalonia.OpenGL/IGlPlatformSurfaceRenderTarget.cs b/src/Avalonia.OpenGL/IGlPlatformSurfaceRenderTarget.cs new file mode 100644 index 00000000000..53da93315ca --- /dev/null +++ b/src/Avalonia.OpenGL/IGlPlatformSurfaceRenderTarget.cs @@ -0,0 +1,9 @@ +using System; + +namespace Avalonia.OpenGL +{ + public interface IGlPlatformSurfaceRenderTarget : IDisposable + { + IGlPlatformSurfaceRenderingSession BeginDraw(); + } +} \ No newline at end of file diff --git a/src/Avalonia.OpenGL/IGlPlatformSurfaceRenderingSession.cs b/src/Avalonia.OpenGL/IGlPlatformSurfaceRenderingSession.cs new file mode 100644 index 00000000000..22641d7b539 --- /dev/null +++ b/src/Avalonia.OpenGL/IGlPlatformSurfaceRenderingSession.cs @@ -0,0 +1,12 @@ +using System; + +namespace Avalonia.OpenGL +{ + public interface IGlPlatformSurfaceRenderingSession : IDisposable + { + IGlDisplay Display { get; } + // TODO: Change to PixelSize struct once https://github.com/AvaloniaUI/Avalonia/pull/1889 is merged + System.Drawing.Size PixelSize { get; } + double Scaling { get; } + } +} \ No newline at end of file diff --git a/src/Avalonia.OpenGL/IGlSurface.cs b/src/Avalonia.OpenGL/IGlSurface.cs new file mode 100644 index 00000000000..499d0a3c90a --- /dev/null +++ b/src/Avalonia.OpenGL/IGlSurface.cs @@ -0,0 +1,10 @@ +using System; + +namespace Avalonia.OpenGL +{ + public interface IGlSurface : IDisposable + { + IGlDisplay Display { get; } + void SwapBuffers(); + } +} \ No newline at end of file diff --git a/src/Avalonia.OpenGL/IWindowingPlatformGlFeature.cs b/src/Avalonia.OpenGL/IWindowingPlatformGlFeature.cs new file mode 100644 index 00000000000..2c4a8b64b37 --- /dev/null +++ b/src/Avalonia.OpenGL/IWindowingPlatformGlFeature.cs @@ -0,0 +1,7 @@ +namespace Avalonia.OpenGL +{ + public interface IWindowingPlatformGlFeature + { + IGlContext ImmediateContext { get; } + } +} diff --git a/src/Avalonia.OpenGL/OpenGlException.cs b/src/Avalonia.OpenGL/OpenGlException.cs new file mode 100644 index 00000000000..7ba539a2b2c --- /dev/null +++ b/src/Avalonia.OpenGL/OpenGlException.cs @@ -0,0 +1,12 @@ +using System; + +namespace Avalonia.OpenGL +{ + public class OpenGlException : Exception + { + public OpenGlException(string message) : base(message) + { + + } + } +} diff --git a/src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj b/src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj index ef043959adc..aa569a5e6a6 100644 --- a/src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj +++ b/src/Gtk/Avalonia.Gtk3/Avalonia.Gtk3.csproj @@ -9,6 +9,7 @@ + \ No newline at end of file diff --git a/src/Gtk/Avalonia.Gtk3/ClipboardImpl.cs b/src/Gtk/Avalonia.Gtk3/ClipboardImpl.cs index a3e7590cf5f..a8606737327 100644 --- a/src/Gtk/Avalonia.Gtk3/ClipboardImpl.cs +++ b/src/Gtk/Avalonia.Gtk3/ClipboardImpl.cs @@ -3,6 +3,7 @@ using System.Threading.Tasks; using Avalonia.Gtk3.Interop; using Avalonia.Input.Platform; +using Avalonia.Platform.Interop; namespace Avalonia.Gtk3 { diff --git a/src/Gtk/Avalonia.Gtk3/CursorFactory.cs b/src/Gtk/Avalonia.Gtk3/CursorFactory.cs index d6a3c1f2604..a28b1cbb1ae 100644 --- a/src/Gtk/Avalonia.Gtk3/CursorFactory.cs +++ b/src/Gtk/Avalonia.Gtk3/CursorFactory.cs @@ -3,6 +3,7 @@ using Avalonia.Gtk3.Interop; using Avalonia.Input; using Avalonia.Platform; +using Avalonia.Platform.Interop; using CursorType = Avalonia.Gtk3.GdkCursorType; namespace Avalonia.Gtk3 { diff --git a/src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs b/src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs index bbb6a01c052..e2e8a346769 100644 --- a/src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs +++ b/src/Gtk/Avalonia.Gtk3/Gtk3Platform.cs @@ -7,7 +7,9 @@ using Avalonia.Gtk3.Interop; using Avalonia.Input; using Avalonia.Input.Platform; +using Avalonia.OpenGL; using Avalonia.Platform; +using Avalonia.Platform.Interop; using Avalonia.Rendering; using Avalonia.Threading; @@ -22,8 +24,33 @@ public class Gtk3Platform : IWindowingPlatform, IPlatformSettings, IPlatformThre internal static string DisplayClassName; public static bool UseDeferredRendering = true; private static bool s_gtkInitialized; - public static void Initialize() + + static bool EnvOption(string option, bool def, bool? specified) + { + bool? Parse(string env) + { + var v = Environment.GetEnvironmentVariable("AVALONIA_GTK3_" + env); + if (v == null) + return null; + if (v.ToLowerInvariant() == "false" || v == "0") + return false; + return true; + } + + var overridden = Parse(option + "_OVERRIDE"); + if (overridden.HasValue) + return overridden.Value; + if (specified.HasValue) + return specified.Value; + var envValue = Parse(option); + return envValue ?? def; + } + + public static void Initialize(Gtk3PlatformOptions options) { + Resolver.Custom = options.CustomResolver; + UseDeferredRendering = EnvOption("USE_DEFERRED_RENDERING", true, options.UseDeferredRendering); + var useGpu = EnvOption("USE_GPU", false, options.UseGpuAcceleration); if (!s_gtkInitialized) { try @@ -55,7 +82,8 @@ public static void Initialize() .Bind().ToConstant(new RenderLoop()) .Bind().ToConstant(new DefaultRenderTimer(60)) .Bind().ToConstant(new PlatformIconLoader()); - + if (useGpu) + EglGlPlatformFeature.TryInitialize(); } public IWindowImpl CreateWindow() => new WindowImpl(); @@ -116,18 +144,24 @@ public void Signal(DispatcherPriority prio) public bool CurrentThreadIsLoopThread => s_tlsMarker; } + + public class Gtk3PlatformOptions + { + public bool? UseDeferredRendering { get; set; } + public bool? UseGpuAcceleration { get; set; } + public ICustomGtk3NativeLibraryResolver CustomResolver { get; set; } + } } namespace Avalonia { public static class Gtk3AppBuilderExtensions { - public static T UseGtk3(this AppBuilderBase builder, bool deferredRendering = true, ICustomGtk3NativeLibraryResolver resolver = null) + public static T UseGtk3(this AppBuilderBase builder, Gtk3PlatformOptions options = null) where T : AppBuilderBase, new() { - Resolver.Custom = resolver; - Gtk3Platform.UseDeferredRendering = deferredRendering; - return builder.UseWindowingSubsystem(Gtk3Platform.Initialize, "GTK3"); + return builder.UseWindowingSubsystem(() => Gtk3Platform.Initialize(options ?? new Gtk3PlatformOptions()), + "GTK3"); } } } diff --git a/src/Gtk/Avalonia.Gtk3/Interop/GException.cs b/src/Gtk/Avalonia.Gtk3/Interop/GException.cs index b0c171089ea..5ff6cbe8edc 100644 --- a/src/Gtk/Avalonia.Gtk3/Interop/GException.cs +++ b/src/Gtk/Avalonia.Gtk3/Interop/GException.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.InteropServices; +using Avalonia.Platform.Interop; namespace Avalonia.Gtk3.Interop { diff --git a/src/Gtk/Avalonia.Gtk3/Interop/Native.cs b/src/Gtk/Avalonia.Gtk3/Interop/Native.cs index 914d0feafca..98a73a98a99 100644 --- a/src/Gtk/Avalonia.Gtk3/Interop/Native.cs +++ b/src/Gtk/Avalonia.Gtk3/Interop/Native.cs @@ -2,6 +2,7 @@ using System; using System.Runtime.InteropServices; using Avalonia.Controls; +using Avalonia.Platform.Interop; using gdouble = System.Double; using gint = System.Int32; using gint16 = System.Int16; diff --git a/src/Gtk/Avalonia.Gtk3/Interop/Pixbuf.cs b/src/Gtk/Avalonia.Gtk3/Interop/Pixbuf.cs index 989a96a4f0b..322b9bdfaed 100644 --- a/src/Gtk/Avalonia.Gtk3/Interop/Pixbuf.cs +++ b/src/Gtk/Avalonia.Gtk3/Interop/Pixbuf.cs @@ -2,6 +2,7 @@ using System.IO; using System.Runtime.InteropServices; using Avalonia.Platform; +using Avalonia.Platform.Interop; namespace Avalonia.Gtk3.Interop { diff --git a/src/Gtk/Avalonia.Gtk3/Interop/Resolver.cs b/src/Gtk/Avalonia.Gtk3/Interop/Resolver.cs index 57c8ac7c3a7..c39cb9e394d 100644 --- a/src/Gtk/Avalonia.Gtk3/Interop/Resolver.cs +++ b/src/Gtk/Avalonia.Gtk3/Interop/Resolver.cs @@ -5,6 +5,7 @@ using System.Reflection; using System.Runtime.InteropServices; using Avalonia.Platform; +using Avalonia.Platform.Interop; namespace Avalonia.Gtk3.Interop { @@ -82,7 +83,7 @@ static string GetDllName(GtkDll dll) } } - static IntPtr LoadDll(IDynLoader loader, GtkDll dll) + static IntPtr LoadDll(IDynamicLibraryLoader loader, GtkDll dll) { var exceptions = new List(); @@ -118,7 +119,7 @@ static IntPtr LoadDll(IDynLoader loader, GtkDll dll) public static void Resolve(string basePath = null) { - var loader = Platform.Value == OperatingSystemType.WinNT ? (IDynLoader)new Win32Loader() : new UnixLoader(); + var loader = AvaloniaLocator.Current.GetService(); var dlls = Enum.GetValues(typeof(GtkDll)).Cast().ToDictionary(x => x, x => LoadDll(loader, x)); diff --git a/src/Gtk/Avalonia.Gtk3/Interop/Signal.cs b/src/Gtk/Avalonia.Gtk3/Interop/Signal.cs index bc555585517..8eaca931524 100644 --- a/src/Gtk/Avalonia.Gtk3/Interop/Signal.cs +++ b/src/Gtk/Avalonia.Gtk3/Interop/Signal.cs @@ -1,5 +1,6 @@ using System; using System.Runtime.InteropServices; +using Avalonia.Platform.Interop; namespace Avalonia.Gtk3.Interop { diff --git a/src/Gtk/Avalonia.Gtk3/SystemDialogs.cs b/src/Gtk/Avalonia.Gtk3/SystemDialogs.cs index d4bd878d539..5e6615f92d1 100644 --- a/src/Gtk/Avalonia.Gtk3/SystemDialogs.cs +++ b/src/Gtk/Avalonia.Gtk3/SystemDialogs.cs @@ -7,6 +7,7 @@ using Avalonia.Controls.Platform; using Avalonia.Gtk3.Interop; using Avalonia.Platform; +using Avalonia.Platform.Interop; namespace Avalonia.Gtk3 { diff --git a/src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs b/src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs index 67ddcf1e5f6..0ec4047086f 100644 --- a/src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs +++ b/src/Gtk/Avalonia.Gtk3/WindowBaseImpl.cs @@ -7,18 +7,21 @@ using Avalonia.Gtk3.Interop; using Avalonia.Input; using Avalonia.Input.Raw; +using Avalonia.OpenGL; using Avalonia.Platform; +using Avalonia.Platform.Interop; using Avalonia.Rendering; using Avalonia.Threading; namespace Avalonia.Gtk3 { - abstract class WindowBaseImpl : IWindowBaseImpl, IPlatformHandle + abstract class WindowBaseImpl : IWindowBaseImpl, IPlatformHandle, EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo { public readonly GtkWindow GtkWidget; private IInputRoot _inputRoot; private readonly GtkImContext _imContext; private readonly FramebufferManager _framebuffer; + private readonly EglGlPlatformSurface _egl; protected readonly List Disposables = new List(); private Size _lastSize; private Point _lastPosition; @@ -36,7 +39,13 @@ public WindowBaseImpl(GtkWindow gtkWidget) { GtkWidget = gtkWidget; - _framebuffer = new FramebufferManager(this); + + var glf = AvaloniaLocator.Current.GetService() as EglGlPlatformFeature; + if (glf != null) + _egl = new EglGlPlatformSurface((EglDisplay)glf.Display, glf.DeferredContext, this); + else + _framebuffer = new FramebufferManager(this); + _imContext = Native.GtkImMulticontextNew(); Disposables.Add(_imContext); Native.GtkWidgetSetEvents(gtkWidget, 0xFFFFFE); @@ -57,12 +66,15 @@ public WindowBaseImpl(GtkWindow gtkWidget) Native.GtkWidgetRealize(gtkWidget); GdkWindowHandle = this.Handle.Handle; _lastSize = ClientSize; - if (Gtk3Platform.UseDeferredRendering) + + if (_egl != null) + Native.GtkWidgetSetDoubleBuffered(gtkWidget, false); + else if (Gtk3Platform.UseDeferredRendering) { Native.GtkWidgetSetDoubleBuffered(gtkWidget, false); _gcHandle = GCHandle.Alloc(this); - _tickCallback = Native.GtkWidgetAddTickCallback(GtkWidget, PinnedStaticCallback, GCHandle.ToIntPtr(_gcHandle), IntPtr.Zero); - + _tickCallback = Native.GtkWidgetAddTickCallback(GtkWidget, PinnedStaticCallback, + GCHandle.ToIntPtr(_gcHandle), IntPtr.Zero); } } @@ -488,7 +500,7 @@ public Point Position } IntPtr IPlatformHandle.Handle => Native.GetNativeGdkWindowHandle(Native.GtkWidgetGetWindow(GtkWidget)); - public IEnumerable Surfaces => new object[] {Handle, _framebuffer}; + public IEnumerable Surfaces => new object[] {Handle, _egl, _framebuffer}; public IRenderer CreateRenderer(IRenderRoot root) { @@ -497,5 +509,17 @@ public IRenderer CreateRenderer(IRenderRoot root) ? (IRenderer) new DeferredRenderer(root, loop) : new ImmediateRenderer(root); } + + System.Drawing.Size EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo.PixelSize + { + get + { + var cs = ClientSize; + return new System.Drawing.Size((int)Math.Max(1, LastKnownScaleFactor * cs.Width), + (int)Math.Max(1, LastKnownScaleFactor * ClientSize.Height)); + } + } + double EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo.Scaling => LastKnownScaleFactor; + IntPtr EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo.Handle => Handle.Handle; } } diff --git a/src/Gtk/Avalonia.Gtk3/WindowImpl.cs b/src/Gtk/Avalonia.Gtk3/WindowImpl.cs index a0b754c2294..34950ca8b8b 100644 --- a/src/Gtk/Avalonia.Gtk3/WindowImpl.cs +++ b/src/Gtk/Avalonia.Gtk3/WindowImpl.cs @@ -2,6 +2,7 @@ using Avalonia.Controls; using Avalonia.Gtk3.Interop; using Avalonia.Platform; +using Avalonia.Platform.Interop; namespace Avalonia.Gtk3 { diff --git a/src/Gtk/Avalonia.Gtk3/Interop/DynLoader.cs b/src/Shared/PlatformSupport/DynLoader.cs similarity index 73% rename from src/Gtk/Avalonia.Gtk3/Interop/DynLoader.cs rename to src/Shared/PlatformSupport/DynLoader.cs index 112e00c879d..5884558baaa 100644 --- a/src/Gtk/Avalonia.Gtk3/Interop/DynLoader.cs +++ b/src/Shared/PlatformSupport/DynLoader.cs @@ -1,22 +1,12 @@ -using System; +using System; using System.Runtime.InteropServices; +using Avalonia.Platform; +using Avalonia.Platform.Interop; -/* - * Source code imported from https://github.com/kekekeks/evhttp-sharp - * Source is provided under MIT license for Avalonia project and derived works - */ - - -namespace Avalonia.Gtk3.Interop +namespace Avalonia.Shared.PlatformSupport { - internal interface IDynLoader - { - IntPtr LoadLibrary(string dll); - IntPtr GetProcAddress(IntPtr dll, string proc, bool optional); - - } - - class UnixLoader : IDynLoader +#if !__IOS__ + class UnixLoader : IDynamicLibraryLoader { // ReSharper disable InconsistentNaming static class LinuxImports @@ -37,6 +27,7 @@ public static void Init() DlError = dlerror; } } + static class OsXImports { @@ -86,7 +77,7 @@ public IntPtr LoadLibrary(string dll) { var handle = DlOpen(dll, 1); if (handle == IntPtr.Zero) - throw new NativeException(DlErrorString()); + throw new DynamicLibraryLoaderException(DlErrorString()); return handle; } @@ -94,12 +85,12 @@ public IntPtr GetProcAddress(IntPtr dll, string proc, bool optional) { var ptr = DlSym(dll, proc); if (ptr == IntPtr.Zero && !optional) - throw new NativeException(DlErrorString()); + throw new DynamicLibraryLoaderException(DlErrorString()); return ptr; } } - internal class Win32Loader : IDynLoader + internal class Win32Loader : IDynamicLibraryLoader { [DllImport("kernel32", CharSet = CharSet.Ansi, ExactSpelling = true, SetLastError = true)] private static extern IntPtr GetProcAddress(IntPtr hModule, string procName); @@ -107,22 +98,37 @@ internal class Win32Loader : IDynLoader [DllImport("kernel32", EntryPoint = "LoadLibraryW", SetLastError = true, CharSet = CharSet.Unicode)] private static extern IntPtr LoadLibrary(string lpszLib); - IntPtr IDynLoader.LoadLibrary(string dll) + IntPtr IDynamicLibraryLoader.LoadLibrary(string dll) { var handle = LoadLibrary(dll); if (handle != IntPtr.Zero) return handle; var err = Marshal.GetLastWin32Error(); - throw new NativeException("Error loading " + dll + " error " + err); + throw new DynamicLibraryLoaderException("Error loading " + dll + " error " + err); } - IntPtr IDynLoader.GetProcAddress(IntPtr dll, string proc, bool optional) + IntPtr IDynamicLibraryLoader.GetProcAddress(IntPtr dll, string proc, bool optional) { var ptr = GetProcAddress(dll, proc); if (ptr == IntPtr.Zero && !optional) - throw new NativeException("Error " + Marshal.GetLastWin32Error()); + throw new DynamicLibraryLoaderException("Error " + Marshal.GetLastWin32Error()); return ptr; } } + +#else + internal class IOSLoader : IDynamicLibraryLoader + { + IntPtr IDynamicLibraryLoader.LoadLibrary(string dll) + { + throw new PlatformNotSupportedException(); + } + + IntPtr IDynamicLibraryLoader.GetProcAddress(IntPtr dll, string proc, bool optional) + { + throw new PlatformNotSupportedException(); + } + } +#endif } diff --git a/src/Shared/PlatformSupport/PlatformSupport.projitems b/src/Shared/PlatformSupport/PlatformSupport.projitems index a9b6a8fa2a6..34515a09127 100644 --- a/src/Shared/PlatformSupport/PlatformSupport.projitems +++ b/src/Shared/PlatformSupport/PlatformSupport.projitems @@ -10,6 +10,7 @@ + diff --git a/src/Shared/PlatformSupport/StandardRuntimePlatformServices.cs b/src/Shared/PlatformSupport/StandardRuntimePlatformServices.cs index 9ccf097ffdd..b34b8f7f5f7 100644 --- a/src/Shared/PlatformSupport/StandardRuntimePlatformServices.cs +++ b/src/Shared/PlatformSupport/StandardRuntimePlatformServices.cs @@ -1,5 +1,7 @@ using System.Reflection; +using System.Runtime.InteropServices; using Avalonia.Platform; +using Avalonia.Platform.Interop; namespace Avalonia.Shared.PlatformSupport { @@ -7,9 +9,19 @@ static class StandardRuntimePlatformServices { public static void Register(Assembly assembly = null) { + var standardPlatform = new StandardRuntimePlatform(); AvaloniaLocator.CurrentMutable - .Bind().ToSingleton() - .Bind().ToConstant(new AssetLoader(assembly)); + .Bind().ToConstant(standardPlatform) + .Bind().ToConstant(new AssetLoader(assembly)) + .Bind().ToConstant( +#if __IOS__ + new IOSLoader() +#else + RuntimeInformation.IsOSPlatform(OSPlatform.Windows) + ? (IDynamicLibraryLoader)new Win32Loader() + : new UnixLoader() +#endif + ); } } } diff --git a/src/Skia/Avalonia.Skia/Avalonia.Skia.csproj b/src/Skia/Avalonia.Skia/Avalonia.Skia.csproj index 03618e00f59..d125ca0be49 100644 --- a/src/Skia/Avalonia.Skia/Avalonia.Skia.csproj +++ b/src/Skia/Avalonia.Skia/Avalonia.Skia.csproj @@ -12,6 +12,7 @@ + diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs index 685987ae800..f43bddd4d57 100644 --- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs +++ b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs @@ -29,6 +29,7 @@ public class DrawingContextImpl : IDrawingContextImpl private double _currentOpacity = 1.0f; private readonly bool _canTextUseLcdRendering; private Matrix _currentTransform; + private GRContext _grContext; /// /// Context create info. @@ -54,6 +55,11 @@ public struct CreateInfo /// Render text without Lcd rendering. /// public bool DisableTextLcdRendering; + + /// + /// GPU-accelerated context (optional) + /// + public GRContext GrContext; } /// @@ -67,7 +73,8 @@ public DrawingContextImpl(CreateInfo createInfo, params IDisposable[] disposable _visualBrushRenderer = createInfo.VisualBrushRenderer; _disposables = disposables; _canTextUseLcdRendering = !createInfo.DisableTextLcdRendering; - + _grContext = createInfo.GrContext; + Canvas = createInfo.Canvas; if (Canvas == null) @@ -615,7 +622,8 @@ private SurfaceRenderTarget CreateRenderTarget(int width, int height, Vector dpi Height = height, Dpi = dpi, Format = format, - DisableTextLcdRendering = !_canTextUseLcdRendering + DisableTextLcdRendering = !_canTextUseLcdRendering, + GrContext = _grContext }; return new SurfaceRenderTarget(createInfo); diff --git a/src/Skia/Avalonia.Skia/GlRenderTarget.cs b/src/Skia/Avalonia.Skia/GlRenderTarget.cs new file mode 100644 index 00000000000..0435e1060a0 --- /dev/null +++ b/src/Skia/Avalonia.Skia/GlRenderTarget.cs @@ -0,0 +1,69 @@ +using System; +using System.Reactive.Disposables; +using Avalonia.OpenGL; +using Avalonia.Platform; +using Avalonia.Rendering; +using SkiaSharp; +using static Avalonia.OpenGL.GlConsts; + +namespace Avalonia.Skia +{ + public class GlRenderTarget : IRenderTarget + { + private readonly GRContext _grContext; + private IGlPlatformSurfaceRenderTarget _surface; + + public GlRenderTarget(GRContext grContext, IGlPlatformSurface glSurface) + { + _grContext = grContext; + _surface = glSurface.CreateGlRenderTarget(); + } + + public void Dispose() => _surface.Dispose(); + + public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer) + { + var session = _surface.BeginDraw(); + var disp = session.Display; + var gl = disp.GlInterface; + gl.GetIntegerv(GL_FRAMEBUFFER_BINDING, out var fb); + + var size = session.PixelSize; + var scaling = session.Scaling; + + GRBackendRenderTargetDesc desc = new GRBackendRenderTargetDesc + { + Width = size.Width, + Height = size.Height, + SampleCount = disp.SampleCount, + StencilBits = disp.StencilSize, + Config = GRPixelConfig.Rgba8888, + Origin=GRSurfaceOrigin.BottomLeft, + RenderTargetHandle = new IntPtr(fb) + }; + + gl.Viewport(0, 0, desc.Width, desc.Height); + gl.ClearStencil(0); + gl.ClearColor(0, 0, 0, 0); + gl.Clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + + var surface = SKSurface.Create(_grContext, desc); + + var nfo = new DrawingContextImpl.CreateInfo + { + GrContext = _grContext, + Canvas = surface.Canvas, + Dpi = SkiaPlatform.DefaultDpi * scaling, + VisualBrushRenderer = visualBrushRenderer, + DisableTextLcdRendering = true + }; + + return new DrawingContextImpl(nfo, Disposable.Create(() => + { + surface.Canvas.Flush(); + surface.Dispose(); + session.Dispose(); + })); + } + } +} diff --git a/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs b/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs index d4e6403dc94..80e2608dbe5 100644 --- a/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs +++ b/src/Skia/Avalonia.Skia/PlatformRenderInterface.cs @@ -6,7 +6,9 @@ using System.IO; using Avalonia.Controls.Platform.Surfaces; using Avalonia.Media; +using Avalonia.OpenGL; using Avalonia.Platform; +using SkiaSharp; namespace Avalonia.Skia { @@ -15,6 +17,22 @@ namespace Avalonia.Skia /// public class PlatformRenderInterface : IPlatformRenderInterface { + private GRContext GrContext { get; } + + public PlatformRenderInterface() + { + var gl = AvaloniaLocator.Current.GetService(); + if (gl != null) + { + var display = gl.ImmediateContext.Display; + var iface = display.Type == GlDisplayType.OpenGL2 + ? GRGlInterface.AssembleGlInterface((_, proc) => display.GlInterface.GetProcAddress(proc)) + : GRGlInterface.AssembleGlesInterface((_, proc) => display.GlInterface.GetProcAddress(proc)); + gl.ImmediateContext.MakeCurrent(null); + GrContext = GRContext.Create(GRBackend.OpenGL, iface); + } + } + /// public IFormattedTextImpl CreateFormattedText( string text, @@ -78,7 +96,8 @@ public IRenderTargetBitmapImpl CreateRenderTargetBitmap( Width = width, Height = height, Dpi = dpi, - DisableTextLcdRendering = false + DisableTextLcdRendering = false, + GrContext = GrContext }; return new SurfaceRenderTarget(createInfo); @@ -89,6 +108,10 @@ public virtual IRenderTarget CreateRenderTarget(IEnumerable surfaces) { foreach (var surface in surfaces) { + if (surface is IGlPlatformSurface glSurface && GrContext != null) + { + return new GlRenderTarget(GrContext, glSurface); + } if (surface is IFramebufferPlatformSurface framebufferSurface) { return new FramebufferRenderTarget(framebufferSurface); @@ -105,4 +128,4 @@ public IWriteableBitmapImpl CreateWriteableBitmap(int width, int height, PixelFo return new WriteableBitmapImpl(width, height, format); } } -} \ No newline at end of file +} diff --git a/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs b/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs index 88200dcfbe8..914dc7d05a1 100644 --- a/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs +++ b/src/Skia/Avalonia.Skia/SurfaceRenderTarget.cs @@ -19,6 +19,7 @@ public class SurfaceRenderTarget : IRenderTargetBitmapImpl, IDrawableBitmapImpl private readonly SKSurface _surface; private readonly SKCanvas _canvas; private readonly bool _disableLcdRendering; + private readonly GRContext _grContext; /// /// Create new surface render target. @@ -30,8 +31,8 @@ public SurfaceRenderTarget(CreateInfo createInfo) PixelHeight = createInfo.Height; _dpi = createInfo.Dpi; _disableLcdRendering = createInfo.DisableTextLcdRendering; - - _surface = CreateSurface(PixelWidth, PixelHeight, createInfo.Format); + _grContext = createInfo.GrContext; + _surface = CreateSurface(createInfo.GrContext, PixelWidth, PixelHeight, createInfo.Format); _canvas = _surface?.Canvas; @@ -48,10 +49,11 @@ public SurfaceRenderTarget(CreateInfo createInfo) /// Height. /// Format. /// - private static SKSurface CreateSurface(int width, int height, PixelFormat? format) + private static SKSurface CreateSurface(GRContext gpu, int width, int height, PixelFormat? format) { var imageInfo = MakeImageInfo(width, height, format); - + if (gpu != null) + return SKSurface.Create(gpu, false, imageInfo); return SKSurface.Create(imageInfo); } @@ -73,7 +75,8 @@ public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrush Canvas = _canvas, Dpi = _dpi, VisualBrushRenderer = visualBrushRenderer, - DisableTextLcdRendering = _disableLcdRendering + DisableTextLcdRendering = _disableLcdRendering, + GrContext = _grContext }; return new DrawingContextImpl(createInfo); @@ -164,6 +167,11 @@ public struct CreateInfo /// Render text without Lcd rendering. /// public bool DisableTextLcdRendering; + + /// + /// GPU-accelerated context (optional) + /// + public GRContext GrContext; } } -} \ No newline at end of file +} diff --git a/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj b/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj index 5f26e4ad3e1..1fb566dad02 100644 --- a/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj +++ b/src/Windows/Avalonia.Win32/Avalonia.Win32.csproj @@ -10,6 +10,7 @@ + diff --git a/src/Windows/Avalonia.Win32/Win32GlManager.cs b/src/Windows/Avalonia.Win32/Win32GlManager.cs new file mode 100644 index 00000000000..585e68056b9 --- /dev/null +++ b/src/Windows/Avalonia.Win32/Win32GlManager.cs @@ -0,0 +1,26 @@ +using Avalonia.OpenGL; + +namespace Avalonia.Win32 +{ + static class Win32GlManager + { + /// This property is initialized if drawing platform requests OpenGL support + public static EglGlPlatformFeature EglFeature { get; private set; } + + private static bool s_attemptedToInitialize; + + public static void Initialize() + { + AvaloniaLocator.CurrentMutable.Bind().ToFunc(() => + { + if (!s_attemptedToInitialize) + { + EglFeature = EglGlPlatformFeature.TryCreate(); + s_attemptedToInitialize = true; + } + + return EglFeature; + }); + } + } +} diff --git a/src/Windows/Avalonia.Win32/Win32Platform.cs b/src/Windows/Avalonia.Win32/Win32Platform.cs index ef2dfd3c1ad..89943b5b0a0 100644 --- a/src/Windows/Avalonia.Win32/Win32Platform.cs +++ b/src/Windows/Avalonia.Win32/Win32Platform.cs @@ -88,7 +88,7 @@ public static void Initialize(bool deferredRendering = true) .Bind().ToSingleton() .Bind().ToConstant(s_instance) .Bind().ToConstant(s_instance); - + Win32GlManager.Initialize(); UseDeferredRendering = deferredRendering; _uiThread = UnmanagedMethods.GetCurrentThreadId(); diff --git a/src/Windows/Avalonia.Win32/WindowImpl.cs b/src/Windows/Avalonia.Win32/WindowImpl.cs index 292d8a81385..65580ff9c85 100644 --- a/src/Windows/Avalonia.Win32/WindowImpl.cs +++ b/src/Windows/Avalonia.Win32/WindowImpl.cs @@ -10,6 +10,7 @@ using Avalonia.Controls; using Avalonia.Input; using Avalonia.Input.Raw; +using Avalonia.OpenGL; using Avalonia.Platform; using Avalonia.Rendering; using Avalonia.Win32.Input; @@ -18,7 +19,7 @@ namespace Avalonia.Win32 { - public class WindowImpl : IWindowImpl + public class WindowImpl : IWindowImpl, EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo { private static readonly List s_instances = new List(); @@ -37,6 +38,7 @@ public class WindowImpl : IWindowImpl private WindowState _showWindowState; private WindowState _lastWindowState; private FramebufferManager _framebuffer; + private IGlPlatformSurface _gl; private OleDropTarget _dropTarget; private Size _minSize; private Size _maxSize; @@ -58,6 +60,10 @@ public WindowImpl() #endif CreateWindow(); _framebuffer = new FramebufferManager(_hwnd); + if (Win32GlManager.EglFeature != null) + _gl = new EglGlPlatformSurface((EglDisplay)Win32GlManager.EglFeature.Display, + Win32GlManager.EglFeature.DeferredContext, this); + s_instances.Add(this); } @@ -211,7 +217,7 @@ public WindowState WindowState public IEnumerable Surfaces => new object[] { - Handle, _framebuffer + Handle, _gl, _framebuffer }; public void Activate() @@ -921,5 +927,18 @@ public void SetTopmost(bool value) _topmost = value; } + + System.Drawing.Size EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo.PixelSize + { + get + { + RECT rect; + GetClientRect(_hwnd, out rect); + return new System.Drawing.Size( + Math.Max(1, rect.right - rect.left), + Math.Max(1, rect.bottom - rect.top)); + } + } + IntPtr EglGlPlatformSurface.IEglWindowGlPlatformSurfaceInfo.Handle => Handle.Handle; } }