Merge pull request #123 from thefiddler/eglfix

[EGL] Fix initialization and extension loading
This commit is contained in:
thefiddler 2014-05-19 23:14:41 +02:00
commit ea0ab3243e
14 changed files with 276 additions and 76 deletions

View file

@ -163,9 +163,12 @@
<Compile Include="Math\Matrix4x3.cs" />
<Compile Include="Math\Matrix4x3d.cs" />
<Compile Include="Platform\DisplayDeviceBase.cs" />
<Compile Include="Platform\Egl\EglUnixContext.cs" />
<Compile Include="Platform\Egl\EglWinContext.cs" />
<Compile Include="Platform\MappedGamePadDriver.cs" />
<Compile Include="Platform\Windows\WinInputBase.cs" />
<Compile Include="Platform\Windows\XInputJoystick.cs" />
<Compile Include="Platform\X11\Bindings\DL.cs" />
<Compile Include="Platform\X11\Bindings\INotify.cs" />
<Compile Include="Platform\X11\Bindings\XI.cs" />
<Compile Include="ToolkitOptions.cs" />
@ -831,7 +834,5 @@
</Properties>
</MonoDevelop>
</ProjectExtensions>
<ItemGroup>
<Folder Include="Platform\MacOS\Quartz\" />
</ItemGroup>
<ItemGroup />
</Project>

View file

@ -207,7 +207,7 @@ namespace OpenTK.Platform.Egl
public static extern bool GetConfigAttrib(EGLDisplay dpy, EGLConfig config, int attribute, out int value);
[DllImportAttribute("libEGL.dll", EntryPoint = "eglCreateWindowSurface")]
public static extern EGLSurface CreateWindowSurface(EGLDisplay dpy, EGLConfig config, IntPtr win, int[] attrib_list);
public static extern EGLSurface CreateWindowSurface(EGLDisplay dpy, EGLConfig config, IntPtr win, IntPtr attrib_list);
[DllImportAttribute("libEGL.dll", EntryPoint = "eglCreatePbufferSurface")]
public static extern EGLSurface CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, int[] attrib_list);

View file

@ -31,10 +31,12 @@ using OpenTK.Graphics;
namespace OpenTK.Platform.Egl
{
class EglContext : EmbeddedGraphicsContext
abstract class EglContext : EmbeddedGraphicsContext
{
#region Fields
readonly RenderableFlags Renderable;
EglWindowInfo WindowInfo;
IntPtr HandleAsEGLContext { get { return Handle.Handle; } set { Handle = new ContextHandle(value); } }
int swap_interval = 1; // Default interval is defined as 1 in EGL.
@ -53,19 +55,16 @@ namespace OpenTK.Platform.Egl
EglContext shared = (EglContext)sharedContext;
int dummy_major, dummy_minor;
if (!Egl.Initialize(window.Display, out dummy_major, out dummy_minor))
throw new GraphicsContextException(String.Format("Failed to initialize EGL, error {0}.", Egl.GetError()));
WindowInfo = window;
// 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.
Mode = new EglGraphicsMode().SelectGraphicsMode(mode.ColorFormat,
mode.Depth, mode.Stencil, mode.Samples, mode.AccumulatorFormat,
mode.Buffers, mode.Stereo,
major > 1 ? RenderableFlags.ES2 : RenderableFlags.ES);
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,
Renderable);
if (!Mode.Index.HasValue)
throw new GraphicsModeException("Invalid or unsupported GraphicsMode.");
IntPtr config = Mode.Index.Value;
@ -144,9 +143,25 @@ namespace OpenTK.Platform.Egl
public override IntPtr GetAddress(IntPtr function)
{
return Egl.GetProcAddress(function);
// Try loading a static export from ES1 or ES2
IntPtr address = GetStaticAddress(function, Renderable);
// If a static export is not available, try retrieving an extension
// function pointer with eglGetProcAddress
if (address == IntPtr.Zero)
{
address = Egl.GetProcAddress(function);
}
return address;
}
#endregion
#region Abstract Members
protected abstract IntPtr GetStaticAddress(IntPtr function, RenderableFlags renderable);
#endregion
#region IDisposable Members
@ -159,7 +174,7 @@ namespace OpenTK.Platform.Egl
// Todo: cross-reference the specs. What should happen if the context is destroyed from a different
// thread?
void Dispose(bool manual)
protected virtual void Dispose(bool manual)
{
if (!IsDisposed)
{

View file

@ -32,31 +32,17 @@ using OpenTK.Graphics;
namespace OpenTK.Platform.Egl
{
class EglGraphicsMode : IGraphicsMode
class EglGraphicsMode
{
#region IGraphicsMode Members
public GraphicsMode SelectGraphicsMode(ColorFormat color, int depth, int stencil,
int samples, ColorFormat accum, int buffers, bool stereo)
{
// According to the EGL specs, the ES flag should select ES 1.0 or higher, which
// makes sense as a default. EglContext.cs checks
return SelectGraphicsMode(color, depth, stencil, samples, accum, buffers, stereo,
RenderableFlags.ES);
}
#endregion
#region Public Members
public GraphicsMode SelectGraphicsMode(ColorFormat color, int depth, int stencil,
public GraphicsMode SelectGraphicsMode(EglWindowInfo window,
ColorFormat color, int depth, int stencil,
int samples, ColorFormat accum, int buffers, bool stereo,
RenderableFlags renderable_flags)
{
IntPtr[] configs = new IntPtr[1];
int[] attribList = new int[]
{
//Egl.SURFACE_TYPE, Egl.WINDOW_BIT,
Egl.SURFACE_TYPE, Egl.WINDOW_BIT,
Egl.RENDERABLE_TYPE, (int)renderable_flags,
Egl.RED_SIZE, color.Red,
@ -73,11 +59,7 @@ namespace OpenTK.Platform.Egl
Egl.NONE,
};
// Todo: what if we don't wish to use the default display?
IntPtr display = Egl.GetDisplay(IntPtr.Zero);
int major, minor;
if (!Egl.Initialize(display, out major, out minor))
throw new GraphicsModeException(String.Format("Failed to initialize display connection, error {0}", Egl.GetError()));
IntPtr display = window.Display;
int num_configs;
if (!Egl.ChooseConfig(display, attribList, configs, configs.Length, out num_configs) || num_configs == 0)
@ -101,7 +83,5 @@ namespace OpenTK.Platform.Egl
return new GraphicsMode(active_config, new ColorFormat(r, g, b, a), d, s, sample_buffers > 0 ? samples : 0, 0, 2, false);
}
#endregion
}
}

View file

@ -0,0 +1,79 @@
#region License
//
// EglUnixContext.cs
//
// Author:
// Stefanos A. <stapostol@gmail.com>
//
// Copyright (c) 2006-2014 Stefanos Apostolopoulos
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#endregion
using System;
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);
public EglUnixContext(GraphicsMode mode, EglWindowInfo window, IGraphicsContext sharedContext,
int major, int minor, GraphicsContextFlags flags)
: base(mode, window, sharedContext, major, minor, flags)
{
}
public EglUnixContext(ContextHandle handle, EglWindowInfo window, IGraphicsContext sharedContext,
int major, int minor, GraphicsContextFlags flags)
: base(handle, window, sharedContext, major, minor, flags)
{
}
protected override IntPtr GetStaticAddress(IntPtr function, RenderableFlags renderable)
{
if ((renderable & RenderableFlags.ES) != 0 && ES1 != IntPtr.Zero)
{
return X11.DL.Symbol(ES1, function);
}
else if ((renderable & RenderableFlags.ES2) != 0 && ES2 != IntPtr.Zero)
{
return X11.DL.Symbol(ES2, function);
}
return IntPtr.Zero;
}
protected override void Dispose(bool manual)
{
if (ES1 != IntPtr.Zero)
{
X11.DL.Close(ES1);
}
if (ES2 != IntPtr.Zero)
{
X11.DL.Close(ES2);
}
base.Dispose(manual);
}
}
}

View file

@ -0,0 +1,83 @@
#region License
//
// EglWinContext.cs
//
// Author:
// Stefanos A. <stapostol@gmail.com>
//
// Copyright (c) 2006-2014 Stefanos Apostolopoulos
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#endregion
using System;
using OpenTK.Graphics;
namespace OpenTK.Platform.Egl
{
class EglWinContext : EglContext
{
readonly IntPtr ES1 = OpenTK.Platform.Windows.Functions.LoadLibrary("libGLESv1_CM");
readonly IntPtr ES2 = OpenTK.Platform.Windows.Functions.LoadLibrary("libGLESv2");
public EglWinContext(GraphicsMode mode, EglWindowInfo window, IGraphicsContext sharedContext,
int major, int minor, GraphicsContextFlags flags)
: base(mode, window, sharedContext, major, minor, flags)
{
}
public EglWinContext(ContextHandle handle, EglWindowInfo window, IGraphicsContext sharedContext,
int major, int minor, GraphicsContextFlags flags)
: base(handle, window, sharedContext, major, minor, flags)
{
}
#region Protected Members
protected override IntPtr GetStaticAddress(IntPtr function, RenderableFlags renderable)
{
if ((renderable & RenderableFlags.ES) != 0 && ES1 != IntPtr.Zero)
{
return Windows.Functions.GetProcAddress(ES1, function);
}
else if ((renderable & RenderableFlags.ES2) != 0 && ES2 != IntPtr.Zero)
{
return Windows.Functions.GetProcAddress(ES2, function);
}
return IntPtr.Zero;
}
protected override void Dispose(bool manual)
{
if (ES1 != IntPtr.Zero)
{
Windows.Functions.FreeLibrary(ES1);
}
if (ES2 != IntPtr.Zero)
{
Windows.Functions.FreeLibrary(ES2);
}
base.Dispose(manual);
}
#endregion
}
}

View file

@ -44,7 +44,7 @@ namespace OpenTK.Platform.Egl
WinWindowInfo win_win = (WinWindowInfo)window;
IntPtr egl_display = GetDisplay(win_win.DeviceContext);
EglWindowInfo egl_win = new OpenTK.Platform.Egl.EglWindowInfo(win_win.Handle, egl_display);
return new EglContext(mode, egl_win, shareContext, major, minor, flags);
return new EglWinContext(mode, egl_win, shareContext, major, minor, flags);
}
public override IGraphicsContext CreateGLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags)
@ -52,7 +52,7 @@ namespace OpenTK.Platform.Egl
WinWindowInfo win_win = (WinWindowInfo)window;
IntPtr egl_display = GetDisplay(win_win.DeviceContext);
EglWindowInfo egl_win = new OpenTK.Platform.Egl.EglWindowInfo(win_win.Handle, egl_display);
return new EglContext(handle, egl_win, shareContext, major, minor, flags);
return new EglWinContext(handle, egl_win, shareContext, major, minor, flags);
}
public override GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext()
@ -63,11 +63,6 @@ namespace OpenTK.Platform.Egl
};
}
public override IGraphicsMode CreateGraphicsMode()
{
return new EglGraphicsMode();
}
#endregion
#region Private Members

View file

@ -45,19 +45,30 @@ namespace OpenTK.Platform.Egl
#endregion
#region Constructiors
#region Constructors
public EglWindowInfo(IntPtr handle, IntPtr display)
: this(handle, display, IntPtr.Zero)
{
Handle = handle;
Display = display;
}
public EglWindowInfo(IntPtr handle, IntPtr display, IntPtr surface)
{
Handle = handle;
Display = display;
Surface = surface;
if (display == IntPtr.Zero)
{
display = Egl.GetDisplay(IntPtr.Zero);
}
Display = display;
int dummy_major, dummy_minor;
if (!Egl.Initialize(Display, out dummy_major, out dummy_minor))
{
throw new GraphicsContextException(String.Format("Failed to initialize EGL, error {0}.", Egl.GetError()));
}
}
#endregion
@ -72,7 +83,7 @@ namespace OpenTK.Platform.Egl
public void CreateWindowSurface(IntPtr config)
{
Surface = Egl.CreateWindowSurface(Display, config, Handle, null);
Surface = Egl.CreateWindowSurface(Display, config, Handle, IntPtr.Zero);
if (Surface==IntPtr.Zero)
{
throw new GraphicsContextException(String.Format(

View file

@ -39,14 +39,14 @@ namespace OpenTK.Platform.Egl
{
X11WindowInfo x11_win = (X11WindowInfo)window;
EglWindowInfo egl_win = new OpenTK.Platform.Egl.EglWindowInfo(x11_win.Handle, Egl.GetDisplay(x11_win.Display));
return new EglContext(mode, egl_win, shareContext, major, minor, flags);
return new EglUnixContext(mode, egl_win, shareContext, major, minor, flags);
}
public override IGraphicsContext CreateGLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags)
{
X11WindowInfo x11_win = (X11WindowInfo)window;
EglWindowInfo egl_win = new OpenTK.Platform.Egl.EglWindowInfo(x11_win.Handle, Egl.GetDisplay(x11_win.Display));
return new EglContext(handle, egl_win, shareContext, major, minor, flags);
return new EglUnixContext(handle, egl_win, shareContext, major, minor, flags);
}
public override GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext()

View file

@ -130,11 +130,6 @@ namespace OpenTK.Platform
return default_implementation.CreateGetCurrentGraphicsContext();
}
public IGraphicsMode CreateGraphicsMode()
{
return default_implementation.CreateGraphicsMode();
}
public IKeyboardDriver2 CreateKeyboardDriver()
{
return default_implementation.CreateKeyboardDriver();
@ -195,11 +190,6 @@ namespace OpenTK.Platform
throw new PlatformNotSupportedException(error_string);
}
public override IGraphicsMode CreateGraphicsMode()
{
throw new PlatformNotSupportedException(error_string);
}
public override IKeyboardDriver2 CreateKeyboardDriver()
{
throw new PlatformNotSupportedException(error_string);

View file

@ -45,8 +45,6 @@ namespace OpenTK.Platform
GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext();
IGraphicsMode CreateGraphicsMode();
OpenTK.Input.IKeyboardDriver2 CreateKeyboardDriver();
OpenTK.Input.IMouseDriver2 CreateMouseDriver();

View file

@ -63,11 +63,6 @@ namespace OpenTK.Platform
public abstract GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext();
public virtual IGraphicsMode CreateGraphicsMode()
{
throw new NotSupportedException();
}
public abstract IKeyboardDriver2 CreateKeyboardDriver();
public abstract IMouseDriver2 CreateMouseDriver();

View file

@ -0,0 +1,58 @@
#region License
//
// DL.cs
//
// Author:
// Stefanos A. <stapostol@gmail.com>
//
// Copyright (c) 2006-2014 Stefanos Apostolopoulos
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
//
#endregion
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
namespace OpenTK.Platform.X11
{
class DL
{
const string lib = "dl";
[DllImport(lib, EntryPoint = "dlopen")]
internal static extern IntPtr Open(string filename, DLOpenFlags flags);
[DllImport(lib, EntryPoint = "dlclose")]
internal static extern int Close(IntPtr handle);
[DllImport(lib, EntryPoint = "dlsym")]
internal static extern IntPtr Symbol(IntPtr handle, IntPtr name);
}
enum DLOpenFlags
{
Lazy = 0x0001,
Now = 0x0002,
Global = 0x0100,
Local = 0x0000,
}
}

View file

@ -94,11 +94,6 @@ namespace OpenTK.Platform.X11
};
}
public override IGraphicsMode CreateGraphicsMode()
{
throw new NotSupportedException();
}
public override IKeyboardDriver2 CreateKeyboardDriver()
{
return InputDriver.KeyboardDriver;