mirror of
https://github.com/Ryujinx/Opentk.git
synced 2025-06-19 07:28:02 +00:00
[Mac] Migrated AglContext to OpenTK.GLControl
This commit is contained in:
parent
3475582c30
commit
cdd88e6f7e
|
@ -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));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/*
|
/*
|
|
@ -42,318 +42,199 @@ 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;
|
||||||
|
|
||||||
|
XOffset = xoffset;
|
||||||
|
YOffset = yoffset;
|
||||||
|
|
||||||
|
carbonWindow = window;
|
||||||
|
|
||||||
this.carbonWindow = (CarbonWindowInfo)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;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shareContextRef == IntPtr.Zero)
|
if (shareContextRef == IntPtr.Zero)
|
||||||
{
|
{
|
||||||
Debug.Print("No context sharing will take place.");
|
Debug.Print("No context sharing will take place.");
|
||||||
}
|
}
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
aglAttributes.Add((int)pixelFormatAttribute);
|
aglAttributes.Add((int)pixelFormatAttribute);
|
||||||
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.
|
|
||||||
IntPtr gdevice;
|
|
||||||
IntPtr cgdevice = GetQuartzDevice(carbonWindow);
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
// Choose a pixel format with the attributes we specified.
|
||||||
|
AGLPixelFormat pixelformat;
|
||||||
|
AglGraphicsMode selector = new AglGraphicsMode();
|
||||||
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;
|
||||||
glrect[3] = rect.Height;
|
glrect[3] = rect.Height;
|
||||||
|
|
||||||
Agl.aglSetInteger(Handle.Handle, Agl.ParameterNames.AGL_BUFFER_RECT, glrect);
|
Agl.aglSetInteger(Handle.Handle, Agl.ParameterNames.AGL_BUFFER_RECT, glrect);
|
||||||
MyAGLReportError("aglSetInteger");
|
MyAGLReportError("aglSetInteger");
|
||||||
|
|
||||||
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);
|
||||||
{
|
windowPort = API.GetWindowPort(controlOwner);
|
||||||
IntPtr controlOwner = API.GetControlOwner(carbonWindow.Handle);
|
|
||||||
|
|
||||||
windowPort = API.GetWindowPort(controlOwner);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
windowPort = API.GetWindowPort(carbonWindow.Handle);
|
|
||||||
}
|
|
||||||
|
|
||||||
return windowPort;
|
return windowPort;
|
||||||
}
|
}
|
||||||
public override void Update(IWindowInfo window)
|
|
||||||
{
|
|
||||||
CarbonWindowInfo carbonWindow = (CarbonWindowInfo)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)
|
public void Update(IWindowInfo window)
|
||||||
{
|
{
|
||||||
carbonWindow.GoWindowedHack = false;
|
SetDrawable(window);
|
||||||
CarbonGLNative wind = GetCarbonWindow(carbonWindow);
|
SetBufferRect(window);
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
Agl.aglSwapBuffers(Handle.Handle);
|
Agl.aglSwapBuffers(Handle.Handle);
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
@ -390,13 +329,13 @@ namespace OpenTK.Platform.MacOS
|
||||||
{
|
{
|
||||||
if (IsDisposed || Handle.Handle == IntPtr.Zero)
|
if (IsDisposed || Handle.Handle == IntPtr.Zero)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Debug.Print("Disposing of AGL context.");
|
Debug.Print("Disposing of AGL context.");
|
||||||
Agl.aglSetCurrentContext(IntPtr.Zero);
|
Agl.aglSetCurrentContext(IntPtr.Zero);
|
||||||
|
|
||||||
//Debug.Print("Setting drawable to null for context {0}.", Handle.Handle);
|
//Debug.Print("Setting drawable to null for context {0}.", Handle.Handle);
|
||||||
//Agl.aglSetDrawable(Handle.Handle, IntPtr.Zero);
|
//Agl.aglSetDrawable(Handle.Handle, IntPtr.Zero);
|
||||||
|
|
||||||
// I do not know MacOS allows us to destroy a context from a separate thread,
|
// I do not know MacOS allows us to destroy a context from a separate thread,
|
||||||
// like the finalizer thread. It's untested, but worst case is probably
|
// like the finalizer thread. It's untested, but worst case is probably
|
||||||
// an exception on application exit, which would be logged to the console.
|
// an exception on application exit, which would be logged to the console.
|
||||||
|
@ -410,34 +349,50 @@ namespace OpenTK.Platform.MacOS
|
||||||
Handle = ContextHandle.Zero;
|
Handle = ContextHandle.Zero;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// failed to destroy context.
|
// failed to destroy context.
|
||||||
Debug.WriteLine("Failed to destroy context.");
|
Debug.WriteLine("Failed to destroy context.");
|
||||||
Debug.WriteLine(Agl.ErrorString(Agl.GetError()));
|
Debug.WriteLine(Agl.ErrorString(Agl.GetError()));
|
||||||
|
|
||||||
// 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
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -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
160
Source/GLControl/Carbon.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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
113
Source/GLControl/NS.cs
Normal 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -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">
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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
|
@ -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(); }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -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;
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in a new issue