00001 using System;
00002 using System.Collections.Generic;
00003 using System.Diagnostics;
00004
00005 namespace OpenTK.Platform.MacOS
00006 {
00007 using System.Drawing;
00008 using Carbon;
00009
00010 class QuartzDisplayDeviceDriver : IDisplayDeviceDriver
00011 {
00012 static object display_lock = new object();
00013
00014 static Dictionary<DisplayDevice, IntPtr> displayMap =
00015 new Dictionary<DisplayDevice, IntPtr>();
00016
00017 static IntPtr mainDisplay;
00018 internal static IntPtr MainDisplay { get { return mainDisplay; } }
00019
00020 static QuartzDisplayDeviceDriver()
00021 {
00022 lock (display_lock)
00023 {
00024
00025
00026
00027
00028
00029
00030 const int maxDisplayCount = 20;
00031 IntPtr[] displays = new IntPtr[maxDisplayCount];
00032 int displayCount;
00033
00034 unsafe
00035 {
00036 fixed(IntPtr* displayPtr = displays)
00037 {
00038 CG.GetActiveDisplayList(maxDisplayCount, displayPtr, out displayCount);
00039 }
00040 }
00041
00042 Debug.Print("CoreGraphics reported {0} display(s).", displayCount);
00043 Debug.Indent();
00044
00045 for (int i = 0; i < displayCount; i++)
00046 {
00047 IntPtr currentDisplay = displays[i];
00048
00049
00050
00051 bool primary = (i == 0);
00052
00053 if (primary)
00054 mainDisplay = currentDisplay;
00055
00056
00057 int currentWidth = CG.DisplayPixelsWide(currentDisplay);
00058 int currentHeight = CG.DisplayPixelsHigh(currentDisplay);
00059 Debug.Print("Display {0} is at {1}x{2}", i, currentWidth, currentHeight);
00060
00061 IntPtr displayModesPtr = CG.DisplayAvailableModes(currentDisplay);
00062 CFArray displayModes = new CFArray(displayModesPtr);
00063 Debug.Print("Supports {0} display modes.", displayModes.Count);
00064
00065 DisplayResolution opentk_dev_current_res = null;
00066 List<DisplayResolution> opentk_dev_available_res = new List<DisplayResolution>();
00067 IntPtr currentModePtr = CG.DisplayCurrentMode(currentDisplay);
00068 CFDictionary currentMode = new CFDictionary(currentModePtr);
00069
00070 for (int j = 0; j < displayModes.Count; j++)
00071 {
00072 CFDictionary dict = new CFDictionary(displayModes[j]);
00073
00074 int width = (int) dict.GetNumberValue("Width");
00075 int height = (int) dict.GetNumberValue("Height");
00076 int bpp = (int) dict.GetNumberValue("BitsPerPixel");
00077 double freq = dict.GetNumberValue("RefreshRate");
00078 bool current = currentMode.Ref == dict.Ref;
00079
00080
00081
00082
00083
00084
00085 DisplayResolution thisRes = new DisplayResolution(0, 0, width, height, bpp, (float)freq);
00086 opentk_dev_available_res.Add(thisRes);
00087
00088 if (current)
00089 opentk_dev_current_res = thisRes;
00090
00091 }
00092
00093 HIRect bounds = CG.DisplayBounds(currentDisplay);
00094 Rectangle newRect = new Rectangle(
00095 (int)bounds.Origin.X, (int)bounds.Origin.Y, (int)bounds.Size.Width, (int)bounds.Size.Height);
00096
00097 Debug.Print("Display {0} bounds: {1}", i, newRect);
00098
00099 DisplayDevice opentk_dev =
00100 new DisplayDevice(opentk_dev_current_res, primary, opentk_dev_available_res, newRect);
00101
00102 displayMap.Add(opentk_dev, currentDisplay);
00103 }
00104
00105 Debug.Unindent();
00106 }
00107 }
00108
00109
00110 internal static IntPtr HandleTo(DisplayDevice displayDevice)
00111 {
00112 if (displayMap.ContainsKey(displayDevice))
00113 return displayMap[displayDevice];
00114 else
00115 return IntPtr.Zero;
00116 }
00117
00118 #region IDisplayDeviceDriver Members
00119
00120 Dictionary<IntPtr, IntPtr> storedModes = new Dictionary<IntPtr, IntPtr>();
00121 List<IntPtr> displaysCaptured = new List<IntPtr>();
00122
00123 public bool TryChangeResolution(DisplayDevice device, DisplayResolution resolution)
00124 {
00125 IntPtr display = displayMap[device];
00126 IntPtr currentModePtr = CG.DisplayCurrentMode(display);
00127
00128 if (storedModes.ContainsKey(display) == false)
00129 {
00130 storedModes.Add(display, currentModePtr);
00131 }
00132
00133 IntPtr displayModesPtr = CG.DisplayAvailableModes(display);
00134 CFArray displayModes = new CFArray(displayModesPtr);
00135
00136 for (int j = 0; j < displayModes.Count; j++)
00137 {
00138 CFDictionary dict = new CFDictionary(displayModes[j]);
00139
00140 int width = (int)dict.GetNumberValue("Width");
00141 int height = (int)dict.GetNumberValue("Height");
00142 int bpp = (int)dict.GetNumberValue("BitsPerPixel");
00143 double freq = dict.GetNumberValue("RefreshRate");
00144
00145 if (width == resolution.Width &&
00146 height == resolution.Height &&
00147 bpp == resolution.BitsPerPixel &&
00148 System.Math.Abs(freq - resolution.RefreshRate) < 1e-6)
00149 {
00150 if (displaysCaptured.Contains(display) == false)
00151 {
00152 CG.DisplayCapture(display);
00153 }
00154
00155 Debug.Print("Changing resolution to {0}x{1}x{2}@{3}.", width, height, bpp, freq);
00156
00157 CG.DisplaySwitchToMode(display, displayModes[j]);
00158
00159 return true;
00160 }
00161
00162 }
00163 return false;
00164 }
00165
00166 public bool TryRestoreResolution(DisplayDevice device)
00167 {
00168 IntPtr display = displayMap[device];
00169
00170 if (storedModes.ContainsKey(display))
00171 {
00172 Debug.Print("Restoring resolution.");
00173
00174 CG.DisplaySwitchToMode(display, storedModes[display]);
00175 CG.DisplayRelease(display);
00176 displaysCaptured.Remove(display);
00177
00178 return true;
00179 }
00180
00181 return false;
00182 }
00183
00184 #endregion
00185
00186 }
00187 }