Updates to macos fullscreen.

Resolution switching is now accompanied by a call to CGDisplayCapture.
A secondary fullscreen context is created for going full screen.
This commit is contained in:
kanato 2009-01-27 18:27:44 +00:00
parent 34e283367d
commit 74707ccdfd
5 changed files with 94 additions and 46 deletions

View file

@ -26,26 +26,34 @@ namespace OpenTK.Platform.MacOS
class AglContext : IGraphicsContext, IGraphicsContextInternal class AglContext : IGraphicsContext, IGraphicsContextInternal
{ {
IntPtr storedContextRef;
IntPtr contextRef; IntPtr contextRef;
bool mVSync = false; bool mVSync = false;
IntPtr displayID; IntPtr displayID;
GraphicsMode mode; GraphicsMode mode;
CarbonWindowInfo carbonWindow; CarbonWindowInfo carbonWindow;
IGraphicsContext shareContext; IntPtr shareContextRef;
static AglContext() static AglContext()
{ {
if (GraphicsContext.GetCurrentContext == null) if (GraphicsContext.GetCurrentContext == null)
GraphicsContext.GetCurrentContext = AglContext.GetCurrentContext; GraphicsContext.GetCurrentContext = AglContext.GetCurrentContext;
} }
public AglContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext) public AglContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, bool fullscreen)
{ {
Debug.Print("Context Type: {0}", shareContext);
Debug.Print("Window info: {0}", window);
this.mode = mode; this.mode = mode;
this.carbonWindow = (CarbonWindowInfo)window; this.carbonWindow = (CarbonWindowInfo)window;
this.shareContext = shareContext;
CreateContext(mode, carbonWindow, shareContext);
if (shareContext is AglContext)
shareContextRef = ((AglContext)shareContext).contextRef;
CreateContext(mode, carbonWindow, shareContextRef, fullscreen);
} }
@ -62,11 +70,12 @@ namespace OpenTK.Platform.MacOS
aglAttributes.Add((int)pixelFormatAttribute); aglAttributes.Add((int)pixelFormatAttribute);
aglAttributes.Add(value); aglAttributes.Add(value);
} }
void CreateContext(GraphicsMode mode, CarbonWindowInfo carbonWindow, IGraphicsContext shareContext) void CreateContext(GraphicsMode mode, CarbonWindowInfo carbonWindow,
IntPtr shareContextRef, bool fullscreen)
{ {
List<int> aglAttributes = new List<int>(); List<int> aglAttributes = new List<int>();
Debug.Print("AGL attributes:"); Debug.Print("AGL pixel format attributes:");
Debug.Indent(); Debug.Indent();
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_RGBA); AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_RGBA);
@ -89,7 +98,11 @@ namespace OpenTK.Platform.MacOS
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ACCUM_BLUE_SIZE, mode.AccumulatorFormat.Blue); AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ACCUM_BLUE_SIZE, mode.AccumulatorFormat.Blue);
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ACCUM_ALPHA_SIZE, mode.AccumulatorFormat.Alpha); AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_ACCUM_ALPHA_SIZE, mode.AccumulatorFormat.Alpha);
} }
if (fullscreen)
{
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_FULLSCREEN); AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_FULLSCREEN);
}
AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_NONE); AddPixelAttrib(aglAttributes, Agl.PixelFormatAttribute.AGL_NONE);
Debug.Unindent(); Debug.Unindent();
@ -100,30 +113,30 @@ namespace OpenTK.Platform.MacOS
Debug.WriteLine(""); Debug.WriteLine("");
AGLPixelFormat myAGLPixelFormat; AGLPixelFormat myAGLPixelFormat;
// Choose a pixel format with the attributes we specified.
if (fullscreen)
{
IntPtr gdevice; IntPtr gdevice;
OSStatus status = Carbon.API.DMGetGDeviceByDisplayID( OSStatus status = Carbon.API.DMGetGDeviceByDisplayID(
QuartzDisplayDeviceDriver.MainDisplay, out gdevice, false); QuartzDisplayDeviceDriver.MainDisplay, out gdevice, false);
if (status != OSStatus.NoError) if (status != OSStatus.NoError)
throw new MacOSException(status, "DMGetGDeviceByDisplayID failed."); throw new MacOSException(status, "DMGetGDeviceByDisplayID failed.");
// Choose a pixel format with the attributes we specified.
myAGLPixelFormat = Agl.aglChoosePixelFormat( myAGLPixelFormat = Agl.aglChoosePixelFormat(
ref gdevice, 1, ref gdevice, 1,
//IntPtr.Zero, 0,
aglAttributes.ToArray()); aglAttributes.ToArray());
}
MyAGLReportError("aglChoosePixelFormat"); else
IntPtr shareContextRef = IntPtr.Zero;
if (shareContext != null)
{ {
Debug.Print("shareContext type is {0}", shareContext.GetType()); myAGLPixelFormat = Agl.aglChoosePixelFormat(
IntPtr.Zero, 0,
aglAttributes.ToArray());
} }
if (shareContext != null && shareContext is AglContext) MyAGLReportError("aglChoosePixelFormat");
shareContextRef = ((AglContext)shareContext).contextRef;
// create the context and share it with the share reference. // create the context and share it with the share reference.
this.contextRef = Agl.aglCreateContext(myAGLPixelFormat, shareContextRef); this.contextRef = Agl.aglCreateContext(myAGLPixelFormat, shareContextRef);
@ -205,7 +218,6 @@ namespace OpenTK.Platform.MacOS
SetBufferRect(carbonWindow); SetBufferRect(carbonWindow);
//Agl.aglSetCurrentContext(contextRef);
Agl.aglUpdateContext(contextRef); Agl.aglUpdateContext(contextRef);
} }
@ -215,7 +227,8 @@ namespace OpenTK.Platform.MacOS
if (err != Agl.AglError.NoError) if (err != Agl.AglError.NoError)
throw new MacOSException((OSStatus)err, string.Format( throw new MacOSException((OSStatus)err, string.Format(
"AGL Error from function {0}: {1} {2}", err, Agl.ErrorString(err))); "AGL Error from function {0}: {1} {2}",
function, err, Agl.ErrorString(err)));
} }
static ContextHandle GetCurrentContext() static ContextHandle GetCurrentContext()
@ -225,11 +238,37 @@ namespace OpenTK.Platform.MacOS
internal void SetFullScreen() internal void SetFullScreen()
{ {
Agl.aglSetFullScreen(contextRef, 640, 480, 60, 0); if (storedContextRef == IntPtr.Zero)
{
storedContextRef = contextRef;
}
else
{
Agl.aglDestroyContext(contextRef);
}
// TODO: this may be a problem if we are switching from one
// full screen mode to another.
try
{
CreateContext(mode, carbonWindow, storedContextRef, true);
Agl.aglSetFullScreen(contextRef, 0, 0, 0, 0);
}
catch (MacOSException e)
{
contextRef = storedContextRef;
storedContextRef = IntPtr.Zero;
throw;
}
} }
internal void UnsetFullScreen() internal void UnsetFullScreen()
{ {
SetDrawable(carbonWindow); if (storedContextRef == IntPtr.Zero)
return;
Agl.aglDestroyContext(contextRef);
contextRef = storedContextRef;
} }

View file

@ -281,6 +281,18 @@ namespace OpenTK.Platform.MacOS
** Pixel format functions ** Pixel format functions
*/ */
[DllImport(agl)] internal static extern AGLPixelFormat aglChoosePixelFormat(ref AGLDevice gdevs, int ndev, int []attribs); [DllImport(agl)] internal static extern AGLPixelFormat aglChoosePixelFormat(ref AGLDevice gdevs, int ndev, int []attribs);
/// <summary>
/// Use this overload only with IntPtr.Zero for the first argument.
/// </summary>
/// <param name="gdevs">
/// </param>
/// <param name="ndev">
/// </param>
/// <param name="attribs">
/// </param>
/// <returns>
/// </returns>
[DllImport(agl)] internal static extern AGLPixelFormat aglChoosePixelFormat(IntPtr gdevs, int ndev, int []attribs);
[DllImport(agl)] internal static extern void aglDestroyPixelFormat(AGLPixelFormat pix); [DllImport(agl)] internal static extern void aglDestroyPixelFormat(AGLPixelFormat pix);
[DllImport(agl)] internal static extern AGLPixelFormat aglNextPixelFormat(AGLPixelFormat pix); [DllImport(agl)] internal static extern AGLPixelFormat aglNextPixelFormat(AGLPixelFormat pix);
[DllImport(agl)] static extern byte aglDescribePixelFormat(AGLPixelFormat pix, int attrib, out int value); [DllImport(agl)] static extern byte aglDescribePixelFormat(AGLPixelFormat pix, int attrib, out int value);

View file

@ -632,9 +632,13 @@ namespace OpenTK.Platform.MacOS
case WindowState.Fullscreen: case WindowState.Fullscreen:
((AglContext)context.Implementation).SetFullScreen(); ((AglContext)context.Implementation).SetFullScreen();
context.Update(WindowInfo); context.Update(WindowInfo);
break; break;
case WindowState.Maximized: case WindowState.Maximized:
// hack because mac os has no concept of maximized. Instead windows are "zoomed"
// meaning they are maximized up to their reported ideal size. So we report a
// large ideal size.
idealSize = new Point(9000, 9000); idealSize = new Point(9000, 9000);
API.ZoomWindowIdeal(window.WindowRef, WindowPartCode.inZoomOut, ref idealSize); API.ZoomWindowIdeal(window.WindowRef, WindowPartCode.inZoomOut, ref idealSize);
break; break;

View file

@ -27,7 +27,7 @@ namespace OpenTK.Platform.MacOS
public IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, bool DirectRendering) public IGraphicsContext CreateGLContext(GraphicsMode mode, IWindowInfo window, IGraphicsContext shareContext, bool DirectRendering)
{ {
return new AglContext(mode, window, shareContext); return new AglContext(mode, window, shareContext, false);
} }
public IGraphicsMode CreateGraphicsMode() public IGraphicsMode CreateGraphicsMode()

View file

@ -20,16 +20,6 @@ namespace OpenTK.Platform.MacOS
static QuartzDisplayDeviceDriver() static QuartzDisplayDeviceDriver()
{ {
//lock (display_lock)
//{
// List<DisplayResolution> resolutions = new List<DisplayResolution>();
// DisplayResolution primaryRes = new DisplayResolution(1024, 768, 32, 60);
// resolutions.Add(primaryRes);
// object o = new Graphics.DisplayDevice(primaryRes, true, resolutions);
//}
lock (display_lock) lock (display_lock)
{ {
// To minimize the need to add static methods to OpenTK.Graphics.DisplayDevice // To minimize the need to add static methods to OpenTK.Graphics.DisplayDevice
@ -143,6 +133,8 @@ namespace OpenTK.Platform.MacOS
bpp == resolution.BitsPerPixel && bpp == resolution.BitsPerPixel &&
freq == resolution.RefreshRate) freq == resolution.RefreshRate)
{ {
CG.DisplayCapture(display);
CG.DisplaySwitchToMode(display, displayModes[j]); CG.DisplaySwitchToMode(display, displayModes[j]);
return true; return true;
@ -158,7 +150,8 @@ namespace OpenTK.Platform.MacOS
if (storedModes.ContainsKey(display)) if (storedModes.ContainsKey(display))
{ {
CG.DisplaySwitchToMode(display, storedModes[display]); //CG.DisplaySwitchToMode(display, storedModes[display]);
CG.DisplayRelease(display);
return true; return true;
} }