2010-11-21 21:16:18 +01:00
|
|
|
#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
|
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
using System;
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Diagnostics;
|
2011-12-08 01:03:14 +01:00
|
|
|
#if !MINIMAL
|
2010-11-21 21:16:18 +01:00
|
|
|
using System.Drawing;
|
2011-12-08 01:03:14 +01:00
|
|
|
#endif
|
2010-11-21 21:16:18 +01:00
|
|
|
using OpenTK.Platform.MacOS.Carbon;
|
2009-02-22 11:43:35 +01:00
|
|
|
|
|
|
|
namespace OpenTK.Platform.MacOS
|
|
|
|
{
|
2010-11-21 21:16:18 +01:00
|
|
|
sealed class QuartzDisplayDeviceDriver : DisplayDeviceBase
|
2009-02-22 11:43:35 +01:00
|
|
|
{
|
|
|
|
static object display_lock = new object();
|
|
|
|
|
2010-11-21 21:16:18 +01:00
|
|
|
public QuartzDisplayDeviceDriver()
|
2009-02-22 11:43:35 +01:00
|
|
|
{
|
|
|
|
lock (display_lock)
|
|
|
|
{
|
|
|
|
// To minimize the need to add static methods to OpenTK.Graphics.DisplayDevice
|
|
|
|
// we only allow settings to be set through its constructor.
|
|
|
|
// Thus, we save all necessary parameters in temporary variables
|
|
|
|
// and construct the device when every needed detail is available.
|
|
|
|
// The main DisplayDevice constructor adds the newly constructed device
|
|
|
|
// to the list of available devices.
|
|
|
|
const int maxDisplayCount = 20;
|
|
|
|
IntPtr[] displays = new IntPtr[maxDisplayCount];
|
|
|
|
int displayCount;
|
2010-11-02 20:49:24 +01:00
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
unsafe
|
|
|
|
{
|
2010-11-02 20:49:24 +01:00
|
|
|
fixed (IntPtr* displayPtr = displays)
|
2009-02-22 11:43:35 +01:00
|
|
|
{
|
|
|
|
CG.GetActiveDisplayList(maxDisplayCount, displayPtr, out displayCount);
|
|
|
|
}
|
|
|
|
}
|
2010-11-02 20:49:24 +01:00
|
|
|
|
2009-11-09 08:39:38 +01:00
|
|
|
Debug.Print("CoreGraphics reported {0} display(s).", displayCount);
|
2009-02-22 11:43:35 +01:00
|
|
|
Debug.Indent();
|
2010-11-02 20:49:24 +01:00
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
for (int i = 0; i < displayCount; i++)
|
|
|
|
{
|
|
|
|
IntPtr currentDisplay = displays[i];
|
2010-11-02 20:49:24 +01:00
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
// according to docs, first element in the array is always the
|
|
|
|
// main display.
|
|
|
|
bool primary = (i == 0);
|
2010-11-02 20:49:24 +01:00
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
// gets current settings
|
|
|
|
int currentWidth = CG.DisplayPixelsWide(currentDisplay);
|
|
|
|
int currentHeight = CG.DisplayPixelsHigh(currentDisplay);
|
|
|
|
Debug.Print("Display {0} is at {1}x{2}", i, currentWidth, currentHeight);
|
2010-11-02 20:49:24 +01:00
|
|
|
|
|
|
|
IntPtr displayModesPtr = CG.DisplayAvailableModes(currentDisplay);
|
2009-02-22 11:43:35 +01:00
|
|
|
CFArray displayModes = new CFArray(displayModesPtr);
|
|
|
|
Debug.Print("Supports {0} display modes.", displayModes.Count);
|
2010-11-02 20:49:24 +01:00
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
DisplayResolution opentk_dev_current_res = null;
|
|
|
|
List<DisplayResolution> opentk_dev_available_res = new List<DisplayResolution>();
|
|
|
|
IntPtr currentModePtr = CG.DisplayCurrentMode(currentDisplay);
|
|
|
|
CFDictionary currentMode = new CFDictionary(currentModePtr);
|
2010-11-02 20:49:24 +01:00
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
for (int j = 0; j < displayModes.Count; j++)
|
|
|
|
{
|
|
|
|
CFDictionary dict = new CFDictionary(displayModes[j]);
|
|
|
|
|
2010-11-02 20:49:24 +01:00
|
|
|
int width = (int)dict.GetNumberValue("Width");
|
|
|
|
int height = (int)dict.GetNumberValue("Height");
|
|
|
|
int bpp = (int)dict.GetNumberValue("BitsPerPixel");
|
2009-02-22 11:43:35 +01:00
|
|
|
double freq = dict.GetNumberValue("RefreshRate");
|
|
|
|
bool current = currentMode.Ref == dict.Ref;
|
2010-11-02 20:49:24 +01:00
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
//if (current) Debug.Write(" * ");
|
|
|
|
//else Debug.Write(" ");
|
2010-11-02 20:49:24 +01:00
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
//Debug.Print("Mode {0} is {1}x{2}x{3} @ {4}.", j, width, height, bpp, freq);
|
2010-11-02 20:49:24 +01:00
|
|
|
|
2009-06-02 17:49:39 +02:00
|
|
|
DisplayResolution thisRes = new DisplayResolution(0, 0, width, height, bpp, (float)freq);
|
2009-02-22 11:43:35 +01:00
|
|
|
opentk_dev_available_res.Add(thisRes);
|
2010-11-02 20:49:24 +01:00
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
if (current)
|
|
|
|
opentk_dev_current_res = thisRes;
|
2010-11-02 20:49:24 +01:00
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
}
|
2010-11-02 20:49:24 +01:00
|
|
|
|
|
|
|
HIRect bounds = CG.DisplayBounds(currentDisplay);
|
|
|
|
Rectangle newRect = new Rectangle((int)bounds.Origin.X, (int)bounds.Origin.Y, (int)bounds.Size.Width, (int)bounds.Size.Height);
|
|
|
|
|
|
|
|
Debug.Print("Display {0} bounds: {1}", i, newRect);
|
|
|
|
|
2010-11-21 21:16:18 +01:00
|
|
|
DisplayDevice opentk_dev = new DisplayDevice(opentk_dev_current_res,
|
|
|
|
primary, opentk_dev_available_res, newRect, currentDisplay);
|
|
|
|
|
|
|
|
AvailableDevices.Add(opentk_dev);
|
|
|
|
|
|
|
|
if (primary)
|
|
|
|
Primary = opentk_dev;
|
2009-02-22 11:43:35 +01:00
|
|
|
}
|
2010-11-02 20:49:24 +01:00
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
Debug.Unindent();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2010-11-02 20:49:24 +01:00
|
|
|
static internal IntPtr HandleTo(DisplayDevice displayDevice)
|
|
|
|
{
|
2010-11-21 21:16:18 +01:00
|
|
|
return (IntPtr)displayDevice.Id;
|
2010-11-02 20:49:24 +01:00
|
|
|
}
|
2009-11-09 08:50:21 +01:00
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
#region IDisplayDeviceDriver Members
|
|
|
|
|
|
|
|
Dictionary<IntPtr, IntPtr> storedModes = new Dictionary<IntPtr, IntPtr>();
|
|
|
|
List<IntPtr> displaysCaptured = new List<IntPtr>();
|
2010-11-02 20:49:24 +01:00
|
|
|
|
2010-11-21 21:16:18 +01:00
|
|
|
public sealed override bool TryChangeResolution(DisplayDevice device, DisplayResolution resolution)
|
2009-02-22 11:43:35 +01:00
|
|
|
{
|
2010-11-21 21:16:18 +01:00
|
|
|
IntPtr display = HandleTo(device);
|
2009-02-22 11:43:35 +01:00
|
|
|
IntPtr currentModePtr = CG.DisplayCurrentMode(display);
|
2010-11-02 20:49:24 +01:00
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
if (storedModes.ContainsKey(display) == false)
|
|
|
|
{
|
2010-11-02 20:49:24 +01:00
|
|
|
storedModes.Add(display, currentModePtr);
|
2009-02-22 11:43:35 +01:00
|
|
|
}
|
2010-11-02 20:49:24 +01:00
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
IntPtr displayModesPtr = CG.DisplayAvailableModes(display);
|
|
|
|
CFArray displayModes = new CFArray(displayModesPtr);
|
2010-11-02 20:49:24 +01:00
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
for (int j = 0; j < displayModes.Count; j++)
|
|
|
|
{
|
|
|
|
CFDictionary dict = new CFDictionary(displayModes[j]);
|
2010-11-02 20:49:24 +01:00
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
int width = (int)dict.GetNumberValue("Width");
|
|
|
|
int height = (int)dict.GetNumberValue("Height");
|
|
|
|
int bpp = (int)dict.GetNumberValue("BitsPerPixel");
|
|
|
|
double freq = dict.GetNumberValue("RefreshRate");
|
2010-11-02 20:49:24 +01:00
|
|
|
|
|
|
|
if (width == resolution.Width && height == resolution.Height && bpp == resolution.BitsPerPixel && System.Math.Abs(freq - resolution.RefreshRate) < 1e-6)
|
2009-02-22 11:43:35 +01:00
|
|
|
{
|
|
|
|
if (displaysCaptured.Contains(display) == false)
|
|
|
|
{
|
|
|
|
CG.DisplayCapture(display);
|
|
|
|
}
|
2010-11-02 20:49:24 +01:00
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
Debug.Print("Changing resolution to {0}x{1}x{2}@{3}.", width, height, bpp, freq);
|
2010-11-02 20:49:24 +01:00
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
CG.DisplaySwitchToMode(display, displayModes[j]);
|
2010-11-02 20:49:24 +01:00
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
return true;
|
|
|
|
}
|
2010-11-02 20:49:24 +01:00
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
}
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
2010-11-21 21:16:18 +01:00
|
|
|
public sealed override bool TryRestoreResolution(DisplayDevice device)
|
2009-02-22 11:43:35 +01:00
|
|
|
{
|
2010-11-21 21:16:18 +01:00
|
|
|
IntPtr display = HandleTo(device);
|
2010-11-02 20:49:24 +01:00
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
if (storedModes.ContainsKey(display))
|
|
|
|
{
|
|
|
|
Debug.Print("Restoring resolution.");
|
2010-11-02 20:49:24 +01:00
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
CG.DisplaySwitchToMode(display, storedModes[display]);
|
|
|
|
CG.DisplayRelease(display);
|
|
|
|
displaysCaptured.Remove(display);
|
2010-11-02 20:49:24 +01:00
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
return true;
|
|
|
|
}
|
2010-11-02 20:49:24 +01:00
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
return false;
|
|
|
|
}
|
2010-11-21 21:16:18 +01:00
|
|
|
|
2009-02-22 11:43:35 +01:00
|
|
|
#endregion
|
2010-11-02 20:49:24 +01:00
|
|
|
}
|
2009-02-22 11:43:35 +01:00
|
|
|
}
|