diff --git a/samples/ControlCatalog/Pages/OpenGlPage.xaml b/samples/ControlCatalog/Pages/OpenGlPage.xaml index afd8001263..0eb09004ba 100644 --- a/samples/ControlCatalog/Pages/OpenGlPage.xaml +++ b/samples/ControlCatalog/Pages/OpenGlPage.xaml @@ -4,6 +4,9 @@ xmlns:pages="clr-namespace:ControlCatalog.Pages"> + + + Yaw diff --git a/samples/ControlCatalog/Pages/OpenGlPage.xaml.cs b/samples/ControlCatalog/Pages/OpenGlPage.xaml.cs index eb75d905a6..12a3c17fe3 100644 --- a/samples/ControlCatalog/Pages/OpenGlPage.xaml.cs +++ b/samples/ControlCatalog/Pages/OpenGlPage.xaml.cs @@ -66,6 +66,16 @@ namespace ControlCatalog.Pages set => SetAndRaise(DiscoProperty, ref _disco, value); } + private string _info; + + public static readonly DirectProperty InfoProperty = + AvaloniaProperty.RegisterDirect("Info", o => o.Info, (o, v) => o.Info = v); + + public string Info + { + get => _info; + private set => SetAndRaise(InfoProperty, ref _info, value); + } static OpenGlPageControl() { @@ -79,13 +89,33 @@ namespace ControlCatalog.Pages private int _indexBufferObject; private int _vertexArrayObject; - private string WithVersion(string shader) => - $"#version {(DisplayType == GlDisplayType.OpenGl ? 120 : 100)}\n" + shader; + private string GetShader(bool fragment, string shader) + { + var version = (DisplayType == GlDisplayType.OpenGl ? + RuntimeInformation.IsOSPlatform(OSPlatform.OSX) ? 150 : 120 : + 100); + var data = "#version " + version + "\n"; + if (DisplayType == GlDisplayType.OpenGLES) + data += "precision mediump float\n"; + if (version >= 150) + { + shader = shader.Replace("attribute", "in"); + if (fragment) + shader = shader + .Replace("varying", "in") + .Replace("//DECLAREGLFRAG", "out vec4 outFragColor;") + .Replace("gl_FragColor", "outFragColor"); + else + shader = shader.Replace("varying", "out"); + } + + data += shader; + + return data; + } - private string WithVersionAndPrecision(string shader, string precision) => - WithVersion(DisplayType == GlDisplayType.OpenGLES ? $"precision {precision};\n{shader}" : shader); - private string VertexShaderSource => WithVersionAndPrecision(@" + private string VertexShaderSource => GetShader(false, @" attribute vec3 aPos; attribute vec3 aNormal; uniform mat4 uModel; @@ -113,9 +143,9 @@ namespace ControlCatalog.Pages VecPos = aPos; Normal = normalize(vec3(uModel * vec4(aNormal, 1.0))); } -", "mediump float"); +"); - private string FragmentShaderSource => WithVersionAndPrecision(@" + private string FragmentShaderSource => GetShader(true, @" varying vec3 FragPos; varying vec3 VecPos; varying vec3 Normal; @@ -123,6 +153,7 @@ namespace ControlCatalog.Pages uniform float uMinY; uniform float uTime; uniform float uDisco; + //DECLAREGLFRAG void main() { @@ -154,7 +185,7 @@ namespace ControlCatalog.Pages gl_FragColor = vec4(result, 1.0); } -", "mediump float"); +"); [StructLayout(LayoutKind.Sequential, Pack = 4)] private struct Vertex @@ -224,6 +255,9 @@ namespace ControlCatalog.Pages protected unsafe override void OnOpenGlInit(GlInterface GL, int fb) { CheckError(GL); + + Info = $"Renderer: {GL.GetString(GL_RENDERER)} Version: {GL.GetString(GL_VERSION)}"; + // Load the source of the vertex shader and compile it. _vertexShader = GL.CreateShader(GL_VERTEX_SHADER); Console.WriteLine(GL.CompileShaderAndGetError(_vertexShader, VertexShaderSource)); @@ -247,6 +281,7 @@ namespace ControlCatalog.Pages _vertexBufferObject = GL.GenBuffer(); // Bind the VBO and copy the vertex data into it. GL.BindBuffer(GL_ARRAY_BUFFER, _vertexBufferObject); + CheckError(GL); var vertexSize = Marshal.SizeOf(); fixed (void* pdata = _points) GL.BufferData(GL_ARRAY_BUFFER, new IntPtr(_points.Length * vertexSize), @@ -254,13 +289,14 @@ namespace ControlCatalog.Pages _indexBufferObject = GL.GenBuffer(); GL.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBufferObject); + CheckError(GL); fixed (void* pdata = _indices) GL.BufferData(GL_ELEMENT_ARRAY_BUFFER, new IntPtr(_indices.Length * sizeof(ushort)), new IntPtr(pdata), GL_STATIC_DRAW); - + CheckError(GL); _vertexArrayObject = GL.GenVertexArray(); GL.BindVertexArray(_vertexArrayObject); - + CheckError(GL); GL.VertexAttribPointer(positionLocation, 3, GL_FLOAT, 0, vertexSize, IntPtr.Zero); GL.VertexAttribPointer(normalLocation, 3, GL_FLOAT, @@ -300,6 +336,7 @@ namespace ControlCatalog.Pages GL.BindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBufferObject); GL.BindVertexArray(_vertexArrayObject); GL.UseProgram(_shaderProgram); + CheckError(GL); var projection = Matrix4x4.CreatePerspectiveFieldOfView((float)(Math.PI / 4), (float)(Bounds.Width / Bounds.Height), 0.01f, 1000); @@ -321,6 +358,7 @@ namespace ControlCatalog.Pages GL.Uniform1f(minYLoc, _minY); GL.Uniform1f(timeLoc, (float)St.Elapsed.TotalSeconds); GL.Uniform1f(discoLoc, _disco); + CheckError(GL); GL.DrawElements(GL_TRIANGLES, _indices.Length, GL_UNSIGNED_SHORT, IntPtr.Zero); CheckError(GL); diff --git a/src/Avalonia.Native/GlPlatformFeature.cs b/src/Avalonia.Native/GlPlatformFeature.cs index b86404d15b..83c741658a 100644 --- a/src/Avalonia.Native/GlPlatformFeature.cs +++ b/src/Avalonia.Native/GlPlatformFeature.cs @@ -8,8 +8,11 @@ namespace Avalonia.Native { class GlPlatformFeature : IWindowingPlatformGlFeature { + private readonly IAvnGlDisplay _display; + public GlPlatformFeature(IAvnGlDisplay display) { + _display = display; var immediate = display.CreateContext(null); var deferred = display.CreateContext(immediate); GlDisplay = new GlDisplay(display, immediate.SampleCount, immediate.StencilSize); @@ -22,7 +25,9 @@ namespace Avalonia.Native internal GlContext DeferredContext { get; } internal GlDisplay GlDisplay; public IGlDisplay Display => GlDisplay; - public IGlContext CreateContext() => new GlContext(GlDisplay, ((GlContext)ImmediateContext).Context); + + public IGlContext CreateContext() => new GlContext(GlDisplay, + _display.CreateContext(((GlContext)ImmediateContext).Context)); } class GlDisplay : IGlDisplay diff --git a/src/Avalonia.OpenGL/GlInterfaceBase.cs b/src/Avalonia.OpenGL/GlInterfaceBase.cs index 445777b065..7715438389 100644 --- a/src/Avalonia.OpenGL/GlInterfaceBase.cs +++ b/src/Avalonia.OpenGL/GlInterfaceBase.cs @@ -30,7 +30,8 @@ namespace Avalonia.OpenGL foreach (var ep in a.EntryPoints) { proc = getProcAddress(ep, true); - + if(proc != IntPtr.Zero) + break; } if (proc == IntPtr.Zero && !a.Optional)