2014-04-18 20:30:50 +00:00
|
|
|
using System;
|
|
|
|
using OpenTK.Platform;
|
|
|
|
using OpenTK.Graphics;
|
|
|
|
using OpenTK.Platform.MacOS;
|
|
|
|
using System.Diagnostics;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Runtime.InteropServices;
|
|
|
|
|
|
|
|
namespace OpenTK
|
|
|
|
{
|
|
|
|
class CocoaContext : DesktopGraphicsContext
|
|
|
|
{
|
|
|
|
private CocoaWindowInfo cocoaWindow;
|
|
|
|
private IntPtr shareContextRef;
|
|
|
|
|
|
|
|
static readonly IntPtr NSOpenGLContext = Class.Get("NSOpenGLContext");
|
2014-04-20 08:08:44 +00:00
|
|
|
static readonly IntPtr selCurrentContext = Selector.Get("currentContext");
|
|
|
|
static readonly IntPtr selFlushBuffer = Selector.Get("flushBuffer");
|
|
|
|
static readonly IntPtr selMakeCurrentContext = Selector.Get("makeCurrentContext");
|
|
|
|
static readonly IntPtr selUpdate = Selector.Get("update");
|
2014-04-18 20:30:50 +00:00
|
|
|
|
|
|
|
static CocoaContext()
|
|
|
|
{
|
|
|
|
Cocoa.Initialize();
|
|
|
|
}
|
|
|
|
|
|
|
|
public CocoaContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, int majorVersion, int minorVersion)
|
|
|
|
{
|
|
|
|
Debug.Print("Context Type: {0}", shareContext);
|
|
|
|
Debug.Print("Window info: {0}", window);
|
|
|
|
|
|
|
|
cocoaWindow = (CocoaWindowInfo)window;
|
|
|
|
|
|
|
|
if (shareContext is CocoaContext)
|
|
|
|
shareContextRef = ((CocoaContext)shareContext).Handle.Handle;
|
|
|
|
|
|
|
|
if (shareContext is GraphicsContext)
|
|
|
|
{
|
|
|
|
ContextHandle shareHandle = shareContext != null ? (shareContext as IGraphicsContextInternal).Context : (ContextHandle)IntPtr.Zero;
|
|
|
|
shareContextRef = shareHandle.Handle;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (shareContextRef == IntPtr.Zero)
|
|
|
|
{
|
|
|
|
Debug.Print("No context sharing will take place.");
|
|
|
|
}
|
|
|
|
|
|
|
|
CreateContext(mode, cocoaWindow, shareContextRef, majorVersion, minorVersion, true);
|
|
|
|
}
|
|
|
|
|
|
|
|
public CocoaContext(ContextHandle handle, IWindowInfo window, IGraphicsContext shareContext, int majorVersion, int minorVersion)
|
|
|
|
{
|
|
|
|
if (handle == ContextHandle.Zero)
|
|
|
|
throw new ArgumentException("handle");
|
|
|
|
if (window == null)
|
|
|
|
throw new ArgumentNullException("window");
|
|
|
|
|
|
|
|
Handle = handle;
|
|
|
|
cocoaWindow = (CocoaWindowInfo)window;
|
|
|
|
}
|
|
|
|
|
|
|
|
private void AddPixelAttrib(List<NSOpenGLPixelFormatAttribute> attributes, NSOpenGLPixelFormatAttribute attribute)
|
|
|
|
{
|
|
|
|
Debug.Print(attribute.ToString());
|
|
|
|
|
|
|
|
attributes.Add(attribute);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void AddPixelAttrib(List<NSOpenGLPixelFormatAttribute> attributes, NSOpenGLPixelFormatAttribute attribute, int value)
|
|
|
|
{
|
|
|
|
Debug.Print("{0} : {1}", attribute, value);
|
|
|
|
|
|
|
|
attributes.Add(attribute);
|
|
|
|
attributes.Add((NSOpenGLPixelFormatAttribute)value);
|
|
|
|
}
|
|
|
|
|
|
|
|
private void CreateContext(GraphicsMode mode, CocoaWindowInfo cocoaWindow, IntPtr shareContextRef, int majorVersion, int minorVersion, bool fullscreen)
|
|
|
|
{
|
|
|
|
// Prepare attributes
|
|
|
|
List<NSOpenGLPixelFormatAttribute> attributes = new List<NSOpenGLPixelFormatAttribute>();
|
|
|
|
|
|
|
|
var profile = NSOpenGLProfile.VersionLegacy;
|
|
|
|
if (majorVersion > 3 || (majorVersion == 3 && minorVersion >= 2))
|
|
|
|
{
|
|
|
|
profile = NSOpenGLProfile.Version3_2Core;
|
|
|
|
Debug.Print("Running the OpenGL core profile.");
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
Debug.Print("Running the legacy OpenGL profile. Start with version major=3, minor=2 or later for the 3.2 profile.");
|
|
|
|
}
|
|
|
|
|
|
|
|
Debug.Print("NSGL pixel format attributes:");
|
|
|
|
Debug.Indent();
|
|
|
|
|
|
|
|
AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.OpenGLProfile, (int)profile);
|
|
|
|
AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.DoubleBuffer);
|
|
|
|
AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.Accelerated);
|
|
|
|
AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.ColorSize, mode.ColorFormat.BitsPerPixel);
|
|
|
|
|
|
|
|
if (mode.Depth > 0)
|
|
|
|
AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.DepthSize, mode.Depth);
|
|
|
|
|
|
|
|
if (mode.Stencil > 0)
|
|
|
|
AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.StencilSize, mode.Stencil);
|
|
|
|
|
|
|
|
if (mode.AccumulatorFormat.BitsPerPixel > 0)
|
|
|
|
{
|
|
|
|
AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.AccumSize, mode.AccumulatorFormat.BitsPerPixel);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (mode.Samples > 1)
|
|
|
|
{
|
|
|
|
AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.SampleBuffers, 1);
|
|
|
|
AddPixelAttrib(attributes, NSOpenGLPixelFormatAttribute.Samples, mode.Samples);
|
|
|
|
}
|
|
|
|
|
|
|
|
AddPixelAttrib(attributes, (NSOpenGLPixelFormatAttribute)0);
|
|
|
|
|
|
|
|
Debug.Unindent();
|
|
|
|
|
|
|
|
Debug.Write("Attribute array: ");
|
|
|
|
for (int i = 0; i < attributes.Count; i++)
|
|
|
|
Debug.Write(attributes[i].ToString() + " ");
|
|
|
|
Debug.WriteLine("");
|
|
|
|
|
|
|
|
// Create pixel format
|
|
|
|
var pixelFormat = Cocoa.SendIntPtr(Class.Get("NSOpenGLPixelFormat"), Selector.Alloc);
|
|
|
|
|
|
|
|
unsafe
|
|
|
|
{
|
|
|
|
fixed (NSOpenGLPixelFormatAttribute* ptr = attributes.ToArray())
|
|
|
|
{
|
|
|
|
pixelFormat = Cocoa.SendIntPtr(pixelFormat, Selector.Get("initWithAttributes:"), (IntPtr)ptr);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create context
|
|
|
|
var context = Cocoa.SendIntPtr(NSOpenGLContext, Selector.Alloc);
|
|
|
|
context = Cocoa.SendIntPtr(context, Selector.Get("initWithFormat:shareContext:"), pixelFormat, shareContextRef);
|
|
|
|
|
|
|
|
// Release pixel format
|
|
|
|
Cocoa.SendVoid(pixelFormat, Selector.Release);
|
|
|
|
pixelFormat = IntPtr.Zero;
|
|
|
|
|
|
|
|
// Attach the view
|
|
|
|
Cocoa.SendVoid(context, Selector.Get("setView:"), cocoaWindow.ViewHandle);
|
|
|
|
Cocoa.SendVoid(cocoaWindow.ViewHandle, Selector.Get("setWantsBestResolutionOpenGLSurface:"), true);
|
|
|
|
|
|
|
|
// Finalize
|
|
|
|
Handle = new ContextHandle(context);
|
2014-04-22 18:02:05 +00:00
|
|
|
Mode = mode;
|
2014-04-18 20:30:50 +00:00
|
|
|
Update(cocoaWindow);
|
|
|
|
MakeCurrent(cocoaWindow);
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void SwapBuffers()
|
|
|
|
{
|
2014-04-20 08:08:44 +00:00
|
|
|
Cocoa.SendVoid(Handle.Handle, selFlushBuffer);
|
2014-04-18 20:30:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public override void MakeCurrent(IWindowInfo window)
|
|
|
|
{
|
2014-04-20 08:08:44 +00:00
|
|
|
Cocoa.SendVoid(Handle.Handle, selMakeCurrentContext);
|
2014-04-18 20:30:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public override bool IsCurrent
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return Handle.Handle == CurrentContext;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public static IntPtr CurrentContext
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
2014-04-20 08:08:44 +00:00
|
|
|
return Cocoa.SendIntPtr(NSOpenGLContext, selCurrentContext);
|
2014-04-18 20:30:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-04-19 11:36:44 +00:00
|
|
|
private unsafe void SetContextValue (int val, NSOpenGLContextParameter par)
|
|
|
|
{
|
|
|
|
int* p = &val;
|
|
|
|
Cocoa.SendVoid(Handle.Handle, Selector.Get("setValues:forParameter:"), (IntPtr)p, (int)par);
|
|
|
|
}
|
|
|
|
|
|
|
|
private unsafe int GetContextValue (NSOpenGLContextParameter par)
|
|
|
|
{
|
|
|
|
int ret;
|
|
|
|
int* p = &ret;
|
|
|
|
Cocoa.SendVoid(Handle.Handle, Selector.Get("getValues:forParameter:"), (IntPtr)p, (int)par);
|
|
|
|
return ret;
|
|
|
|
}
|
2014-04-18 20:30:50 +00:00
|
|
|
|
|
|
|
public override int SwapInterval
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
2014-04-19 11:36:44 +00:00
|
|
|
return GetContextValue(NSOpenGLContextParameter.SwapInterval);
|
2014-04-18 20:30:50 +00:00
|
|
|
}
|
|
|
|
set
|
|
|
|
{
|
2014-04-19 11:36:44 +00:00
|
|
|
SetContextValue(value, NSOpenGLContextParameter.SwapInterval);
|
2014-04-18 20:30:50 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void Update(IWindowInfo window)
|
|
|
|
{
|
2014-04-20 08:08:44 +00:00
|
|
|
Cocoa.SendVoid(Handle.Handle, selUpdate);
|
2014-04-18 20:30:50 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
#region IDisposable Members
|
|
|
|
|
|
|
|
~CocoaContext()
|
|
|
|
{
|
|
|
|
Dispose(false);
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void Dispose()
|
|
|
|
{
|
|
|
|
Dispose(true);
|
|
|
|
}
|
|
|
|
|
|
|
|
void Dispose(bool disposing)
|
|
|
|
{
|
|
|
|
if (IsDisposed || Handle.Handle == IntPtr.Zero)
|
|
|
|
return;
|
|
|
|
|
|
|
|
Debug.Print("Disposing of Cocoa context.");
|
|
|
|
|
2014-04-19 11:36:44 +00:00
|
|
|
Cocoa.SendVoid(NSOpenGLContext, Selector.Get("clearCurrentContext"));
|
2014-04-20 08:08:44 +00:00
|
|
|
Cocoa.SendVoid(Handle.Handle, Selector.Get("clearDrawable"));
|
|
|
|
Cocoa.SendVoid(Handle.Handle, Selector.Get("release"));
|
2014-04-18 20:30:50 +00:00
|
|
|
|
|
|
|
Handle = ContextHandle.Zero;
|
|
|
|
|
|
|
|
IsDisposed = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
|
|
|
|
#region IGraphicsContextInternal Members
|
|
|
|
|
|
|
|
public override IntPtr GetAddress(string function)
|
|
|
|
{
|
|
|
|
return NS.GetAddress(function);
|
|
|
|
}
|
|
|
|
|
|
|
|
public override IntPtr GetAddress(IntPtr function)
|
|
|
|
{
|
|
|
|
return NS.GetAddress(function);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endregion
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|