Permalink
Browse files

Merge branch 'external' into develop

  • Loading branch information...
thefiddler committed Dec 28, 2013
2 parents 0d1df41 + 3dbf575 commit dc121286797f5fdd95221d4728d3937c91199efe
@@ -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">
@@ -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 @@ public sealed class GraphicsContext : IGraphicsContext, IGraphicsContextInternal
#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>
@@ -164,54 +152,81 @@ public GraphicsContext(GraphicsMode mode, IWindowInfo window, int major, int min
}
/// <summary>
- /// Constructs a new GraphicsContext from a pre-existing context created outside of OpenTK.
+ /// 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">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>
- public GraphicsContext(ContextHandle handle, IWindowInfo window)
- : this(handle, window, null, 1, 0, GraphicsContextFlags.Default)
- { }
-
- /// <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>
- /// <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>
- public GraphicsContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, int major, int minor, GraphicsContextFlags flags)
- : this(handle)
+ /// <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)
{
- IsExternal = true;
-
+ // Replace a zero-handle by the current context, if any
if (handle == ContextHandle.Zero)
{
- implementation = new OpenTK.Platform.Dummy.DummyGLContext(handle);
+ handle = getCurrent();
}
- else if (available_contexts.ContainsKey(handle))
+
+ // Make sure this handle corresponds to a valid, unique OpenGL context
+ if (handle == ContextHandle.Zero)
{
- throw new GraphicsContextException("Context already exists.");
+ throw new GraphicsContextMissingException();
}
- else
+ else if (available_contexts.ContainsKey(handle))
{
- 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;
- }
+ throw new InvalidOperationException("Context handle has already been added");
}
- (this as IGraphicsContextInternal).LoadAll();
+ // 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">This parameter is reserved.</param>
+ public GraphicsContext(ContextHandle handle, IWindowInfo window)
+ : this(handle, window, null, 1, 0, GraphicsContextFlags.Default)
+ { }
+
+ /// <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">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, Platform.Utilities.CreateGetAddress(), Factory.Default.CreateGetCurrentGraphicsContext())
+ { }
+
#endregion
#region Public Members
@@ -309,6 +324,7 @@ static IGraphicsContext FindSharedContext()
/// <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 @@ public static GraphicsContext CreateDummyContext()
/// <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 @@ public static void Assert()
#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,29 +32,27 @@ internal sealed class DummyGLContext : DesktopGraphicsContext
#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);
}
#endregion
#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 @@ public override bool IsCurrent
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 @@ public override void Update(IWindowInfo window)
{ }
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
Oops, something went wrong.

0 comments on commit dc12128

Please sign in to comment.