mirror of
https://github.com/Ryujinx/Opentk.git
synced 2024-12-23 12:55:36 +00:00
Merge branch 'external' into develop
This commit is contained in:
commit
dc12128679
|
@ -565,6 +565,7 @@
|
|||
<None Include="..\..\Dependencies\x64\libSDL2.dylib">
|
||||
<Link>Dependencies\x64\libSDL2.dylib</Link>
|
||||
</None>
|
||||
<Compile Include="OpenTK\Test\ExternalContext.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<BootstrapperPackage Include="Microsoft.Net.Client.3.5">
|
||||
|
|
81
Source/Examples/OpenTK/Test/ExternalContext.cs
Normal file
81
Source/Examples/OpenTK/Test/ExternalContext.cs
Normal file
|
@ -0,0 +1,81 @@
|
|||
// This code was written for the OpenTK library and has been released
|
||||
// to the Public Domain.
|
||||
// It is provided "as is" without express or implied warranty of any kind.
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using OpenTK;
|
||||
using OpenTK.Graphics;
|
||||
using OpenTK.Graphics.OpenGL;
|
||||
|
||||
namespace Examples.Tests
|
||||
{
|
||||
[Example("External Context Test", ExampleCategory.OpenTK, "OpenGL")]
|
||||
class ExternalContext
|
||||
{
|
||||
public static void Main()
|
||||
{
|
||||
using (Toolkit.Init(new ToolkitOptions { Backend = PlatformBackend.PreferNative }))
|
||||
{
|
||||
var window = Sdl2.CreateWindow("Test", 0, 0, 640, 480, WindowFlags.AllowHighDpi | WindowFlags.OpenGL);
|
||||
var context = Sdl2.CreateContext(window);
|
||||
Sdl2.MakeCurrent(window, context);
|
||||
|
||||
using (var dummy = new GraphicsContext(new ContextHandle(context), OpenTK.Platform.Utilities.CreateDummyWindowInfo()))
|
||||
{
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
Sdl2.PumpEvents();
|
||||
GL.ClearColor(i / 100.0f, i / 100.0f, i / 100.0f, i / 100.0f);
|
||||
GL.Clear(ClearBufferMask.ColorBufferBit);
|
||||
|
||||
Sdl2.SwapWindow(window);
|
||||
}
|
||||
|
||||
Sdl2.DestroyWindow(window);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#region SDL2 bindings
|
||||
|
||||
public enum WindowFlags
|
||||
{
|
||||
Default = 0,
|
||||
OpenGL = 0x00000002,
|
||||
AllowHighDpi = 0x00002000,
|
||||
}
|
||||
|
||||
static class Sdl2
|
||||
{
|
||||
const string lib = "SDL2.dll";
|
||||
|
||||
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_CreateWindow", ExactSpelling = true)]
|
||||
public static extern IntPtr CreateWindow(string title, int x, int y, int w, int h, WindowFlags flags);
|
||||
|
||||
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_CreateContext", ExactSpelling = true)]
|
||||
public static extern IntPtr CreateContext(IntPtr window);
|
||||
|
||||
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_DestroyWindow", ExactSpelling = true)]
|
||||
public static extern void DestroyWindow(IntPtr window);
|
||||
|
||||
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_GetCurrentContext", ExactSpelling = true)]
|
||||
public static extern IntPtr GetCurrentContext();
|
||||
|
||||
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_GetProcAddress", ExactSpelling = true)]
|
||||
public static extern IntPtr GetAddress(string name);
|
||||
|
||||
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_MakeCurrent", ExactSpelling = true)]
|
||||
public static extern int MakeCurrent(IntPtr window, IntPtr context);
|
||||
|
||||
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_PumpEvents", ExactSpelling = true)]
|
||||
public static extern void PumpEvents();
|
||||
|
||||
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_SwapWindow", ExactSpelling = true)]
|
||||
public static extern void SwapWindow(IntPtr window);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
}
|
|
@ -39,14 +39,13 @@ namespace OpenTK.Graphics
|
|||
/// </summary>
|
||||
public sealed class GraphicsContext : IGraphicsContext, IGraphicsContextInternal
|
||||
{
|
||||
public delegate IntPtr GetAddressDelegate(string function);
|
||||
public delegate ContextHandle GetCurrentContextDelegate();
|
||||
|
||||
#region --- Fields ---
|
||||
|
||||
IGraphicsContext implementation; // The actual render context implementation for the underlying platform.
|
||||
bool disposed;
|
||||
// Indicates that this context was created through external means, e.g. Tao.Sdl or GLWidget#.
|
||||
// In this case, We'll assume that the external program will manage the lifetime of this
|
||||
// context - we'll not destroy it manually.
|
||||
readonly bool IsExternal;
|
||||
bool check_errors = true;
|
||||
// Cache for the context handle. We need this for RemoveContext()
|
||||
// in case the user does not call Dispose(). When this happens,
|
||||
|
@ -67,17 +66,6 @@ namespace OpenTK.Graphics
|
|||
|
||||
#region --- Constructors ---
|
||||
|
||||
// Necessary to allow creation of dummy GraphicsContexts (see CreateDummyContext static method).
|
||||
GraphicsContext(ContextHandle handle)
|
||||
{
|
||||
implementation = new OpenTK.Platform.Dummy.DummyGLContext(handle);
|
||||
|
||||
lock (SyncRoot)
|
||||
{
|
||||
AddContext(this);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new GraphicsContext with the specified GraphicsMode and attaches it to the specified window.
|
||||
/// </summary>
|
||||
|
@ -163,12 +151,65 @@ namespace OpenTK.Graphics
|
|||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="OpenTK.Graphics.GraphicsContext"/> class using
|
||||
/// an external context handle that was created by a third-party library.
|
||||
/// </summary>
|
||||
/// <param name="handle">
|
||||
/// A valid, unique handle for an external OpenGL context, or <c>ContextHandle.Zero</c> to use the current context.
|
||||
/// It is an error to specify a handle that has been created through OpenTK or that has been passed to OpenTK before.
|
||||
/// </param>
|
||||
/// <param name="getAddress">
|
||||
/// A <c>GetAddressDelegate</c> instance that accepts the name of an OpenGL function and returns
|
||||
/// a valid function pointer, or <c>IntPtr.Zero</c> if that function is not supported. This delegate should be
|
||||
/// implemented using the same toolkit that created the OpenGL context (i.e. if the context was created with
|
||||
/// SDL_GL_CreateContext(), then this delegate should use SDL_GL_GetProcAddress() to retrieve function
|
||||
/// pointers.)
|
||||
/// </param>
|
||||
/// <param name="getCurrent">
|
||||
/// A <c>GetCurrentContextDelegate</c> instance that returns the handle of the current OpenGL context,
|
||||
/// or <c>IntPtr.Zero</c> if no context is current on the calling thread. This delegate should be implemented
|
||||
/// using the same toolkit that created the OpenGL context (i.e. if the context was created with
|
||||
/// SDL_GL_CreateContext(), then this delegate should use SDL_GL_GetCurrentContext() to retrieve
|
||||
/// the current context.)
|
||||
/// </param>
|
||||
public GraphicsContext(ContextHandle handle, GetAddressDelegate getAddress, GetCurrentContextDelegate getCurrent)
|
||||
{
|
||||
if (getAddress == null || getCurrent == null)
|
||||
throw new ArgumentNullException();
|
||||
|
||||
lock (SyncRoot)
|
||||
{
|
||||
// Replace a zero-handle by the current context, if any
|
||||
if (handle == ContextHandle.Zero)
|
||||
{
|
||||
handle = getCurrent();
|
||||
}
|
||||
|
||||
// Make sure this handle corresponds to a valid, unique OpenGL context
|
||||
if (handle == ContextHandle.Zero)
|
||||
{
|
||||
throw new GraphicsContextMissingException();
|
||||
}
|
||||
else if (available_contexts.ContainsKey(handle))
|
||||
{
|
||||
throw new InvalidOperationException("Context handle has already been added");
|
||||
}
|
||||
|
||||
// We have a valid handle for an external OpenGL context, wrap it into a
|
||||
// DummyGLContext instance.
|
||||
implementation = new Platform.Dummy.DummyGLContext(handle, getAddress);
|
||||
GetCurrentContext = getCurrent ?? GetCurrentContext;
|
||||
AddContext(this);
|
||||
}
|
||||
implementation.LoadAll();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Constructs a new GraphicsContext from a pre-existing context created outside of OpenTK.
|
||||
/// </summary>
|
||||
/// <param name="handle">The handle of the existing context. This must be a valid, unique handle that is not known to OpenTK.</param>
|
||||
/// <param name="window">The window this context is bound to. This must be a valid window obtained through Utilities.CreateWindowInfo.</param>
|
||||
/// <exception cref="GraphicsContextException">Occurs if handle is identical to a context already registered with OpenTK.</exception>
|
||||
/// <param name="window">This parameter is reserved.</param>
|
||||
public GraphicsContext(ContextHandle handle, IWindowInfo window)
|
||||
: this(handle, window, null, 1, 0, GraphicsContextFlags.Default)
|
||||
{ }
|
||||
|
@ -177,40 +218,14 @@ namespace OpenTK.Graphics
|
|||
/// Constructs a new GraphicsContext from a pre-existing context created outside of OpenTK.
|
||||
/// </summary>
|
||||
/// <param name="handle">The handle of the existing context. This must be a valid, unique handle that is not known to OpenTK.</param>
|
||||
/// <param name="window">The window this context is bound to. This must be a valid window obtained through Utilities.CreateWindowInfo.</param>
|
||||
/// <param name="shareContext">A different context that shares resources with this instance, if any.
|
||||
/// Pass null if the context is not shared or if this is the first GraphicsContext instruct you construct.</param>
|
||||
/// <param name="major">The major version of the context (e.g. "2" for "2.1").</param>
|
||||
/// <param name="minor">The minor version of the context (e.g. "1" for "2.1").</param>
|
||||
/// <param name="flags">A bitwise combination of <see cref="GraphicsContextFlags"/> that describe this context.</param>
|
||||
/// <exception cref="GraphicsContextException">Occurs if handle is identical to a context already registered with OpenTK.</exception>
|
||||
/// <param name="window">This parameter is reserved.</param>
|
||||
/// <param name="shareContext">This parameter is reserved.</param>
|
||||
/// <param name="major">This parameter is reserved.</param>
|
||||
/// <param name="minor">This parameter is reserved.</param>
|
||||
/// <param name="flags">This parameter is reserved..</param>
|
||||
public GraphicsContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, int major, int minor, GraphicsContextFlags flags)
|
||||
: this(handle)
|
||||
{
|
||||
lock (SyncRoot)
|
||||
{
|
||||
IsExternal = true;
|
||||
|
||||
if (handle == ContextHandle.Zero)
|
||||
{
|
||||
implementation = new OpenTK.Platform.Dummy.DummyGLContext(handle);
|
||||
}
|
||||
else if (available_contexts.ContainsKey(handle))
|
||||
{
|
||||
throw new GraphicsContextException("Context already exists.");
|
||||
}
|
||||
else
|
||||
{
|
||||
switch ((flags & GraphicsContextFlags.Embedded) == GraphicsContextFlags.Embedded)
|
||||
{
|
||||
case false: implementation = Factory.Default.CreateGLContext(handle, window, shareContext, direct_rendering, major, minor, flags); break;
|
||||
case true: implementation = Factory.Embedded.CreateGLContext(handle, window, shareContext, direct_rendering, major, minor, flags); break;
|
||||
}
|
||||
}
|
||||
|
||||
(this as IGraphicsContextInternal).LoadAll();
|
||||
}
|
||||
}
|
||||
: this(handle, Platform.Utilities.CreateGetAddress(), Factory.Default.CreateGetCurrentGraphicsContext())
|
||||
{ }
|
||||
|
||||
#endregion
|
||||
|
||||
|
@ -309,6 +324,7 @@ namespace OpenTK.Graphics
|
|||
/// <para>Instances created by this method will not be functional. Instance methods will have no effect.</para>
|
||||
/// <para>This method requires that a context is current on the calling thread.</para>
|
||||
/// </remarks>
|
||||
[Obsolete("Use GraphicsContext(ContextHandle, IWindowInfo) constructor instead")]
|
||||
public static GraphicsContext CreateDummyContext()
|
||||
{
|
||||
ContextHandle handle = GetCurrentContext();
|
||||
|
@ -326,12 +342,13 @@ namespace OpenTK.Graphics
|
|||
/// <remarks>
|
||||
/// <para>Instances created by this method will not be functional. Instance methods will have no effect.</para>
|
||||
/// </remarks>
|
||||
[Obsolete("Use GraphicsContext(ContextHandle, IWindowInfo) constructor instead")]
|
||||
public static GraphicsContext CreateDummyContext(ContextHandle handle)
|
||||
{
|
||||
if (handle == ContextHandle.Zero)
|
||||
throw new ArgumentOutOfRangeException("handle");
|
||||
|
||||
return new GraphicsContext(handle);
|
||||
return new GraphicsContext(handle, (IWindowInfo)null);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
@ -352,7 +369,6 @@ namespace OpenTK.Graphics
|
|||
|
||||
#region public static IGraphicsContext CurrentContext
|
||||
|
||||
internal delegate ContextHandle GetCurrentContextDelegate();
|
||||
internal static GetCurrentContextDelegate GetCurrentContext;
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -777,6 +777,7 @@
|
|||
<Compile Include="SlotAttribute.cs" />
|
||||
<Compile Include="RewrittenAttribute.cs" />
|
||||
<Compile Include="Graphics\OpenGL\GLObsolete.cs" />
|
||||
<Compile Include="Platform\MacOS\NS.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
|
|
|
@ -22,7 +22,8 @@ namespace OpenTK.Platform.Dummy
|
|||
/// </summary>
|
||||
internal sealed class DummyGLContext : DesktopGraphicsContext
|
||||
{
|
||||
// This mode is not real. To receive a real mode we'd have to create a temporary context, which is not desirable!
|
||||
readonly GraphicsContext.GetAddressDelegate Loader;
|
||||
|
||||
bool vsync;
|
||||
int swap_interval;
|
||||
static int handle_count;
|
||||
|
@ -31,13 +32,20 @@ namespace OpenTK.Platform.Dummy
|
|||
#region --- Constructors ---
|
||||
|
||||
public DummyGLContext()
|
||||
: this(new ContextHandle(new IntPtr(++handle_count)))
|
||||
{
|
||||
Handle = new ContextHandle(
|
||||
new IntPtr(Interlocked.Increment(
|
||||
ref handle_count)));
|
||||
}
|
||||
|
||||
public DummyGLContext(ContextHandle handle)
|
||||
public DummyGLContext(ContextHandle handle, GraphicsContext.GetAddressDelegate loader)
|
||||
: this()
|
||||
{
|
||||
Handle = handle;
|
||||
if (handle != ContextHandle.Zero)
|
||||
{
|
||||
Handle = handle;
|
||||
}
|
||||
Loader = loader;
|
||||
Mode = new GraphicsMode(new IntPtr(2), 32, 16, 0, 0, 0, 2, false);
|
||||
}
|
||||
|
||||
|
@ -45,15 +53,6 @@ namespace OpenTK.Platform.Dummy
|
|||
|
||||
#region --- IGraphicsContext Members ---
|
||||
|
||||
public void CreateContext(bool direct, IGraphicsContext source)
|
||||
{
|
||||
if (Handle == ContextHandle.Zero)
|
||||
{
|
||||
++handle_count;
|
||||
Handle = new ContextHandle((IntPtr)handle_count);
|
||||
}
|
||||
}
|
||||
|
||||
public override void SwapBuffers() { }
|
||||
|
||||
public override void MakeCurrent(IWindowInfo info)
|
||||
|
@ -81,9 +80,15 @@ namespace OpenTK.Platform.Dummy
|
|||
get { return current_thread != null && current_thread == Thread.CurrentThread; }
|
||||
}
|
||||
|
||||
public override IntPtr GetAddress(string function) { return IntPtr.Zero; }
|
||||
public override IntPtr GetAddress(string function)
|
||||
{
|
||||
return Loader(function);
|
||||
}
|
||||
|
||||
public override IntPtr GetAddress(IntPtr function) { return IntPtr.Zero; }
|
||||
public override IntPtr GetAddress(IntPtr function)
|
||||
{
|
||||
return IntPtr.Zero;
|
||||
}
|
||||
|
||||
public override int SwapInterval
|
||||
{
|
||||
|
@ -101,7 +106,14 @@ namespace OpenTK.Platform.Dummy
|
|||
{ }
|
||||
|
||||
public override void LoadAll()
|
||||
{ }
|
||||
{
|
||||
new OpenTK.Graphics.OpenGL.GL().LoadEntryPoints();
|
||||
new OpenTK.Graphics.OpenGL4.GL().LoadEntryPoints();
|
||||
new OpenTK.Graphics.ES10.GL().LoadEntryPoints();
|
||||
new OpenTK.Graphics.ES11.GL().LoadEntryPoints();
|
||||
new OpenTK.Graphics.ES20.GL().LoadEntryPoints();
|
||||
new OpenTK.Graphics.ES30.GL().LoadEntryPoints();
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
|
|
|
@ -464,62 +464,14 @@ namespace OpenTK.Platform.MacOS
|
|||
|
||||
#region IGraphicsContextInternal Members
|
||||
|
||||
private const string Library = "libdl.dylib";
|
||||
|
||||
[DllImport(Library, EntryPoint = "NSIsSymbolNameDefined")]
|
||||
private static extern bool NSIsSymbolNameDefined(string s);
|
||||
[DllImport(Library, EntryPoint = "NSIsSymbolNameDefined")]
|
||||
private static extern bool NSIsSymbolNameDefined(IntPtr s);
|
||||
[DllImport(Library, EntryPoint = "NSLookupAndBindSymbol")]
|
||||
private static extern IntPtr NSLookupAndBindSymbol(string s);
|
||||
[DllImport(Library, EntryPoint = "NSLookupAndBindSymbol")]
|
||||
private static extern IntPtr NSLookupAndBindSymbol(IntPtr s);
|
||||
[DllImport(Library, EntryPoint = "NSAddressOfSymbol")]
|
||||
private static extern IntPtr NSAddressOfSymbol(IntPtr symbol);
|
||||
|
||||
public override IntPtr GetAddress(string function)
|
||||
{
|
||||
// Instead of allocating and combining strings in managed memory
|
||||
// we do that directly in unmanaged memory. This way, we avoid
|
||||
// 2 string allocations every time this function is called.
|
||||
|
||||
// must add a '_' prefix and null-terminate the function name,
|
||||
// hence we allocate +2 bytes
|
||||
IntPtr ptr = Marshal.AllocHGlobal(function.Length + 2);
|
||||
try
|
||||
{
|
||||
Marshal.WriteByte(ptr, (byte)'_');
|
||||
for (int i = 0; i < function.Length; i++)
|
||||
{
|
||||
Marshal.WriteByte(ptr, i + 1, (byte)function[i]);
|
||||
}
|
||||
Marshal.WriteByte(ptr, function.Length + 1, 0); // null-terminate
|
||||
|
||||
IntPtr symbol = IntPtr.Zero;
|
||||
if (NSIsSymbolNameDefined(ptr))
|
||||
{
|
||||
symbol = NSLookupAndBindSymbol(ptr);
|
||||
if (symbol != IntPtr.Zero)
|
||||
symbol = NSAddressOfSymbol(symbol);
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeHGlobal(ptr);
|
||||
}
|
||||
return NS.GetAddress(function);
|
||||
}
|
||||
|
||||
public override IntPtr GetAddress(IntPtr function)
|
||||
{
|
||||
if (!NSIsSymbolNameDefined(function))
|
||||
return IntPtr.Zero;
|
||||
|
||||
IntPtr symbol = NSLookupAndBindSymbol(function);
|
||||
if (symbol != IntPtr.Zero)
|
||||
symbol = NSAddressOfSymbol(symbol);
|
||||
|
||||
return symbol;
|
||||
return NS.GetAddress(function);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
|
|
@ -70,7 +70,7 @@ namespace OpenTK.Platform.MacOS
|
|||
{
|
||||
return (GraphicsContext.GetCurrentContextDelegate)delegate
|
||||
{
|
||||
return new ContextHandle(Agl.aglGetCurrentContext());
|
||||
return new ContextHandle(Cgl.GetCurrentContext());
|
||||
};
|
||||
}
|
||||
|
||||
|
|
92
Source/OpenTK/Platform/MacOS/NS.cs
Normal file
92
Source/OpenTK/Platform/MacOS/NS.cs
Normal file
|
@ -0,0 +1,92 @@
|
|||
#region License
|
||||
//
|
||||
// NS.cs
|
||||
//
|
||||
// Author:
|
||||
// Stefanos A. <stapostol@gmail.com>
|
||||
//
|
||||
// Copyright (c) 2006-2013 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.Runtime.InteropServices;
|
||||
|
||||
namespace OpenTK.Platform.MacOS
|
||||
{
|
||||
|
||||
internal class NS
|
||||
{
|
||||
const string Library = "libdl.dylib";
|
||||
|
||||
[DllImport(Library, EntryPoint = "NSIsSymbolNameDefined")]
|
||||
static extern bool NSIsSymbolNameDefined(string s);
|
||||
[DllImport(Library, EntryPoint = "NSIsSymbolNameDefined")]
|
||||
static extern bool NSIsSymbolNameDefined(IntPtr s);
|
||||
[DllImport(Library, EntryPoint = "NSLookupAndBindSymbol")]
|
||||
static extern IntPtr NSLookupAndBindSymbol(string s);
|
||||
[DllImport(Library, EntryPoint = "NSLookupAndBindSymbol")]
|
||||
static extern IntPtr NSLookupAndBindSymbol(IntPtr s);
|
||||
[DllImport(Library, EntryPoint = "NSAddressOfSymbol")]
|
||||
static extern IntPtr NSAddressOfSymbol(IntPtr symbol);
|
||||
|
||||
public static IntPtr GetAddress(string function)
|
||||
{
|
||||
// Instead of allocating and combining strings in managed memory
|
||||
// we do that directly in unmanaged memory. This way, we avoid
|
||||
// 2 string allocations every time this function is called.
|
||||
|
||||
// must add a '_' prefix and null-terminate the function name,
|
||||
// hence we allocate +2 bytes
|
||||
IntPtr ptr = Marshal.AllocHGlobal(function.Length + 2);
|
||||
try
|
||||
{
|
||||
Marshal.WriteByte(ptr, (byte)'_');
|
||||
for (int i = 0; i < function.Length; i++)
|
||||
{
|
||||
Marshal.WriteByte(ptr, i + 1, (byte)function[i]);
|
||||
}
|
||||
Marshal.WriteByte(ptr, function.Length + 1, 0); // null-terminate
|
||||
|
||||
IntPtr symbol = GetAddress(ptr);
|
||||
return symbol;
|
||||
}
|
||||
finally
|
||||
{
|
||||
Marshal.FreeHGlobal(ptr);
|
||||
}
|
||||
}
|
||||
|
||||
public static IntPtr GetAddress(IntPtr function)
|
||||
{
|
||||
IntPtr symbol = IntPtr.Zero;
|
||||
if (NSIsSymbolNameDefined(function))
|
||||
{
|
||||
symbol = NSLookupAndBindSymbol(function);
|
||||
if (symbol != IntPtr.Zero)
|
||||
symbol = NSAddressOfSymbol(symbol);
|
||||
}
|
||||
return symbol;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -334,6 +334,7 @@ namespace OpenTK.Platform.SDL2
|
|||
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_GetAttribute", ExactSpelling = true)]
|
||||
public static extern int GetAttribute(ContextAttribute attr, out int value);
|
||||
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_GetCurrentContext", ExactSpelling = true)]
|
||||
public static extern IntPtr GetCurrentContext();
|
||||
|
||||
|
|
|
@ -170,6 +170,32 @@ namespace OpenTK.Platform
|
|||
|
||||
#endregion
|
||||
|
||||
#region CreateGetAddress
|
||||
|
||||
internal static GraphicsContext.GetAddressDelegate CreateGetAddress()
|
||||
{
|
||||
GraphicsContext.GetAddressDelegate loader = null;
|
||||
if (Configuration.RunningOnWindows)
|
||||
{
|
||||
loader = Platform.Windows.Wgl.GetProcAddress;
|
||||
}
|
||||
else if (Configuration.RunningOnX11)
|
||||
{
|
||||
loader = Platform.X11.Glx.GetProcAddress;
|
||||
}
|
||||
else if (Configuration.RunningOnMacOS)
|
||||
{
|
||||
loader = Platform.MacOS.NS.GetAddress;
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new PlatformNotSupportedException();
|
||||
}
|
||||
return loader;
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
#region --- Creating a Graphics Context ---
|
||||
|
||||
/// <summary>
|
||||
|
|
Loading…
Reference in a new issue