[EGL] Added support for desktop GL rendering

On Linux, EGL can be used to initialize a desktop GL context.
This is especially true on KMS, Wayland and Mir.
This commit is contained in:
thefiddler 2014-06-25 09:35:20 +02:00
parent 5da5ac0fa7
commit d8adf92feb
3 changed files with 53 additions and 4 deletions

View file

@ -41,6 +41,13 @@ namespace OpenTK.Platform.Egl
using EGLSurface = IntPtr; using EGLSurface = IntPtr;
using EGLClientBuffer = IntPtr; using EGLClientBuffer = IntPtr;
enum RenderApi
{
ES = Egl.OPENGL_ES_API,
GL = Egl.OPENGL_API,
VG = Egl.OPENVG_API
}
[Flags] [Flags]
enum RenderableFlags enum RenderableFlags
{ {
@ -229,7 +236,7 @@ namespace OpenTK.Platform.Egl
[DllImportAttribute("libEGL.dll", EntryPoint = "eglBindAPI")] [DllImportAttribute("libEGL.dll", EntryPoint = "eglBindAPI")]
[return: MarshalAsAttribute(UnmanagedType.I1)] [return: MarshalAsAttribute(UnmanagedType.I1)]
public static extern bool BindAPI(int api); public static extern bool BindAPI(RenderApi api);
[DllImportAttribute("libEGL.dll", EntryPoint = "eglQueryAPI")] [DllImportAttribute("libEGL.dll", EntryPoint = "eglQueryAPI")]
public static extern int QueryAPI(); public static extern int QueryAPI();

View file

@ -60,7 +60,12 @@ namespace OpenTK.Platform.Egl
// Select an EGLConfig that matches the desired mode. We cannot use the 'mode' // 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) // parameter directly, since it may have originated on a different system (e.g. GLX)
// and it may not support the desired renderer. // 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 = new EglGraphicsMode().SelectGraphicsMode(window,
mode.ColorFormat, mode.Depth, mode.Stencil, mode.Samples, mode.ColorFormat, mode.Depth, mode.Stencil, mode.Samples,
mode.AccumulatorFormat, mode.Buffers, mode.Stereo, 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); HandleAsEGLContext = Egl.CreateContext(window.Display, config, shared != null ? shared.HandleAsEGLContext : IntPtr.Zero, attrib_list);
MakeCurrent(window); 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, public EglContext(ContextHandle handle, EglWindowInfo window, IGraphicsContext sharedContext,

View file

@ -28,14 +28,16 @@
#endregion #endregion
using System; using System;
using System.Diagnostics;
using OpenTK.Graphics; using OpenTK.Graphics;
namespace OpenTK.Platform.Egl namespace OpenTK.Platform.Egl
{ {
class EglUnixContext : EglContext class EglUnixContext : EglContext
{ {
readonly IntPtr ES1 = OpenTK.Platform.X11.DL.Open("libGLESv1_CM", X11.DLOpenFlags.Lazy); IntPtr GL = OpenTK.Platform.X11.DL.Open("libGL", X11.DLOpenFlags.Lazy);
readonly IntPtr ES2 = OpenTK.Platform.X11.DL.Open("libGLESv2", 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, public EglUnixContext(GraphicsMode mode, EglWindowInfo window, IGraphicsContext sharedContext,
int major, int minor, GraphicsContextFlags flags) int major, int minor, GraphicsContextFlags flags)
@ -59,11 +61,19 @@ namespace OpenTK.Platform.Egl
{ {
return X11.DL.Symbol(ES2, function); return X11.DL.Symbol(ES2, function);
} }
else if ((renderable & RenderableFlags.GL) != 0 && GL != IntPtr.Zero)
{
return X11.DL.Symbol(GL, function);
}
return IntPtr.Zero; return IntPtr.Zero;
} }
protected override void Dispose(bool manual) protected override void Dispose(bool manual)
{ {
if (GL != IntPtr.Zero)
{
X11.DL.Close(GL);
}
if (ES1 != IntPtr.Zero) if (ES1 != IntPtr.Zero)
{ {
X11.DL.Close(ES1); X11.DL.Close(ES1);
@ -73,7 +83,27 @@ namespace OpenTK.Platform.Egl
X11.DL.Close(ES2); X11.DL.Close(ES2);
} }
GL = ES1 = ES2 = IntPtr.Zero;
base.Dispose(manual); 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);
}
} }
} }