[EGL] Added support for desktop GL rendering
authorthefiddler <stapostol@gmail.com>
Wed, 25 Jun 2014 07:35:20 +0000 (09:35 +0200)
committerthefiddler <stapostol@gmail.com>
Wed, 16 Jul 2014 12:28:27 +0000 (14:28 +0200)
On Linux, EGL can be used to initialize a desktop GL context.
This is especially true on KMS, Wayland and Mir.

Source/OpenTK/Platform/Egl/Egl.cs
Source/OpenTK/Platform/Egl/EglContext.cs
Source/OpenTK/Platform/Egl/EglUnixContext.cs

index c4fa383..9d539da 100644 (file)
@@ -41,6 +41,13 @@ namespace OpenTK.Platform.Egl
     using EGLSurface = IntPtr;
     using EGLClientBuffer = IntPtr;
 
+    enum RenderApi
+    {
+        ES = Egl.OPENGL_ES_API,
+        GL = Egl.OPENGL_API,
+        VG = Egl.OPENVG_API
+    }
+
     [Flags]
     enum RenderableFlags
     {
@@ -229,7 +236,7 @@ namespace OpenTK.Platform.Egl
 
         [DllImportAttribute("libEGL.dll", EntryPoint = "eglBindAPI")]
         [return: MarshalAsAttribute(UnmanagedType.I1)]
-        public static extern bool BindAPI(int api);
+        public static extern bool BindAPI(RenderApi api);
 
         [DllImportAttribute("libEGL.dll", EntryPoint = "eglQueryAPI")]
         public static extern int QueryAPI();
index a6f961e..ee9d493 100644 (file)
@@ -60,7 +60,12 @@ namespace OpenTK.Platform.Egl
             // Select an EGLConfig that matches the desired mode. We cannot use the 'mode'
             // parameter directly, since it may have originated on a different system (e.g. GLX)
             // and it may not support the desired renderer.
-            Renderable = major > 1 ? RenderableFlags.ES2 : RenderableFlags.ES;
+
+            Renderable = RenderableFlags.GL;
+            if ((flags & GraphicsContextFlags.Embedded) != 0)
+            {
+                Renderable = major > 1 ? RenderableFlags.ES2 : RenderableFlags.ES;
+            }
             Mode = new EglGraphicsMode().SelectGraphicsMode(window,
                 mode.ColorFormat, mode.Depth, mode.Stencil, mode.Samples,
                 mode.AccumulatorFormat, mode.Buffers, mode.Stereo,
@@ -76,6 +81,13 @@ namespace OpenTK.Platform.Egl
             HandleAsEGLContext = Egl.CreateContext(window.Display, config, shared != null ? shared.HandleAsEGLContext : IntPtr.Zero, attrib_list);
 
             MakeCurrent(window);
+
+            RenderApi api = (Renderable & RenderableFlags.GL) != 0 ? RenderApi.GL : RenderApi.ES;
+            Debug.Print("[EGL] Binding rendering API {0}.", api);
+            if (!Egl.BindAPI(api))
+            {
+                Debug.Print("[EGL] Failed to bind rendering API. Error: {0}", Egl.GetError());
+            }
         }
 
         public EglContext(ContextHandle handle, EglWindowInfo window, IGraphicsContext sharedContext,
index 5880138..5ceca2d 100644 (file)
 #endregion
 
 using System;
+using System.Diagnostics;
 using OpenTK.Graphics;
 
 namespace OpenTK.Platform.Egl
 {
     class EglUnixContext : EglContext
     {
-        readonly IntPtr ES1 = OpenTK.Platform.X11.DL.Open("libGLESv1_CM", X11.DLOpenFlags.Lazy);
-        readonly IntPtr ES2 = OpenTK.Platform.X11.DL.Open("libGLESv2", X11.DLOpenFlags.Lazy);
+        IntPtr GL = OpenTK.Platform.X11.DL.Open("libGL", X11.DLOpenFlags.Lazy);
+        IntPtr ES1 = OpenTK.Platform.X11.DL.Open("libGLESv1_CM", X11.DLOpenFlags.Lazy);
+        IntPtr ES2 = OpenTK.Platform.X11.DL.Open("libGLESv2", X11.DLOpenFlags.Lazy);
 
         public EglUnixContext(GraphicsMode mode, EglWindowInfo window, IGraphicsContext sharedContext,
             int major, int minor, GraphicsContextFlags flags)
@@ -59,11 +61,19 @@ namespace OpenTK.Platform.Egl
             {
                 return X11.DL.Symbol(ES2, function);
             }
+            else if ((renderable & RenderableFlags.GL) != 0 && GL != IntPtr.Zero)
+            {
+                return X11.DL.Symbol(GL, function);
+            }
             return IntPtr.Zero;
         }
 
         protected override void Dispose(bool manual)
         {
+            if (GL != IntPtr.Zero)
+            {
+                X11.DL.Close(GL);
+            }
             if (ES1 != IntPtr.Zero)
             {
                 X11.DL.Close(ES1);
@@ -73,7 +83,27 @@ namespace OpenTK.Platform.Egl
                 X11.DL.Close(ES2);
             }
 
+            GL = ES1 = ES2 = IntPtr.Zero;
+
             base.Dispose(manual);
         }
+
+        public override void LoadAll()
+        {
+            // Modern unices can use EGL to create
+            // both GL and ES contexts, so we need
+            // to load all entry points. This is
+            // especially true on KMS, Wayland and Mir.
+
+            Stopwatch time = Stopwatch.StartNew();
+
+            new OpenTK.Graphics.OpenGL.GL().LoadEntryPoints();
+            new OpenTK.Graphics.OpenGL4.GL().LoadEntryPoints();
+            new OpenTK.Graphics.ES11.GL().LoadEntryPoints();
+            new OpenTK.Graphics.ES20.GL().LoadEntryPoints();
+            new OpenTK.Graphics.ES30.GL().LoadEntryPoints();
+
+            Debug.Print("Bindings loaded in {0} ms.", time.Elapsed.TotalMilliseconds);
+        }
     }
 }