[EGL] Egl.GetProcAddress only returns extensions

We have to load statically exported entry points using the regular OS
symbol loading facilities, and only use eglGetProcAddress for
extensions.

Fixes crash in https://github.com/mono/MonoGame/pull/2377
This commit is contained in:
thefiddler 2014-05-18 22:04:52 +02:00
parent 687fc90c95
commit 97b211a101
7 changed files with 251 additions and 11 deletions

View file

@ -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" />
@ -828,7 +831,5 @@
</Properties> </Properties>
</MonoDevelop> </MonoDevelop>
</ProjectExtensions> </ProjectExtensions>
<ItemGroup> <ItemGroup />
<Folder Include="Platform\MacOS\Quartz\" />
</ItemGroup>
</Project> </Project>

View file

@ -31,10 +31,12 @@ using OpenTK.Graphics;
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.
@ -62,10 +64,11 @@ 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;
Mode = new EglGraphicsMode().SelectGraphicsMode(mode.ColorFormat, Mode = new EglGraphicsMode().SelectGraphicsMode(mode.ColorFormat,
mode.Depth, mode.Stencil, mode.Samples, mode.AccumulatorFormat, mode.Depth, mode.Stencil, mode.Samples, mode.AccumulatorFormat,
mode.Buffers, mode.Stereo, mode.Buffers, mode.Stereo,
major > 1 ? RenderableFlags.ES2 : RenderableFlags.ES); 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;
@ -144,11 +147,27 @@ namespace OpenTK.Platform.Egl
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()
@ -159,7 +178,7 @@ namespace OpenTK.Platform.Egl
// 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)
{ {

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; 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)
@ -52,7 +52,7 @@ namespace OpenTK.Platform.Egl
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()

View file

@ -39,14 +39,14 @@ namespace OpenTK.Platform.Egl
{ {
X11WindowInfo x11_win = (X11WindowInfo)window; X11WindowInfo x11_win = (X11WindowInfo)window;
EglWindowInfo egl_win = new OpenTK.Platform.Egl.EglWindowInfo(x11_win.Handle, Egl.GetDisplay(x11_win.Display)); 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) public override IGraphicsContext CreateGLContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, bool directRendering, int major, int minor, GraphicsContextFlags flags)
{ {
X11WindowInfo x11_win = (X11WindowInfo)window; X11WindowInfo x11_win = (X11WindowInfo)window;
EglWindowInfo egl_win = new OpenTK.Platform.Egl.EglWindowInfo(x11_win.Handle, Egl.GetDisplay(x11_win.Display)); 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() public override GraphicsContext.GetCurrentContextDelegate CreateGetCurrentGraphicsContext()

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,
}
}