[Mac] Migrated AglContext to OpenTK.GLControl

This commit is contained in:
thefiddler 2014-04-24 01:14:40 +02:00
parent 3475582c30
commit cdd88e6f7e
20 changed files with 567 additions and 1600 deletions

View file

@ -377,8 +377,7 @@ namespace OpenTK.Platform.MacOS
if (retval == 0) if (retval == 0)
{ {
AglError err = GetError(); AglError err = GetError();
throw new Exception(ErrorString(err));
throw new MacOSException(err, ErrorString(err));
} }
} }
[DllImport(agl)] static extern byte aglSetOffScreen(AGLContext ctx, int width, int height, int rowbytes, IntPtr baseaddr); [DllImport(agl)] static extern byte aglSetOffScreen(AGLContext ctx, int width, int height, int rowbytes, IntPtr baseaddr);
@ -398,7 +397,7 @@ namespace OpenTK.Platform.MacOS
Debug.Print(ErrorString(err)); Debug.Print(ErrorString(err));
Debug.Unindent(); Debug.Unindent();
throw new MacOSException(err, ErrorString(err)); throw new Exception(ErrorString(err));
} }
} }
/* /*

View file

@ -42,28 +42,40 @@ namespace OpenTK.Platform.MacOS
using AGLContext = IntPtr; using AGLContext = IntPtr;
using AGLPbuffer = IntPtr; using AGLPbuffer = IntPtr;
class AglContext : DesktopGraphicsContext /// <summary>
/// AGL context implementation for WinForms compatibility.
/// </summary>
class AglContext : IGraphicsContext, IGraphicsContextInternal
{ {
// Todo: keep track of which display adapter was specified when the context was created. ContextHandle Handle;
// IntPtr displayID; GraphicsMode mode;
IWindowInfo carbonWindow;
IGraphicsContext dummyContext; // for extension loading
bool disposed;
bool error_checking;
CarbonWindowInfo carbonWindow; readonly GetInt XOffset;
IntPtr shareContextRef; readonly GetInt YOffset;
bool mIsFullscreen = false;
public AglContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext) public AglContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext,
GetInt xoffset, GetInt yoffset)
{ {
Debug.Print("Context Type: {0}", shareContext); Debug.Print("Share context: {0}", shareContext);
Debug.Print("Window info: {0}", window); Debug.Print("Window info: {0}", window);
IntPtr shareContextRef = IntPtr.Zero;
this.carbonWindow = (CarbonWindowInfo)window; XOffset = xoffset;
YOffset = yoffset;
carbonWindow = window;
if (shareContext is AglContext) if (shareContext is AglContext)
{
shareContextRef = ((AglContext)shareContext).Handle.Handle; shareContextRef = ((AglContext)shareContext).Handle.Handle;
if (shareContext is GraphicsContext) }
else if (shareContext is GraphicsContext)
{ {
ContextHandle shareHandle = shareContext != null ? (shareContext as IGraphicsContextInternal).Context : (ContextHandle)IntPtr.Zero; ContextHandle shareHandle = shareContext != null ? (shareContext as IGraphicsContextInternal).Context : (ContextHandle)IntPtr.Zero;
shareContextRef = shareHandle.Handle; shareContextRef = shareHandle.Handle;
} }
@ -75,24 +87,13 @@ namespace OpenTK.Platform.MacOS
CreateContext(mode, carbonWindow, shareContextRef, true); CreateContext(mode, carbonWindow, shareContextRef, true);
} }
public AglContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext)
{
if (handle == ContextHandle.Zero)
throw new ArgumentException("handle");
if (window == null)
throw new ArgumentNullException("window");
Handle = handle;
carbonWindow = (CarbonWindowInfo)window;
}
private void AddPixelAttrib(List<int> aglAttributes, Agl.PixelFormatAttribute pixelFormatAttribute) private void AddPixelAttrib(List<int> aglAttributes, Agl.PixelFormatAttribute pixelFormatAttribute)
{ {
Debug.Print(pixelFormatAttribute.ToString()); Debug.Print(pixelFormatAttribute.ToString());
aglAttributes.Add((int)pixelFormatAttribute); aglAttributes.Add((int)pixelFormatAttribute);
} }
private void AddPixelAttrib(List<int> aglAttributes, Agl.PixelFormatAttribute pixelFormatAttribute, int value) private void AddPixelAttrib(List<int> aglAttributes, Agl.PixelFormatAttribute pixelFormatAttribute, int value)
{ {
Debug.Print("{0} : {1}", pixelFormatAttribute, value); Debug.Print("{0} : {1}", pixelFormatAttribute, value);
@ -101,88 +102,58 @@ namespace OpenTK.Platform.MacOS
aglAttributes.Add(value); aglAttributes.Add(value);
} }
void CreateContext(GraphicsMode mode, CarbonWindowInfo carbonWindow, IntPtr shareContextRef, bool fullscreen) void CreateContext(GraphicsMode mode, IWindowInfo carbonWindow, IntPtr shareContextRef, bool fullscreen)
{ {
Debug.Print("AGL pixel format attributes:"); Debug.Print("AGL pixel format attributes:");
AGLPixelFormat myAGLPixelFormat;
// Choose a pixel format with the attributes we specified. // Choose a pixel format with the attributes we specified.
IntPtr gdevice; AGLPixelFormat pixelformat;
IntPtr cgdevice = GetQuartzDevice(carbonWindow); AglGraphicsMode selector = new AglGraphicsMode();
if (cgdevice == IntPtr.Zero)
cgdevice = (IntPtr)DisplayDevice.Default.Id;
OSStatus status = Carbon.API.DMGetGDeviceByDisplayID(cgdevice, out gdevice, false);
if (status != OSStatus.NoError)
throw new MacOSException(status, "DMGetGDeviceByDisplayID failed.");
IGraphicsMode selector = new MacOSGraphicsMode(gdevice);
Mode = selector.SelectGraphicsMode( Mode = selector.SelectGraphicsMode(
mode.ColorFormat, mode.Depth, mode.Stencil, mode.Samples, mode.ColorFormat, mode.Depth, mode.Stencil, mode.Samples,
mode.AccumulatorFormat, mode.Buffers, mode.Stereo); mode.AccumulatorFormat, mode.Buffers, mode.Stereo,
out pixelformat);
MyAGLReportError("aglChoosePixelFormat"); MyAGLReportError("aglChoosePixelFormat");
Debug.Print("Creating AGL context. Sharing with {0}", shareContextRef); Debug.Print("Creating AGL context. Sharing with {0}", shareContextRef);
myAGLPixelFormat = Mode.Index.Value;
// create the context and share it with the share reference. // create the context and share it with the share reference.
Handle = new ContextHandle(Agl.aglCreateContext(myAGLPixelFormat, shareContextRef)); Handle = new ContextHandle(Agl.aglCreateContext(pixelformat, shareContextRef));
MyAGLReportError("aglCreateContext"); MyAGLReportError("aglCreateContext");
// Free the pixel format from memory. // Free the pixel format from memory.
Agl.aglDestroyPixelFormat(myAGLPixelFormat); Agl.aglDestroyPixelFormat(pixelformat);
MyAGLReportError("aglDestroyPixelFormat"); MyAGLReportError("aglDestroyPixelFormat");
Debug.Print("IsControl: {0}", carbonWindow.IsControl);
SetDrawable(carbonWindow); SetDrawable(carbonWindow);
SetBufferRect(carbonWindow); SetBufferRect(carbonWindow);
Update(carbonWindow); Update(carbonWindow);
MakeCurrent(carbonWindow); MakeCurrent(carbonWindow);
Debug.Print("context: {0}", Handle.Handle); Debug.Print("context: {0}", Handle.Handle);
dummyContext = new GraphicsContext(Handle,
GetAddress,
delegate()
{
return new ContextHandle(Agl.aglGetCurrentContext());
});
} }
private IntPtr GetQuartzDevice(CarbonWindowInfo carbonWindow) void SetBufferRect(IWindowInfo carbonWindow)
{ {
IntPtr windowRef = carbonWindow.Handle; Rect rect = API.GetControlBounds(carbonWindow.Handle);
if (CarbonGLNative.WindowRefMap.ContainsKey(windowRef) == false)
return IntPtr.Zero;
WeakReference nativeRef = CarbonGLNative.WindowRefMap[windowRef];
if (nativeRef.IsAlive == false)
return IntPtr.Zero;
CarbonGLNative window = nativeRef.Target as CarbonGLNative;
if (window == null)
return IntPtr.Zero;
return QuartzDisplayDeviceDriver.HandleTo(window.TargetDisplayDevice);
}
void SetBufferRect(CarbonWindowInfo carbonWindow)
{
if (carbonWindow.IsControl == false)
return;
Rect rect = API.GetControlBounds(carbonWindow.WindowHandle);
Debug.Print("Setting buffer_rect for control."); Debug.Print("Setting buffer_rect for control.");
Debug.Print("MacOS Coordinate Rect: {0}", rect); Debug.Print("MacOS Coordinate Rect: {0}", rect);
int[] glrect = new int[4]; int[] glrect = new int[4];
if (carbonWindow.XOffset != null) if (XOffset != null)
glrect[0] = rect.X + carbonWindow.XOffset(); glrect[0] = rect.X + XOffset();
else else
glrect[0] = rect.X; glrect[0] = rect.X;
if (carbonWindow.YOffset != null) if (YOffset != null)
glrect[1] = rect.Y + carbonWindow.YOffset(); glrect[1] = rect.Y + YOffset();
else else
glrect[1] = rect.Y; glrect[1] = rect.Y;
glrect[2] = rect.Width; glrect[2] = rect.Width;
@ -194,144 +165,53 @@ namespace OpenTK.Platform.MacOS
Agl.aglEnable(Handle.Handle, Agl.ParameterNames.AGL_BUFFER_RECT); Agl.aglEnable(Handle.Handle, Agl.ParameterNames.AGL_BUFFER_RECT);
MyAGLReportError("aglEnable"); MyAGLReportError("aglEnable");
} }
void SetDrawable(CarbonWindowInfo carbonWindow)
void SetDrawable(IWindowInfo carbonWindow)
{ {
IntPtr windowPort = GetWindowPortForWindowInfo(carbonWindow); IntPtr windowPort = GetWindowPortForWindowInfo(carbonWindow);
//Debug.Print("Setting drawable for context {0} to window port: {1}", Handle.Handle, windowPort); //Debug.Print("Setting drawable for context {0} to window port: {1}", Handle.Handle, windowPort);
Agl.aglSetDrawable(Handle.Handle, windowPort); Agl.aglSetDrawable(Handle.Handle, windowPort);
MyAGLReportError("aglSetDrawable"); MyAGLReportError("aglSetDrawable");
} }
private static IntPtr GetWindowPortForWindowInfo(CarbonWindowInfo carbonWindow) private static IntPtr GetWindowPortForWindowInfo(IWindowInfo carbonWindow)
{ {
IntPtr windowPort; IntPtr windowPort;
if (carbonWindow.IsControl)
{
IntPtr controlOwner = API.GetControlOwner(carbonWindow.Handle); IntPtr controlOwner = API.GetControlOwner(carbonWindow.Handle);
windowPort = API.GetWindowPort(controlOwner); windowPort = API.GetWindowPort(controlOwner);
}
else
{
windowPort = API.GetWindowPort(carbonWindow.Handle);
}
return windowPort; return windowPort;
} }
public override void Update(IWindowInfo window)
public void Update(IWindowInfo window)
{ {
CarbonWindowInfo carbonWindow = (CarbonWindowInfo)window; SetDrawable(window);
SetBufferRect(window);
if (carbonWindow.GoFullScreenHack)
{
carbonWindow.GoFullScreenHack = false;
CarbonGLNative wind = GetCarbonWindow(carbonWindow);
if (wind != null)
wind.SetFullscreen(this);
else
Debug.Print("Could not find window!");
return;
}
else if (carbonWindow.GoWindowedHack)
{
carbonWindow.GoWindowedHack = false;
CarbonGLNative wind = GetCarbonWindow(carbonWindow);
if (wind != null)
wind.UnsetFullscreen(this);
else
Debug.Print("Could not find window!");
}
if (mIsFullscreen)
return;
SetDrawable(carbonWindow);
SetBufferRect(carbonWindow);
Agl.aglUpdateContext(Handle.Handle); Agl.aglUpdateContext(Handle.Handle);
} }
private CarbonGLNative GetCarbonWindow(CarbonWindowInfo carbonWindow)
{
WeakReference r = CarbonGLNative.WindowRefMap[carbonWindow.Handle];
if (r.IsAlive)
{
return (CarbonGLNative)r.Target;
}
else
return null;
}
void MyAGLReportError(string function) void MyAGLReportError(string function)
{ {
Agl.AglError err = Agl.GetError(); Agl.AglError err = Agl.GetError();
if (err != Agl.AglError.NoError) if (err != Agl.AglError.NoError)
throw new MacOSException((OSStatus)err, string.Format("AGL Error from function {0}: {1} {2}", function, err, Agl.ErrorString(err))); throw new Exception(String.Format(
"AGL Error from function {0}: {1} {2}",
function, err, Agl.ErrorString(err)));
} }
bool firstFullScreen = false;
internal void SetFullScreen(CarbonWindowInfo info, out int width, out int height)
{
CarbonGLNative wind = GetCarbonWindow(info);
Debug.Print("Switching to full screen {0}x{1} on context {2}", wind.TargetDisplayDevice.Width, wind.TargetDisplayDevice.Height, Handle.Handle);
CG.DisplayCapture(GetQuartzDevice(info));
Agl.aglSetFullScreen(Handle.Handle, wind.TargetDisplayDevice.Width, wind.TargetDisplayDevice.Height, 0, 0);
MakeCurrent(info);
width = wind.TargetDisplayDevice.Width;
height = wind.TargetDisplayDevice.Height;
// This is a weird hack to workaround a bug where the first time a context
// is made fullscreen, we just end up with a blank screen. So we undo it as fullscreen
// and redo it as fullscreen.
if (firstFullScreen == false)
{
firstFullScreen = true;
UnsetFullScreen(info);
SetFullScreen(info, out width, out height);
}
mIsFullscreen = true;
}
internal void UnsetFullScreen(CarbonWindowInfo windowInfo)
{
Debug.Print("Unsetting AGL fullscreen.");
Agl.aglSetDrawable(Handle.Handle, IntPtr.Zero);
Agl.aglUpdateContext(Handle.Handle);
CG.DisplayRelease(GetQuartzDevice(windowInfo));
Debug.Print("Resetting drawable.");
SetDrawable(windowInfo);
mIsFullscreen = false;
}
#region IGraphicsContext Members #region IGraphicsContext Members
bool firstSwap = false; bool firstSwap = true;
public override void SwapBuffers() public void SwapBuffers()
{ {
// this is part of the hack to avoid dropping the first frame when // this is part of the hack to avoid dropping the first frame when
// using multiple GLControls. // using multiple GLControls.
if (firstSwap == false && carbonWindow.IsControl) if (firstSwap)
{ {
Debug.WriteLine("--> Resetting drawable. <--"); Debug.WriteLine("--> Resetting drawable. <--");
firstSwap = true; firstSwap = false;
SetDrawable(carbonWindow); SetDrawable(carbonWindow);
Update(carbonWindow); Update(carbonWindow);
} }
@ -340,20 +220,21 @@ namespace OpenTK.Platform.MacOS
MyAGLReportError("aglSwapBuffers"); MyAGLReportError("aglSwapBuffers");
} }
public override void MakeCurrent(IWindowInfo window) public void MakeCurrent(IWindowInfo window)
{ {
if (Agl.aglSetCurrentContext(Handle.Handle) == false) if (Agl.aglSetCurrentContext(Handle.Handle) == false)
MyAGLReportError("aglSetCurrentContext"); MyAGLReportError("aglSetCurrentContext");
} }
public override bool IsCurrent public bool IsCurrent
{ {
get { return (Handle.Handle == Agl.aglGetCurrentContext()); } get { return (Handle.Handle == Agl.aglGetCurrentContext()); }
} }
public override int SwapInterval public int SwapInterval
{
get
{ {
get {
int swap_interval = 0; int swap_interval = 0;
if (Agl.aglGetInteger(Handle.Handle, Agl.ParameterNames.AGL_SWAP_INTERVAL, out swap_interval)) if (Agl.aglGetInteger(Handle.Handle, Agl.ParameterNames.AGL_SWAP_INTERVAL, out swap_interval))
{ {
@ -372,6 +253,64 @@ namespace OpenTK.Platform.MacOS
} }
} }
public GraphicsMode Mode
{
get
{
return mode;
}
set
{
mode = value;
}
}
public void LoadAll()
{
dummyContext.LoadAll();
}
public bool IsDisposed
{
get
{
return disposed;
}
}
public bool VSync
{
get
{
return SwapInterval != 0;
}
set
{
SwapInterval = value ? 1 : 0;
}
}
public GraphicsMode GraphicsMode
{
get
{
return mode;
}
}
public bool ErrorChecking
{
get
{
return error_checking;
}
set
{
error_checking = value;
}
}
#endregion #endregion
#region IDisposable Members #region IDisposable Members
@ -381,7 +320,7 @@ namespace OpenTK.Platform.MacOS
Dispose(false); Dispose(false);
} }
public override void Dispose() public void Dispose()
{ {
Dispose(true); Dispose(true);
} }
@ -418,26 +357,42 @@ namespace OpenTK.Platform.MacOS
// don't throw an exception from the finalizer thread. // don't throw an exception from the finalizer thread.
if (disposing) if (disposing)
{ {
throw new MacOSException((OSStatus)Agl.GetError(), Agl.ErrorString(Agl.GetError())); throw new Exception(Agl.ErrorString(Agl.GetError()));
} }
IsDisposed = true; disposed = true;
} }
#endregion #endregion
#region IGraphicsContextInternal Members #region IGraphicsContextInternal Members
public override IntPtr GetAddress(string function) public IntPtr GetAddress(string function)
{ {
return NS.GetAddress(function); return NS.GetAddress(function);
} }
public override IntPtr GetAddress(IntPtr function) public IntPtr GetAddress(IntPtr function)
{ {
return NS.GetAddress(function); return NS.GetAddress(function);
} }
public IGraphicsContext Implementation
{
get
{
return this;
}
}
public ContextHandle Context
{
get
{
return Handle;
}
}
#endregion #endregion
} }
} }

View file

@ -33,46 +33,23 @@ using OpenTK.Graphics;
namespace OpenTK.Platform.MacOS namespace OpenTK.Platform.MacOS
{ {
using Carbon; class AglGraphicsMode
class MacOSGraphicsMode : IGraphicsMode
{ {
readonly IntPtr Device;
public MacOSGraphicsMode(IntPtr device)
{
Device = device;
}
#region IGraphicsMode Members
public GraphicsMode SelectGraphicsMode(ColorFormat color, int depth, int stencil, 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, out IntPtr pixelformat)
{ {
IntPtr pixelformat;
do do
{ {
pixelformat = SelectPixelFormat( pixelformat = SelectPixelFormat(
color, depth, stencil, samples, accum, buffers, stereo, color, depth, stencil, samples, accum, buffers, stereo);
true, Device);
Agl.AglError err = Agl.GetError();
if (pixelformat == 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.");
pixelformat = SelectPixelFormat(
color, depth, stencil, samples, accum, buffers, stereo,
false, IntPtr.Zero);
}
if (pixelformat == IntPtr.Zero) if (pixelformat == IntPtr.Zero)
{ {
if (!Utilities.RelaxGraphicsMode( if (!RelaxGraphicsMode(
ref color, ref depth, ref stencil, ref samples, ref accum, ref color, ref depth, ref stencil, ref samples, ref accum,
ref buffers, ref stereo)) ref buffers, ref stereo))
{ {
throw new GraphicsModeException("Requested GraphicsMode not available."); throw new GraphicsModeException("Requested GraphicsMode not available, error: " + Agl.GetError());
} }
} }
} }
@ -81,10 +58,76 @@ namespace OpenTK.Platform.MacOS
return GetGraphicsModeFromPixelFormat(pixelformat); return GetGraphicsModeFromPixelFormat(pixelformat);
} }
#endregion
#region Internal Members #region Internal Members
static bool RelaxGraphicsMode(ref ColorFormat color, ref int depth, ref int stencil, ref int samples, ref ColorFormat accum, ref int buffers, ref bool stereo)
{
// Parameters are relaxed in order of importance.
// - Accumulator buffers are way outdated as a concept,
// so they go first.
// - Triple+ buffering is generally not supported by the
// core WGL/GLX/AGL/CGL/EGL specs, so we clamp
// to double-buffering as a second step. (If this doesn't help
// we will also fall back to undefined single/double buffering
// as a last resort).
// - AA samples are an easy way to increase compatibility
// so they go next.
// - Stereoscopic is only supported on very few GPUs
// (Quadro/FirePro series) so it goes next.
// - The rest of the parameters then follow.
if (accum != 0)
{
accum = 0;
return true;
}
if (buffers > 2)
{
buffers = 2;
return true;
}
if (samples > 0)
{
samples = Math.Max(samples - 1, 0);
return true;
}
if (stereo)
{
stereo = false;
return true;
}
if (stencil != 0)
{
stencil = 0;
return true;
}
if (depth != 0)
{
depth = 0;
return true;
}
if (color != 24)
{
color = 24;
return true;
}
if (buffers != 0)
{
buffers = 0;
return true;
}
// no parameters left to relax, fail
return false;
}
GraphicsMode GetGraphicsModeFromPixelFormat(IntPtr pixelformat) GraphicsMode GetGraphicsModeFromPixelFormat(IntPtr pixelformat)
{ {
int r, g, b, a; int r, g, b, a;
@ -104,12 +147,12 @@ namespace OpenTK.Platform.MacOS
Agl.aglDescribePixelFormat(pixelformat, Agl.PixelFormatAttribute.AGL_DOUBLEBUFFER, out buffers); Agl.aglDescribePixelFormat(pixelformat, Agl.PixelFormatAttribute.AGL_DOUBLEBUFFER, out buffers);
Agl.aglDescribePixelFormat(pixelformat, Agl.PixelFormatAttribute.AGL_STEREO, out stereo); Agl.aglDescribePixelFormat(pixelformat, Agl.PixelFormatAttribute.AGL_STEREO, out stereo);
return new GraphicsMode(pixelformat, new ColorFormat(r, g, b, a), return new GraphicsMode(new ColorFormat(r, g, b, a),
depth, stencil, samples, new ColorFormat(ar, ag, ab, aa), buffers + 1, stereo != 0); depth, stencil, samples, new ColorFormat(ar, ag, ab, aa), buffers + 1, stereo != 0);
} }
IntPtr SelectPixelFormat(ColorFormat color, int depth, int stencil, int samples, IntPtr SelectPixelFormat(ColorFormat color, int depth, int stencil, int samples,
ColorFormat accum, int buffers, bool stereo, bool fullscreen, IntPtr device) ColorFormat accum, int buffers, bool stereo)
{ {
List<int> attribs = new List<int>(); List<int> attribs = new List<int>();
@ -144,7 +187,7 @@ namespace OpenTK.Platform.MacOS
attribs.Add((int)Agl.PixelFormatAttribute.AGL_DOUBLEBUFFER); attribs.Add((int)Agl.PixelFormatAttribute.AGL_DOUBLEBUFFER);
} }
if (stencil > 1) if (stencil > 0)
{ {
attribs.Add((int)Agl.PixelFormatAttribute.AGL_STENCIL_SIZE); attribs.Add((int)Agl.PixelFormatAttribute.AGL_STENCIL_SIZE);
attribs.Add(stencil); attribs.Add(stencil);
@ -175,23 +218,10 @@ namespace OpenTK.Platform.MacOS
attribs.Add((int)Agl.PixelFormatAttribute.AGL_STEREO); attribs.Add((int)Agl.PixelFormatAttribute.AGL_STEREO);
} }
if (fullscreen)
{
attribs.Add((int)Agl.PixelFormatAttribute.AGL_FULLSCREEN);
}
attribs.Add(0); attribs.Add(0);
attribs.Add(0); attribs.Add(0);
IntPtr pixelformat = IntPtr.Zero; IntPtr pixelformat = Agl.aglChoosePixelFormat(IntPtr.Zero, 0, attribs.ToArray());
if (device != IntPtr.Zero)
{
pixelformat = Agl.aglChoosePixelFormat(ref device, 0, attribs.ToArray());
}
else
{
pixelformat = Agl.aglChoosePixelFormat(IntPtr.Zero, 0, attribs.ToArray());
}
return pixelformat; return pixelformat;
} }

160
Source/GLControl/Carbon.cs Normal file
View file

@ -0,0 +1,160 @@
using System;
using System.Drawing;
using System.Runtime.InteropServices;
namespace OpenTK.Platform.MacOS.Carbon
{
internal enum OSStatus
{
NoError = 0,
ParameterError = -50, /*error in user parameter list*/
NoHardwareError = -200, /*Sound Manager Error Returns*/
NotEnoughHardwareError = -201, /*Sound Manager Error Returns*/
UserCanceledError = -128,
QueueError = -1, /*queue element not found during deletion*/
VTypErr = -2, /*invalid queue element*/
CorErr = -3, /*core routine number out of range*/
UnimpErr = -4, /*unimplemented core routine*/
SlpTypeErr = -5, /*invalid queue element*/
SeNoDB = -8, /*no debugger installed to handle debugger command*/
ControlErr = -17, /*I/O System Errors*/
StatusErr = -18, /*I/O System Errors*/
ReadErr = -19, /*I/O System Errors*/
WritErr = -20, /*I/O System Errors*/
BadUnitErr = -21, /*I/O System Errors*/
UnitEmptyErr = -22, /*I/O System Errors*/
OpenErr = -23, /*I/O System Errors*/
ClosErr = -24, /*I/O System Errors*/
DRemovErr = -25, /*tried to remove an open driver*/
DInstErr = -26, /*DrvrInstall couldn't find driver in resources*/
// Window Manager result codes.
InvalidWindowPtr = -5600,
UnsupportedWindowAttributesForClass = -5601,
WindowDoesNotHaveProxy = -5602,
WindowPropertyNotFound = -5604,
UnrecognizedWindowClass = -5605,
CorruptWindowDescription = -5606,
UserWantsToDragWindow = -5607,
WindowsAlreadyInitialized = -5608,
FloatingWindowsNotInitialized = -5609,
WindowNotFound = -5610,
WindowDoesNotFitOnscreen = -5611,
WindowAttributeImmutable = -5612,
WindowAttributesConflict = -5613,
WindowManagerInternalError = -5614,
WindowWrongState = -5615,
WindowGroupInvalid = -5616,
WindowAppModalStateAlreadyExists = -5617,
WindowNoAppModalState = -5618,
WindowDoesntSupportFocus = -30583,
WindowRegionCodeInvalid = -30593,
// Event Manager result codes
EventAlreadyPosted = -9860,
EventTargetBusy = -9861,
EventDeferAccessibilityEvent = -9865,
EventInternalError = -9868,
EventParameterNotFound = -9870,
EventNotHandled = -9874,
EventLoopTimedOut = -9875,
EventLoopQuit = -9876,
EventNotInQueue = -9877,
HotKeyExists = -9878,
EventPassToNextTarget = -9880
}
[StructLayout(LayoutKind.Sequential)]
internal struct Rect
{
short top;
short left;
short bottom;
short right;
internal Rect(int left, int top, int width, int height)
: this((short)left, (short)top, (short)width, (short)height)
{
}
internal Rect(short _left, short _top, short _width, short _height)
{
top = _top;
left = _left;
bottom = (short)(_top + _height);
right = (short)(_left + _width);
}
internal short X
{
get { return left; }
set
{
short width = Width;
left = value;
right = (short)(left + width);
}
}
internal short Y
{
get { return top; }
set
{
short height = Height;
top = value;
bottom = (short)(top + height);
}
}
internal short Width
{
get { return (short)(right - left); }
set { right = (short)(left + value); }
}
internal short Height
{
get { return (short)(bottom - top); }
set { bottom = (short)(top + value); }
}
public override string ToString()
{
return string.Format(
"Rect: [{0}, {1}, {2}, {3}]", X, Y, Width, Height);
}
public Rectangle ToRectangle()
{
return new Rectangle(X, Y, Width, Height);
}
}
class API
{
const string carbon = "/System/Library/Frameworks/Carbon.framework/Versions/Current/Carbon";
[DllImport(carbon)]
internal unsafe static extern OSStatus DMGetGDeviceByDisplayID(
IntPtr displayID, out IntPtr displayDevice, Boolean failToMain);
[DllImport(carbon)]
static extern IntPtr GetControlBounds(IntPtr control, out Rect bounds);
internal static Rect GetControlBounds(IntPtr control)
{
Rect retval;
GetControlBounds(control, out retval);
return retval;
}
[DllImport(carbon)]
internal static extern IntPtr GetControlOwner(IntPtr control);
[DllImport(carbon)]
internal static extern IntPtr GetWindowPort(IntPtr windowRef);
}
}

View file

@ -32,6 +32,7 @@ using System.Windows.Forms;
using OpenTK.Graphics; using OpenTK.Graphics;
using OpenTK.Platform; using OpenTK.Platform;
using OpenTK.Platform.MacOS;
namespace OpenTK namespace OpenTK
{ {
@ -46,7 +47,7 @@ namespace OpenTK
this.mode = mode; this.mode = mode;
this.control = owner; this.control = owner;
window_info = Utilities.CreateMacOSCarbonWindowInfo(control.Handle, false, true, GetXOffset, GetYOffset); window_info = Utilities.CreateMacOSCarbonWindowInfo(control.Handle, false, true);
} }
private int GetXOffset() private int GetXOffset()
@ -70,7 +71,8 @@ namespace OpenTK
public IGraphicsContext CreateContext(int major, int minor, GraphicsContextFlags flags) public IGraphicsContext CreateContext(int major, int minor, GraphicsContextFlags flags)
{ {
return new GraphicsContext(mode, WindowInfo, major, minor, flags); // AGL does not support OpenGL profiles
return new AglContext(mode, WindowInfo, GraphicsContext.CurrentContext, GetXOffset, GetYOffset);
} }
// TODO: Fix this // TODO: Fix this

113
Source/GLControl/NS.cs Normal file
View file

@ -0,0 +1,113 @@
#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);
[DllImport(Library)]
private static extern IntPtr dlopen(String fileName, int flags);
[DllImport(Library)]
private static extern int dlclose(IntPtr handle);
[DllImport (Library)]
private static extern IntPtr dlsym (IntPtr handle, string 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;
}
public static IntPtr GetSymbol(IntPtr handle, string symbol)
{
return dlsym(handle, symbol);
}
public static IntPtr LoadLibrary(string fileName)
{
const int RTLD_NOW = 2;
return dlopen(fileName, RTLD_NOW);
}
public static void FreeLibrary(IntPtr handle)
{
dlclose(handle);
}
}
}

View file

@ -162,6 +162,22 @@
<Compile Include="Properties\AssemblyInfo.cs"> <Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Include="Agl.cs">
<DependentUpon>CarbonGLControl.cs</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="AglContext.cs">
<DependentUpon>CarbonGLControl.cs</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="AglGraphicsMode.cs">
<DependentUpon>CarbonGLControl.cs</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="Carbon.cs" />
<Compile Include="NS.cs">
<DependentUpon>CarbonGLControl.cs</DependentUpon>
</Compile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="..\..\OpenTK.snk"> <None Include="..\..\OpenTK.snk">

View file

@ -282,9 +282,6 @@
<Compile Include="Platform\MacOS\EventInfo.cs"> <Compile Include="Platform\MacOS\EventInfo.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Include="Platform\MacOS\MacOSGraphicsMode.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Platform\MacOS\MacOSFactory.cs"> <Compile Include="Platform\MacOS\MacOSFactory.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
@ -294,42 +291,12 @@
<Compile Include="Platform\MacOS\MacOSKeyMap.cs"> <Compile Include="Platform\MacOS\MacOSKeyMap.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Include="Platform\MacOS\CarbonGLNative.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Platform\MacOS\Application.cs"> <Compile Include="Platform\MacOS\Application.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Include="Platform\MacOS\AglContext.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Platform\MacOS\QuartzDisplayDeviceDriver.cs"> <Compile Include="Platform\MacOS\QuartzDisplayDeviceDriver.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
<Compile Include="Platform\MacOS\CarbonInput.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Platform\MacOS\CarbonWindowInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Platform\MacOS\CarbonBindings\CarbonAPI.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Platform\MacOS\CarbonBindings\SpeechChannel.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Platform\MacOS\CarbonBindings\QuartzDisplayServicesAPI.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Platform\MacOS\CarbonBindings\MacOSKeys.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Platform\MacOS\CarbonBindings\Agl.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Platform\MacOS\CarbonBindings\CoreFoundation.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Platform\Windows\WinRawKeyboard.cs"> <Compile Include="Platform\Windows\WinRawKeyboard.cs">
<SubType>Code</SubType> <SubType>Code</SubType>
</Compile> </Compile>
@ -820,7 +787,25 @@
<Compile Include="Platform\MacOS\Cocoa\NSEventModifierMask.cs" /> <Compile Include="Platform\MacOS\Cocoa\NSEventModifierMask.cs" />
<Compile Include="Platform\MacOS\Cocoa\NSTrackingAreaOptions.cs" /> <Compile Include="Platform\MacOS\Cocoa\NSTrackingAreaOptions.cs" />
<Compile Include="Platform\MacOS\Cocoa\NSApplicationPresentationOptions.cs" /> <Compile Include="Platform\MacOS\Cocoa\NSApplicationPresentationOptions.cs" />
<Compile Include="Platform\MacOS\CarbonBindings\Cgl.cs" /> <Compile Include="Platform\MacOS\CarbonWindowInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Platform\MacOS\Carbon\CarbonAPI.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Platform\MacOS\Carbon\SpeechChannel.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Platform\MacOS\Carbon\QuartzDisplayServicesAPI.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Platform\MacOS\Carbon\MacOSKeys.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Platform\MacOS\Carbon\CoreFoundation.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Platform\MacOS\Carbon\Cgl.cs" />
</ItemGroup> </ItemGroup>
<Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
<PropertyGroup> <PropertyGroup>

View file

@ -39,7 +39,6 @@ namespace OpenTK.Platform.MacOS.Carbon
{ {
static bool mInitialized = false; static bool mInitialized = false;
static IntPtr uppHandler; static IntPtr uppHandler;
static CarbonGLNative eventHandler;
static int osMajor, osMinor, osBugfix; static int osMajor, osMinor, osBugfix;
static Application() static Application()
@ -76,12 +75,6 @@ namespace OpenTK.Platform.MacOS.Carbon
API.SetFrontProcess(ref psn); API.SetFrontProcess(ref psn);
} }
static internal CarbonGLNative WindowEventHandler
{
get { return eventHandler; }
set { eventHandler = value; }
}
static void ConnectEvents() static void ConnectEvents()
{ {
@ -131,36 +124,16 @@ namespace OpenTK.Platform.MacOS.Carbon
return OSStatus.EventNotHandled; return OSStatus.EventNotHandled;
} }
case EventClass.AppleEvent: case EventClass.AppleEvent:
// only event here is the apple event. // only event here is the apple event.
Debug.Print("Processing apple event."); Debug.Print("Processing apple event.");
API.ProcessAppleEvent(inEvent); API.ProcessAppleEvent(inEvent);
break; break;
case EventClass.Keyboard:
case EventClass.Mouse:
if (WindowEventHandler != null)
{
return WindowEventHandler.DispatchEvent(inCaller, inEvent, evt, userData);
}
break;
} }
return OSStatus.EventNotHandled; return OSStatus.EventNotHandled;
} }
public static void Run(CarbonGLNative window)
{
window.Closed += MainWindowClosed;
window.Visible = true;
API.RunApplicationEventLoop();
window.Closed -= MainWindowClosed;
}
static void MainWindowClosed(object sender, EventArgs e) static void MainWindowClosed(object sender, EventArgs e)
{ {
Debug.Print("Quitting application event loop."); Debug.Print("Quitting application event loop.");

File diff suppressed because it is too large Load diff

View file

@ -1,122 +0,0 @@
#region License
//
// The Open Toolkit Library License
//
// Copyright (c) 2006 - 2010 the Open Toolkit library.
//
// 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.Diagnostics;
using System.Text;
namespace OpenTK.Platform.MacOS
{
using Input;
class CarbonInput : IInputDriver, IInputDriver2
{
List<KeyboardDevice> dummy_keyboard_list = new List<KeyboardDevice>(1);
List<MouseDevice> dummy_mice_list = new List<MouseDevice>(1);
List<JoystickDevice> dummy_joystick_list = new List<JoystickDevice>(1);
internal CarbonInput()
{
dummy_mice_list.Add(new MouseDevice());
dummy_keyboard_list.Add(new KeyboardDevice());
dummy_joystick_list.Add(new JoystickDevice<object>(0, 0, 0));
}
#region IInputDriver Members
public void Poll()
{
}
#endregion
#region IKeyboardDriver Members
public IList<KeyboardDevice> Keyboard
{
get { return dummy_keyboard_list; }
}
#endregion
#region IMouseDriver Members
public IList<MouseDevice> Mouse
{
get { return dummy_mice_list; }
}
#endregion
#region IJoystickDriver Members
public IList<JoystickDevice> Joysticks
{
get { return dummy_joystick_list; }
}
#endregion
#region IDisposable Members
public void Dispose()
{
}
#endregion
public IMouseDriver2 MouseDriver
{
get
{
throw new NotImplementedException();
}
}
public IKeyboardDriver2 KeyboardDriver
{
get
{
throw new NotImplementedException();
}
}
public IGamePadDriver GamePadDriver
{
get
{
throw new NotImplementedException();
}
}
public IJoystickDriver2 JoystickDriver
{
get { throw new NotImplementedException(); }
}
}
}

View file

@ -32,13 +32,6 @@ using System.Text;
namespace OpenTK.Platform.MacOS namespace OpenTK.Platform.MacOS
{ {
/// <summary>
/// This delegate represents any method that takes no arguments and returns an int.
/// I would have used Func but that requires .NET 4
/// </summary>
/// <returns>The int value that your method returns</returns>
public delegate int GetInt();
/// \internal /// \internal
/// <summary> /// <summary>
/// Describes a Carbon window. /// Describes a Carbon window.
@ -48,7 +41,7 @@ namespace OpenTK.Platform.MacOS
IntPtr windowRef; IntPtr windowRef;
bool ownHandle = false; bool ownHandle = false;
bool disposed = false; bool disposed = false;
bool isControl = false; bool isControl = true;
bool goFullScreenHack = false; bool goFullScreenHack = false;
bool goWindowedHack = false; bool goWindowedHack = false;

View file

@ -47,7 +47,7 @@ namespace OpenTK.Platform.MacOS
{ {
this.errorCode = errorCode; this.errorCode = errorCode;
} }
internal MacOSException(Agl.AglError errorCode, string message) internal MacOSException(int errorCode, string message)
: base(message) : base(message)
{ {
this.errorCode = (OSStatus)errorCode; this.errorCode = (OSStatus)errorCode;

View file

@ -18,6 +18,16 @@ using OpenTK.Graphics;
namespace OpenTK.Platform namespace OpenTK.Platform
{ {
namespace MacOS
{
/// <summary>
/// This delegate represents any method that takes no arguments and returns an int.
/// I would have used Func but that requires .NET 4
/// </summary>
/// <returns>The int value that your method returns</returns>
public delegate int GetInt();
}
/// <summary> /// <summary>
/// Provides cross-platform utilities to help interact with the underlying platform. /// Provides cross-platform utilities to help interact with the underlying platform.
/// </summary> /// </summary>