Skip to content

Commit

Permalink
Merge pull request #123 from thefiddler/eglfix
Browse files Browse the repository at this point in the history
[EGL] Fix initialization and extension loading
  • Loading branch information
thefiddler committed May 19, 2014
2 parents 064fb62 + fd3ac1e commit ea0ab32
Show file tree
Hide file tree
Showing 14 changed files with 276 additions and 76 deletions.
7 changes: 4 additions & 3 deletions Source/OpenTK/OpenTK.csproj
Expand Up @@ -163,9 +163,12 @@
<Compile Include="Math\Matrix4x3.cs" /> <Compile Include="Math\Matrix4x3.cs" />
<Compile Include="Math\Matrix4x3d.cs" /> <Compile Include="Math\Matrix4x3d.cs" />
<Compile Include="Platform\DisplayDeviceBase.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\MappedGamePadDriver.cs" />
<Compile Include="Platform\Windows\WinInputBase.cs" /> <Compile Include="Platform\Windows\WinInputBase.cs" />
<Compile Include="Platform\Windows\XInputJoystick.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\INotify.cs" />
<Compile Include="Platform\X11\Bindings\XI.cs" /> <Compile Include="Platform\X11\Bindings\XI.cs" />
<Compile Include="ToolkitOptions.cs" /> <Compile Include="ToolkitOptions.cs" />
Expand Down Expand Up @@ -831,7 +834,5 @@
</Properties> </Properties>
</MonoDevelop> </MonoDevelop>
</ProjectExtensions> </ProjectExtensions>
<ItemGroup> <ItemGroup />
<Folder Include="Platform\MacOS\Quartz\" />
</ItemGroup>
</Project> </Project>
2 changes: 1 addition & 1 deletion Source/OpenTK/Platform/Egl/Egl.cs
Expand Up @@ -207,7 +207,7 @@ static partial class Egl
public static extern bool GetConfigAttrib(EGLDisplay dpy, EGLConfig config, int attribute, out int value); public static extern bool GetConfigAttrib(EGLDisplay dpy, EGLConfig config, int attribute, out int value);


[DllImportAttribute("libEGL.dll", EntryPoint = "eglCreateWindowSurface")] [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")] [DllImportAttribute("libEGL.dll", EntryPoint = "eglCreatePbufferSurface")]
public static extern EGLSurface CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, int[] attrib_list); public static extern EGLSurface CreatePbufferSurface(EGLDisplay dpy, EGLConfig config, int[] attrib_list);
Expand Down
37 changes: 26 additions & 11 deletions Source/OpenTK/Platform/Egl/EglContext.cs
Expand Up @@ -31,10 +31,12 @@


namespace OpenTK.Platform.Egl namespace OpenTK.Platform.Egl
{ {
class EglContext : EmbeddedGraphicsContext abstract class EglContext : EmbeddedGraphicsContext
{ {
#region Fields #region Fields


readonly RenderableFlags Renderable;

EglWindowInfo WindowInfo; EglWindowInfo WindowInfo;
IntPtr HandleAsEGLContext { get { return Handle.Handle; } set { Handle = new ContextHandle(value); } } IntPtr HandleAsEGLContext { get { return Handle.Handle; } set { Handle = new ContextHandle(value); } }
int swap_interval = 1; // Default interval is defined as 1 in EGL. int swap_interval = 1; // Default interval is defined as 1 in EGL.
Expand All @@ -53,19 +55,16 @@ class EglContext : EmbeddedGraphicsContext


EglContext shared = (EglContext)sharedContext; 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; WindowInfo = window;


// 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.
Mode = new EglGraphicsMode().SelectGraphicsMode(mode.ColorFormat, Renderable = major > 1 ? RenderableFlags.ES2 : RenderableFlags.ES;
mode.Depth, mode.Stencil, mode.Samples, mode.AccumulatorFormat, Mode = new EglGraphicsMode().SelectGraphicsMode(window,
mode.Buffers, mode.Stereo, mode.ColorFormat, mode.Depth, mode.Stencil, mode.Samples,
major > 1 ? RenderableFlags.ES2 : RenderableFlags.ES); mode.AccumulatorFormat, mode.Buffers, mode.Stereo,
Renderable);
if (!Mode.Index.HasValue) if (!Mode.Index.HasValue)
throw new GraphicsModeException("Invalid or unsupported GraphicsMode."); throw new GraphicsModeException("Invalid or unsupported GraphicsMode.");
IntPtr config = Mode.Index.Value; IntPtr config = Mode.Index.Value;
Expand Down Expand Up @@ -144,11 +143,27 @@ public override int SwapInterval


public override IntPtr GetAddress(IntPtr function) 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 #endregion


#region Abstract Members

protected abstract IntPtr GetStaticAddress(IntPtr function, RenderableFlags renderable);

#endregion

#region IDisposable Members #region IDisposable Members


public override void Dispose() public override void Dispose()
Expand All @@ -159,7 +174,7 @@ public override void Dispose()


// Todo: cross-reference the specs. What should happen if the context is destroyed from a different // Todo: cross-reference the specs. What should happen if the context is destroyed from a different
// thread? // thread?
void Dispose(bool manual) protected virtual void Dispose(bool manual)
{ {
if (!IsDisposed) if (!IsDisposed)
{ {
Expand Down
30 changes: 5 additions & 25 deletions Source/OpenTK/Platform/Egl/EglGraphicsMode.cs
Expand Up @@ -32,31 +32,17 @@


namespace OpenTK.Platform.Egl namespace OpenTK.Platform.Egl
{ {
class EglGraphicsMode : IGraphicsMode class EglGraphicsMode
{ {
#region IGraphicsMode Members public GraphicsMode SelectGraphicsMode(EglWindowInfo window,

ColorFormat color, int depth, int stencil,
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,
int samples, ColorFormat accum, int buffers, bool stereo, int samples, ColorFormat accum, int buffers, bool stereo,
RenderableFlags renderable_flags) RenderableFlags renderable_flags)
{ {
IntPtr[] configs = new IntPtr[1]; IntPtr[] configs = new IntPtr[1];
int[] attribList = new int[] int[] attribList = new int[]
{ {
//Egl.SURFACE_TYPE, Egl.WINDOW_BIT, Egl.SURFACE_TYPE, Egl.WINDOW_BIT,
Egl.RENDERABLE_TYPE, (int)renderable_flags, Egl.RENDERABLE_TYPE, (int)renderable_flags,


Egl.RED_SIZE, color.Red, Egl.RED_SIZE, color.Red,
Expand All @@ -73,11 +59,7 @@ class EglGraphicsMode : IGraphicsMode
Egl.NONE, Egl.NONE,
}; };


// Todo: what if we don't wish to use the default display? IntPtr display = window.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()));


int num_configs; int num_configs;
if (!Egl.ChooseConfig(display, attribList, configs, configs.Length, out num_configs) || num_configs == 0) if (!Egl.ChooseConfig(display, attribList, configs, configs.Length, out num_configs) || num_configs == 0)
Expand All @@ -101,7 +83,5 @@ class EglGraphicsMode : IGraphicsMode


return new GraphicsMode(active_config, new ColorFormat(r, g, b, a), d, s, sample_buffers > 0 ? samples : 0, 0, 2, false); return new GraphicsMode(active_config, new ColorFormat(r, g, b, a), d, s, sample_buffers > 0 ? samples : 0, 0, 2, false);
} }

#endregion
} }
} }
79 changes: 79 additions & 0 deletions Source/OpenTK/Platform/Egl/EglUnixContext.cs
@@ -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);
}
}
}
83 changes: 83 additions & 0 deletions Source/OpenTK/Platform/Egl/EglWinContext.cs
@@ -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
}
}
9 changes: 2 additions & 7 deletions Source/OpenTK/Platform/Egl/EglWinPlatformFactory.cs
Expand Up @@ -44,15 +44,15 @@ public override IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo
WinWindowInfo win_win = (WinWindowInfo)window; WinWindowInfo win_win = (WinWindowInfo)window;
IntPtr egl_display = GetDisplay(win_win.DeviceContext); IntPtr egl_display = GetDisplay(win_win.DeviceContext);
EglWindowInfo egl_win = new OpenTK.Platform.Egl.EglWindowInfo(win_win.Handle, egl_display); 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) public override IGraphicsContext CreateGLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags)
{ {
WinWindowInfo win_win = (WinWindowInfo)window; WinWindowInfo win_win = (WinWindowInfo)window;
IntPtr egl_display = GetDisplay(win_win.DeviceContext); IntPtr egl_display = GetDisplay(win_win.DeviceContext);
EglWindowInfo egl_win = new OpenTK.Platform.Egl.EglWindowInfo(win_win.Handle, egl_display); 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() public override GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext()
Expand All @@ -63,11 +63,6 @@ public override GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphi
}; };
} }


public override IGraphicsMode CreateGraphicsMode()
{
return new EglGraphicsMode();
}

#endregion #endregion


#region Private Members #region Private Members
Expand Down

0 comments on commit ea0ab32

Please sign in to comment.