This commit is contained in:
thefiddler 2013-11-10 19:11:05 +01:00
commit 2c9d574b08
15 changed files with 190 additions and 136 deletions

View file

@ -38,7 +38,10 @@ namespace OpenTK
/// <summary>Provides information about the underlying OS and runtime.</summary>
public static class Configuration
{
static bool runningOnWindows, runningOnUnix, runningOnX11, runningOnMacOS, runningOnLinux, runningOnMono;
static bool runningOnWindows, runningOnUnix, runningOnX11, runningOnMacOS, runningOnLinux;
static bool runningOnMono;
static bool runningOnAndroid;
static bool? sdl2supported;
volatile static bool initialized;
readonly static object InitLock = new object();
@ -114,6 +117,26 @@ namespace OpenTK
#endregion
#region public static bool RunningOnAndroid
/// <summary>
/// Gets a <c>System.Boolean</c> indicating whether
/// OpenTK is running on an Android device.
/// </summary>
public static bool RunningOnAndroid
{
get
{
#if ANDROID
return true;
#else
return false;
#endif
}
}
#endregion
#region --- Private Methods ---
#region private static string DetectUnixKernel()

View file

@ -12,7 +12,7 @@ namespace OpenTK.Graphics.ES11
public sealed partial class GL : GraphicsBindingsBase
{
const string Library = "libGLES.dll";
const string Library = "GLESv1_CM";
static readonly object sync_root = new object();
#region --- Protected Members ---

View file

@ -180,6 +180,10 @@ namespace OpenTK.Input
get { return Wheel; }
}
/// <summary>
/// Gets a value indicating whether this instance is connected.
/// </summary>
/// <value><c>true</c> if this instance is connected; otherwise, <c>false</c>.</value>
public bool IsConnected
{
get { return is_connected; }

View file

@ -5,6 +5,7 @@
<dllmap os="linux" dll="alut.dll" target="libalut.so.0"/>
<dllmap os="linux" dll="opencl.dll" target="libOpenCL.so"/>
<dllmap os="linux" dll="libX11" target="libX11.so.6"/>
<dllmap os="linux" dll="libXi" target="libXi.so.6"/>
<dllmap os="linux" dll="SDL2.dll" target="libSDL2-2.0.so.0"/>
<dllmap os="osx" dll="openal32.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />
<dllmap os="osx" dll="alut.dll" target="/System/Library/Frameworks/OpenAL.framework/OpenAL" />

View file

@ -47,18 +47,18 @@ namespace OpenTK.Platform.MacOS
// Todo: keep track of which display adapter was specified when the context was created.
// IntPtr displayID;
GraphicsMode graphics_mode;
CarbonWindowInfo carbonWindow;
IntPtr shareContextRef;
DisplayDevice device;
bool mIsFullscreen = false;
readonly MacOSGraphicsMode ModeSelector = new MacOSGraphicsMode();
public AglContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext)
{
Debug.Print("Context Type: {0}", shareContext);
Debug.Print("Window info: {0}", window);
this.graphics_mode = mode;
this.carbonWindow = (CarbonWindowInfo)window;
if (shareContext is AglContext)
@ -105,50 +105,7 @@ namespace OpenTK.Platform.MacOS
}
void CreateContext(GraphicsMode mode, CarbonWindowInfo carbonWindow, IntPtr shareContextRef, bool fullscreen)
{
List<int> aglAttributes = new List<int>();
Debug.Print("AGL pixel format attributes:");
Debug.Indent();
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_RGBA);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_DOUBLEBUFFER);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_RED_SIZE, mode.ColorFormat.Red);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_GREEN_SIZE, mode.ColorFormat.Green);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_BLUE_SIZE, mode.ColorFormat.Blue);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ALPHA_SIZE, mode.ColorFormat.Alpha);
if (mode.Depth > 0)
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_DEPTH_SIZE, mode.Depth);
if (mode.Stencil > 0)
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_STENCIL_SIZE, mode.Stencil);
if (mode.AccumulatorFormat.BitsPerPixel > 0)
{
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ACCUM_RED_SIZE, mode.AccumulatorFormat.Red);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ACCUM_GREEN_SIZE, mode.AccumulatorFormat.Green);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ACCUM_BLUE_SIZE, mode.AccumulatorFormat.Blue);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ACCUM_ALPHA_SIZE, mode.AccumulatorFormat.Alpha);
}
if (mode.Samples > 1)
{
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_SAMPLE_BUFFERS_ARB, 1);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_SAMPLES_ARB, mode.Samples);
}
if (fullscreen)
{
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_FULLSCREEN);
}
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_NONE);
Debug.Unindent();
Debug.Write("Attribute array: ");
for (int i = 0; i < aglAttributes.Count; i++)
Debug.Write(aglAttributes[i].ToString() + " ");
Debug.WriteLine("");
AGLPixelFormat myAGLPixelFormat;
@ -166,11 +123,13 @@ namespace OpenTK.Platform.MacOS
if (status != OSStatus.NoError)
throw new MacOSException(status, "DMGetGDeviceByDisplayID failed.");
myAGLPixelFormat = Agl.aglChoosePixelFormat(ref gdevice, 1, aglAttributes.ToArray());
myAGLPixelFormat = ModeSelector.SelectPixelFormat(
mode.ColorFormat, mode.Depth, mode.Stencil, mode.Samples,
mode.AccumulatorFormat, mode.Buffers, mode.Stereo,
true, gdevice);
Agl.AglError err = Agl.GetError();
if (err == Agl.AglError.BadPixelFormat)
if (myAGLPixelFormat == IntPtr.Zero || err == Agl.AglError.BadPixelFormat)
{
Debug.Print("Failed to create full screen pixel format.");
Debug.Print("Trying again to create a non-fullscreen pixel format.");
@ -179,21 +138,23 @@ namespace OpenTK.Platform.MacOS
return;
}
}
else
{
myAGLPixelFormat = Agl.aglChoosePixelFormat(IntPtr.Zero, 0, aglAttributes.ToArray());
myAGLPixelFormat = ModeSelector.SelectPixelFormat(
mode.ColorFormat, mode.Depth, mode.Stencil, mode.Samples,
mode.AccumulatorFormat, mode.Buffers, mode.Stereo,
false, IntPtr.Zero);
MyAGLReportError("aglChoosePixelFormat");
}
Debug.Print("Creating AGL context. Sharing with {0}", shareContextRef);
// create the context and share it with the share reference.
Handle = new ContextHandle(Agl.aglCreateContext(myAGLPixelFormat, shareContextRef));
MyAGLReportError("aglCreateContext");
Mode = ModeSelector.GetGraphicsModeFromPixelFormat(myAGLPixelFormat);
// Free the pixel format from memory.
Agl.aglDestroyPixelFormat(myAGLPixelFormat);
MyAGLReportError("aglDestroyPixelFormat");
@ -205,7 +166,6 @@ namespace OpenTK.Platform.MacOS
Update(carbonWindow);
MakeCurrent(carbonWindow);
Debug.Print("context: {0}", Handle.Handle);
}
@ -290,10 +250,11 @@ namespace OpenTK.Platform.MacOS
windowPort = API.GetWindowPort(controlOwner);
}
else
{
windowPort = API.GetWindowPort(carbonWindow.Handle);
}
return windowPort;
}
public override void Update(IWindowInfo window)

View file

@ -76,7 +76,7 @@ namespace OpenTK.Platform.MacOS
public virtual IGraphicsMode CreateGraphicsMode()
{
return new MacOSGraphicsMode();
throw new NotSupportedException();
}
public virtual OpenTK.Input.IKeyboardDriver2 CreateKeyboardDriver()

View file

@ -42,15 +42,17 @@ namespace OpenTK.Platform.MacOS
public GraphicsMode SelectGraphicsMode(ColorFormat color, int depth, int stencil,
int samples, ColorFormat accum, int buffers, bool stereo)
{
IntPtr pixelformat = SelectPixelFormat(color, depth, stencil, samples, accum, buffers, stereo);
IntPtr pixelformat = SelectPixelFormat(
color, depth, stencil, samples, accum, buffers, stereo,
false, IntPtr.Zero);
return GetGraphicsModeFromPixelFormat(pixelformat);
}
#endregion
#region Private Members
#region Internal Members
GraphicsMode GetGraphicsModeFromPixelFormat(IntPtr pixelformat)
internal GraphicsMode GetGraphicsModeFromPixelFormat(IntPtr pixelformat)
{
int r, g, b, a;
Agl.aglDescribePixelFormat(pixelformat, Agl.PixelFormatAttribute.AGL_RED_SIZE, out r);
@ -73,8 +75,8 @@ namespace OpenTK.Platform.MacOS
depth, stencil, samples, new ColorFormat(ar, ag, ab, aa), buffers + 1, stereo != 0);
}
IntPtr SelectPixelFormat(ColorFormat color, int depth, int stencil, int samples,
ColorFormat accum, int buffers, bool stereo)
internal IntPtr SelectPixelFormat(ColorFormat color, int depth, int stencil, int samples,
ColorFormat accum, int buffers, bool stereo, bool fullscreen, IntPtr device)
{
List<int> attribs = new List<int>();
@ -140,14 +142,22 @@ namespace OpenTK.Platform.MacOS
attribs.Add((int)Agl.PixelFormatAttribute.AGL_STEREO);
}
if (fullscreen)
{
attribs.Add((int)Agl.PixelFormatAttribute.AGL_FULLSCREEN);
}
attribs.Add(0);
attribs.Add(0);
IntPtr pixelformat = Agl.aglChoosePixelFormat(IntPtr.Zero, 0, attribs.ToArray());
if (pixelformat == IntPtr.Zero)
IntPtr pixelformat = IntPtr.Zero;
if (device != IntPtr.Zero)
{
throw new GraphicsModeException(String.Format(
"[Error] Failed to select GraphicsMode, error {0}.", Agl.GetError()));
pixelformat = Agl.aglChoosePixelFormat(ref device, 0, attribs.ToArray());
}
else
{
pixelformat = Agl.aglChoosePixelFormat(IntPtr.Zero, 0, attribs.ToArray());
}
return pixelformat;
}

View file

@ -23,6 +23,9 @@
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//
using System.Runtime.InteropServices;
#endregion
using System;
@ -301,6 +304,9 @@ 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);
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_GetCurrentContext", ExactSpelling = true)]
public static extern IntPtr GetCurrentContext();
[SuppressUnmanagedCodeSecurity]
[DllImport(lib, CallingConvention = CallingConvention.Cdecl, EntryPoint = "SDL_GL_GetDrawableSize", ExactSpelling = true)]
public static extern void GetDrawableSize(IntPtr window, out int w, out int h);
@ -1177,6 +1183,25 @@ namespace OpenTK.Platform.SDL2
public uint Which;
public int X;
public int Y;
public enum EventType : uint
{
/* Touch events */
FingerDown = 0x700,
FingerUp,
FingerMotion,
/* Gesture events */
DollarGesture = 0x800,
DollarRecord,
MultiGesture,
}
public const uint TouchMouseID = 0xffffffff;
public static class GL
{
}
}
struct Rect

View file

@ -69,17 +69,7 @@ namespace OpenTK.Platform.SDL2
// so we need to implement our own.
return (GraphicsContext.GetCurrentContextDelegate)delegate
{
IntPtr current;
if (Configuration.RunningOnWindows)
current = OpenTK.Platform.Windows.Wgl.Imports.GetCurrentContext();
else if (Configuration.RunningOnX11)
current = OpenTK.Platform.X11.Glx.GetCurrentContext();
else if (Configuration.RunningOnMacOS)
current = OpenTK.Platform.MacOS.Cgl.GetCurrentContext();
else
throw new NotSupportedException("Unknown platform, please report to http://www.opentk.com");
return new ContextHandle(current);
return Sdl2GraphicsContext.GetCurrentContext();
};
}

View file

@ -65,16 +65,17 @@ namespace OpenTK.Platform.SDL2
{
SetGLAttributes(mode, shareContext, major, minor, flags);
SdlContext = new ContextHandle(SDL.GL.CreateContext(Window.Handle));
if (SdlContext == ContextHandle.Zero)
{
var error = SDL.GetError();
Debug.Print("SDL2 failed to create OpenGL context: {0}", error);
throw new GraphicsContextException(error);
}
Mode = GetGLAttributes(SdlContext, out flags);
Debug.Print("SDL2 created GraphicsContext (mode: {0}) (flags: {1}",
Debug.Print("SDL2 created GraphicsContext (mode: {0}) (flags: {1})",
Mode, flags);
}
if (SdlContext == ContextHandle.Zero)
{
var error = SDL.GetError();
Debug.Print("SDL2 failed to create OpenGL context: {0}", error);
throw new GraphicsContextException(error);
}
Handle = GraphicsContext.GetCurrentContext();
}
@ -254,6 +255,15 @@ namespace OpenTK.Platform.SDL2
#endregion
#region Public Members
public static ContextHandle GetCurrentContext()
{
return new ContextHandle(SDL.GL.GetCurrentContext());
}
#endregion
#region GraphicsContextBase Members
public override void SwapBuffers()

View file

@ -231,11 +231,14 @@ namespace OpenTK.Platform.X11
{
DebugBit = 0x0001,
ForwardCompatibleBit = 0x0002,
CoreProfileBit = 0x00000001,
CompatibilityProfileBit = 0x00000002,
MajorVersion = 0x2091,
MinorVersion = 0x2092,
LayerPlane = 0x2093,
Flags = 0x2094,
ErrorInvalidVersion = 0x2095,
ProfileMask = 0x9126
}
enum ErrorCode : int
@ -349,7 +352,7 @@ namespace OpenTK.Platform.X11
public partial class Arb
{
#region CreateContextAttribs
#region CreateContextAttri
unsafe public static IntPtr CreateContextAttribs(IntPtr display, IntPtr fbconfig, IntPtr share_context, bool direct, int* attribs)
{
@ -368,6 +371,19 @@ namespace OpenTK.Platform.X11
}
#endregion
#region GetProcAddress
// The linux OpenGL ABI 3.6 (1999) requires
// that glXGetProcAddressARB be available as
// a static export. The same is *not* true
// for glXGetProcAddress, so we should use
// glXGetProcAddressARB instead.
// See http://www.opengl.org/registry/ABI/
[DllImport(Library, EntryPoint = "glXGetProcAddressARB")]
public static extern IntPtr GetProcAddress([MarshalAs(UnmanagedType.LPTStr)] string procName);
#endregion
}
internal static partial class Delegates

View file

@ -20,17 +20,28 @@ namespace OpenTK.Platform.X11
const string Library = "libGL.so.1";
static readonly object sync_root = new object();
// Disable BeforeFieldInit optimization.
static Glx() { }
static Glx()
{
// GLX entry points are not bound to a context.
// This means we can load them without creating
// a context first! (unlike WGL)
// See
// for more details.
Debug.WriteLine("Loading GLX entry points.");
new Glx().LoadEntryPoints();
}
protected override object SyncRoot
{
get { return sync_root; }
}
protected override IntPtr GetAddress (string funcname)
protected override IntPtr GetAddress(string funcname)
{
return Glx.GetProcAddress(funcname);
// We must use glXGetProcAddressARB, *not*
// glXGetProcAddress. See comment on function
// signature.
return Glx.Arb.GetProcAddress(funcname);
}
#if false

View file

@ -77,7 +77,7 @@ namespace OpenTK.Platform.X11
public virtual IGraphicsMode CreateGraphicsMode()
{
return new X11GraphicsMode();
throw new NotSupportedException();
}
public virtual OpenTK.Input.IKeyboardDriver2 CreateKeyboardDriver()

View file

@ -31,7 +31,7 @@ namespace OpenTK.Platform.X11
X11WindowInfo currentWindow;
bool vsync_supported;
int swap_interval = 1; // As defined in GLX_SGI_swap_control
bool glx_loaded;
readonly X11GraphicsMode ModeSelector = new X11GraphicsMode();
#endregion
@ -45,14 +45,16 @@ namespace OpenTK.Platform.X11
if (window == null)
throw new ArgumentNullException("window");
Mode = mode;
Mode = ModeSelector.SelectGraphicsMode(
mode.ColorFormat, mode.Depth, mode.Stencil, mode.Samples,
mode.AccumulatorFormat, mode.Buffers, mode.Stereo);
// Do not move this lower, as almost everything requires the Display
// property to be correctly set.
Display = ((X11WindowInfo)window).Display;
currentWindow = (X11WindowInfo)window;
currentWindow.VisualInfo = SelectVisual(mode, currentWindow);
currentWindow.VisualInfo = SelectVisual(Mode, currentWindow);
ContextHandle shareHandle = shared != null ?
(shared as IGraphicsContextInternal).Context : (ContextHandle)IntPtr.Zero;
@ -62,40 +64,13 @@ namespace OpenTK.Platform.X11
Debug.WriteLine(shareHandle.Handle == IntPtr.Zero ? "not shared... " :
String.Format("shared with ({0})... ", shareHandle));
if (!glx_loaded)
{
Debug.WriteLine("Creating temporary context to load GLX extensions.");
// Create a temporary context to obtain the necessary function pointers.
XVisualInfo visual = currentWindow.VisualInfo;
IntPtr ctx = IntPtr.Zero;
using (new XLock(Display))
{
ctx = Glx.CreateContext(Display, ref visual, IntPtr.Zero, true);
if (ctx == IntPtr.Zero)
ctx = Glx.CreateContext(Display, ref visual, IntPtr.Zero, false);
}
if (ctx != IntPtr.Zero)
{
new Glx().LoadEntryPoints();
using (new XLock(Display))
{
Glx.MakeCurrent(Display, IntPtr.Zero, IntPtr.Zero);
//Glx.DestroyContext(Display, ctx);
}
glx_loaded = true;
}
}
// Try using the new context creation method. If it fails, fall back to the old one.
// For each of these methods, we try two times to create a context:
// one with the "direct" flag intact, the other with the flag inversed.
// HACK: It seems that Catalyst 9.1 - 9.4 on Linux have problems with contexts created through
// GLX_ARB_create_context, including hideous input lag, no vsync and other. Use legacy context
// creation if the user doesn't request a 3.0+ context.
if ((major * 10 + minor >= 30) && Glx.Delegates.glXCreateContextAttribsARB != null)
// GLX_ARB_create_context, including hideous input lag, no vsync and other madness.
// Use legacy context creation if the user doesn't request a 3.0+ context.
if ((major * 10 + minor >= 30) && SupportsCreateContextAttribs(Display, currentWindow))
{
Debug.Write("Using GLX_ARB_create_context... ");
@ -106,7 +81,7 @@ namespace OpenTK.Platform.X11
IntPtr* fbconfigs = Glx.ChooseFBConfig(Display, currentWindow.Screen,
new int[] {
(int)GLXAttribute.VISUAL_ID,
(int)mode.Index,
(int)Mode.Index,
0
}, out count);
@ -119,9 +94,10 @@ namespace OpenTK.Platform.X11
attributes.Add(minor);
if (flags != 0)
{
#warning "This is not entirely correct: Embedded is not a valid flag! We need to add a GetARBContextFlags(GraphicsContextFlags) method."
attributes.Add((int)ArbCreateContext.Flags);
attributes.Add((int)flags);
attributes.Add((int)GetARBContextFlags(flags));
attributes.Add((int)ArbCreateContext.ProfileMask);
attributes.Add((int)GetARBProfileFlags(flags));
}
// According to the docs, " <attribList> specifies a list of attributes for the context.
// The list consists of a sequence of <name,value> pairs terminated by the
@ -240,23 +216,46 @@ namespace OpenTK.Platform.X11
#endregion
bool SupportsExtension(X11WindowInfo window, string e)
ArbCreateContext GetARBContextFlags(GraphicsContextFlags flags)
{
ArbCreateContext result = 0;
result |= (flags & GraphicsContextFlags.Debug) != 0 ? ArbCreateContext.DebugBit : 0;
return result;
}
ArbCreateContext GetARBProfileFlags(GraphicsContextFlags flags)
{
ArbCreateContext result = 0;
result |= (flags & GraphicsContextFlags.ForwardCompatible) != 0 ?
ArbCreateContext.ForwardCompatibleBit : ArbCreateContext.CompatibilityProfileBit;
return result;
}
static bool SupportsExtension(IntPtr display, X11WindowInfo window, string e)
{
if (window == null)
throw new ArgumentNullException("window");
if (e == null)
throw new ArgumentNullException("e");
if (window.Display != Display)
if (window.Display != display)
throw new InvalidOperationException();
string extensions = null;
using (new XLock(Display))
using (new XLock(display))
{
extensions = Glx.QueryExtensionsString(Display, window.Screen);
extensions = Glx.QueryExtensionsString(display, window.Screen);
}
return !String.IsNullOrEmpty(extensions) && extensions.Contains(e);
}
static bool SupportsCreateContextAttribs(IntPtr display, X11WindowInfo window)
{
return
SupportsExtension(display, window, "GLX_ARB_create_context") &&
SupportsExtension(display, window, "GLX_ARB_create_context_profile") &&
Glx.Delegates.glXCreateContextAttribsARB != null;
}
#endregion
#region --- IGraphicsContext Members ---

View file

@ -144,7 +144,11 @@ namespace OpenTK.Platform.X11
using (new XLock(window.Display))
{
if (!mode.Index.HasValue)
throw new GraphicsModeException("Invalid or unsupported GraphicsMode.");
{
mode = new X11GraphicsMode().SelectGraphicsMode(
mode.ColorFormat, mode.Depth, mode.Stencil, mode.Samples,
mode.AccumulatorFormat, mode.Buffers, mode.Stereo);
}
info.VisualID = mode.Index.Value;
int dummy;
@ -1347,8 +1351,8 @@ namespace OpenTK.Platform.X11
public event EventHandler<EventArgs> WindowBorderChanged = delegate { };
public event EventHandler<EventArgs> WindowStateChanged = delegate { };
public event EventHandler<KeyboardKeyEventArgs> KeyDown = delegate { };
public event EventHandler<KeyPressEventArgs> KeyPress = delegate { };
public event EventHandler<KeyboardKeyEventArgs> KeyUp = delegate { };
public event EventHandler<KeyPressEventArgs> KeyPress = delegate { };
public event EventHandler<KeyboardKeyEventArgs> KeyUp = delegate { };
public event EventHandler<EventArgs> MouseEnter = delegate { };
public event EventHandler<EventArgs> MouseLeave = delegate { };