00001
00002
00003
00004
00005
00006
00007
00008 using System;
00009 using System.Collections.Generic;
00010 using Microsoft.DirectX;
00011 using Microsoft.DirectX.Direct3D;
00012
00013 namespace Microsoft.Samples.DirectX.UtilityToolkit
00014 {
00018 public static class Enumeration
00019 {
00020 #region Creation (Not allowed)
00024 static Enumeration()
00025 {
00026
00027 ResetPossibleDepthStencilFormats();
00028 ResetPossibleMultisampleTypeList();
00029 ResetPossiblePresentIntervalList();
00030 }
00031 #endregion
00032
00033
00034 private static bool isPostPixelShaderBlendingRequired = true;
00035 private static IDeviceCreation deviceCreationInterface = null;
00036
00037
00038 private static bool isSoftwareVertexProcessing = true;
00039 private static bool isHardwareVertexProcessing = true;
00040 private static bool isPureHardwareVertexProcessing = true;
00041 private static bool isMixedVertexProcessing = false;
00042
00043
00044 private static uint minimumWidth = 0;
00045 private static uint maximumWidth = uint.MaxValue;
00046 private static uint minimumHeight = 0;
00047 private static uint maximumHeight = uint.MaxValue;
00048 private static uint minimumRefresh = 0;
00049 private static uint maximumRefresh = uint.MaxValue;
00050 private static uint multisampleQualityMax = 0xffff;
00051
00052
00053 private static List<DepthFormat> depthStencilPossibleList = new List<DepthFormat>();
00054 private static List<MultiSampleType> multiSampleTypeList = new List<MultiSampleType>();
00055 private static List<PresentInterval> presentIntervalList = new List<PresentInterval>();
00056 private static List<EnumAdapterInformation> adapterInformationList = new List<EnumAdapterInformation>();
00057
00058
00059 private static readonly Format[] allowedFormats = new Format[] {
00060 Format.X8R8G8B8,
00061 Format.X1R5G5B5,
00062 Format.R5G6B5,
00063 Format.A2R10G10B10 };
00064
00065 private static readonly Format[] backbufferFormatsArray = new Format[] {
00066 Format.A8R8G8B8,
00067 Format.X8R8G8B8,
00068 Format.A1R5G5B5,
00069 Format.X1R5G5B5,
00070 Format.R5G6B5,
00071 Format.A2R10G10B10 };
00072
00073 private static readonly DeviceType[] deviceTypeArray = new DeviceType[] {
00074 DeviceType.Hardware,
00075 DeviceType.Software,
00076 DeviceType.Reference };
00077
00078
00079
00080
00084 public static void Enumerate(IDeviceCreation acceptableCallback)
00085 {
00086 DisplayModeSorter sorter = new DisplayModeSorter();
00087 try
00088 {
00089
00090 deviceCreationInterface = acceptableCallback;
00091
00092
00093 adapterInformationList.Clear();
00094 List<Format> adapterFormatList = new List<Format>();
00095
00096
00097 foreach (AdapterDetails ai in Manager.Adapters)
00098 {
00099 EnumAdapterInformation adapterInfo = new EnumAdapterInformation();
00100
00101 adapterInfo.AdapterOrdinal = (uint)ai.Adapter;
00102 adapterInfo.AdapterInformation = ai.Information;
00103
00104
00105
00106 adapterFormatList.Clear();
00107
00108
00109 for (int i = 0; i < allowedFormats.Length; i++)
00110 {
00111
00112 foreach (DisplayMode dm in ai.SupportedDisplayModes[allowedFormats[i]])
00113 {
00114 if ((dm.Width < minimumWidth) ||
00115 (dm.Height < minimumHeight) ||
00116 (dm.Width > maximumWidth) ||
00117 (dm.Height > maximumHeight) ||
00118 (dm.RefreshRate < minimumRefresh) ||
00119 (dm.RefreshRate > maximumRefresh))
00120 {
00121 continue;
00122 }
00123
00124
00125 adapterInfo.displayModeList.Add(dm);
00126
00127
00128 if (!adapterFormatList.Contains(dm.Format))
00129 {
00130 adapterFormatList.Add(dm.Format);
00131 }
00132 }
00133 }
00134
00135
00136 DisplayMode currentAdapterMode = ai.CurrentDisplayMode;
00137
00138 if (!adapterFormatList.Contains(currentAdapterMode.Format))
00139 {
00140 adapterFormatList.Add(currentAdapterMode.Format);
00141 }
00142
00143
00144 adapterInfo.displayModeList.Sort(sorter);
00145
00146
00147 EnumerateDevices(adapterInfo, adapterFormatList);
00148
00149
00150
00151 if (adapterInfo.deviceInfoList.Count > 0)
00152 {
00153 adapterInformationList.Add(adapterInfo);
00154 }
00155 }
00156
00157
00158 bool isUnique = true;
00159 for (int i = 0; i < adapterInformationList.Count; i++)
00160 {
00161 for (int j = i + 1; j < adapterInformationList.Count; j++)
00162 {
00163 EnumAdapterInformation eai1 = adapterInformationList[i] as EnumAdapterInformation;
00164 EnumAdapterInformation eai2 = adapterInformationList[j] as EnumAdapterInformation;
00165
00166 if (string.Compare(eai1.AdapterInformation.Description,
00167 eai2.AdapterInformation.Description, true) == 0)
00168 {
00169 isUnique = false;
00170 break;
00171 }
00172 }
00173 if (!isUnique)
00174 break;
00175 }
00176
00177
00178 for (int i = 0; i < adapterInformationList.Count; i++)
00179 {
00180 EnumAdapterInformation eai1 = adapterInformationList[i] as EnumAdapterInformation;
00181
00182 eai1.UniqueDescription = eai1.AdapterInformation.Description;
00183
00184 if (!isUnique)
00185 eai1.UniqueDescription += string.Format(" (#{0})", eai1.AdapterOrdinal);
00186 }
00187 }
00188 catch (TypeLoadException)
00189 {
00190
00191 throw new NoDirect3DException();
00192 }
00193 }
00194
00198 private static void EnumerateDevices(EnumAdapterInformation adapterInfo, List<Format> adapterFormatList)
00199 {
00200
00201 DirectXException.IsExceptionIgnored = true;
00202
00203 for (uint i = 0; i < deviceTypeArray.Length; i++)
00204 {
00205
00206 EnumDeviceInformation deviceInfo = new EnumDeviceInformation();
00207
00208
00209 deviceInfo.DeviceType = deviceTypeArray[i];
00210
00211
00212 deviceInfo.Caps = Manager.GetDeviceCapabilities((int)adapterInfo.AdapterOrdinal, deviceInfo.DeviceType);
00213
00214
00215 EnumerateDeviceCombos(adapterInfo, deviceInfo, adapterFormatList);
00216
00217
00218 if (deviceInfo.deviceSettingsList.Count > 0)
00219 {
00220
00221 adapterInfo.deviceInfoList.Add(deviceInfo);
00222 }
00223 }
00224
00225 DirectXException.IsExceptionIgnored = false;
00226 }
00227
00231 private static void EnumerateDeviceCombos(EnumAdapterInformation adapterInfo, EnumDeviceInformation deviceInfo,
00232 List<Format> adapterFormatList)
00233 {
00234
00235 foreach (Format adapterFormat in adapterFormatList)
00236 {
00237 for (int i = 0; i < backbufferFormatsArray.Length; i++)
00238 {
00239
00240 for (int windowedIndex = 0; windowedIndex < 2; windowedIndex++)
00241 {
00242 bool isWindowedIndex = (windowedIndex == 1);
00243 if ((!isWindowedIndex) && (adapterInfo.displayModeList.Count == 0))
00244 continue;
00245
00246 if (!Manager.CheckDeviceType((int)adapterInfo.AdapterOrdinal, deviceInfo.DeviceType,
00247 adapterFormat, backbufferFormatsArray[i], isWindowedIndex))
00248 continue;
00249
00250
00251 if (isPostPixelShaderBlendingRequired)
00252 {
00253
00254
00255
00256 if (!Manager.CheckDeviceFormat((int)adapterInfo.AdapterOrdinal, deviceInfo.DeviceType,
00257 adapterFormat, Usage.QueryPostPixelShaderBlending,
00258 ResourceType.Texture, backbufferFormatsArray[i]))
00259 continue;
00260 }
00261
00262
00263
00264 if (deviceCreationInterface != null)
00265 {
00266 if (!deviceCreationInterface.IsDeviceAcceptable(deviceInfo.Caps,
00267 adapterFormat, backbufferFormatsArray[i], isWindowedIndex))
00268 continue;
00269 }
00270
00271
00272
00273
00274
00275
00276 EnumDeviceSettingsCombo deviceCombo = new EnumDeviceSettingsCombo();
00277
00278
00279 deviceCombo.AdapterOrdinal = adapterInfo.AdapterOrdinal;
00280 deviceCombo.DeviceType = deviceInfo.DeviceType;
00281 deviceCombo.AdapterFormat = adapterFormat;
00282 deviceCombo.BackBufferFormat = backbufferFormatsArray[i];
00283 deviceCombo.IsWindowed = isWindowedIndex;
00284
00285
00286 BuildDepthStencilFormatList(deviceCombo);
00287 BuildMultiSampleTypeList(deviceCombo);
00288 if (deviceCombo.multiSampleTypeList.Count == 0)
00289 {
00290
00291 continue;
00292 }
00293
00294 BuildConflictList(deviceCombo);
00295 BuildPresentIntervalList(deviceInfo, deviceCombo);
00296
00297 deviceCombo.adapterInformation = adapterInfo;
00298 deviceCombo.deviceInformation = deviceInfo;
00299
00300
00301 deviceInfo.deviceSettingsList.Add(deviceCombo);
00302 }
00303 }
00304 }
00305 }
00306
00311 private static void BuildDepthStencilFormatList(EnumDeviceSettingsCombo deviceCombo)
00312 {
00313 foreach (DepthFormat depthStencil in depthStencilPossibleList)
00314 {
00315 if (Manager.CheckDeviceFormat((int)deviceCombo.AdapterOrdinal,
00316 deviceCombo.DeviceType, deviceCombo.AdapterFormat,
00317 Usage.DepthStencil, ResourceType.Surface, depthStencil))
00318 {
00319
00320 if (Manager.CheckDepthStencilMatch((int)deviceCombo.AdapterOrdinal,
00321 deviceCombo.DeviceType, deviceCombo.AdapterFormat,
00322 deviceCombo.BackBufferFormat, depthStencil))
00323 {
00324
00325 deviceCombo.depthStencilFormatList.Add(depthStencil);
00326 }
00327 }
00328 }
00329 }
00330
00335 private static void BuildMultiSampleTypeList(EnumDeviceSettingsCombo deviceCombo)
00336 {
00337 foreach (MultiSampleType msType in multiSampleTypeList)
00338 {
00339 int quality;
00340
00341 if (Manager.CheckDeviceMultiSampleType((int)deviceCombo.AdapterOrdinal,
00342 deviceCombo.DeviceType, deviceCombo.BackBufferFormat,
00343 deviceCombo.IsWindowed, msType, out quality))
00344 {
00345 deviceCombo.multiSampleTypeList.Add(msType);
00346 if (quality > multisampleQualityMax + 1)
00347 quality = (int)(multisampleQualityMax + 1);
00348
00349 deviceCombo.multiSampleQualityList.Add(quality);
00350 }
00351 }
00352 }
00353
00354
00359 private static void BuildConflictList(EnumDeviceSettingsCombo deviceCombo)
00360 {
00361 foreach (DepthFormat depthFormat in deviceCombo.depthStencilFormatList)
00362 {
00363 foreach (MultiSampleType msType in deviceCombo.multiSampleTypeList)
00364 {
00365
00366 if (!Manager.CheckDeviceMultiSampleType((int)deviceCombo.AdapterOrdinal,
00367 deviceCombo.DeviceType, (Format)depthFormat,
00368 deviceCombo.IsWindowed, msType))
00369 {
00370
00371 EnumDepthStencilMultisampleConflict conflict = new EnumDepthStencilMultisampleConflict();
00372 conflict.DepthStencilFormat = depthFormat;
00373 conflict.MultisampleType = msType;
00374 deviceCombo.depthStencilConflictList.Add(conflict);
00375 }
00376 }
00377 }
00378 }
00379
00380
00385 private static void BuildPresentIntervalList(EnumDeviceInformation deviceInfo, EnumDeviceSettingsCombo deviceCombo)
00386 {
00387 for (int i = 0; i < presentIntervalList.Count; i++)
00388 {
00389 PresentInterval pi = (PresentInterval)presentIntervalList[i];
00390 if (deviceCombo.IsWindowed)
00391 {
00392 if ((pi == PresentInterval.Two) ||
00393 (pi == PresentInterval.Three) ||
00394 (pi == PresentInterval.Four))
00395 {
00396
00397 continue;
00398 }
00399 }
00400
00401
00402
00403 if ((pi == PresentInterval.Default) ||
00404 ((deviceInfo.Caps.PresentInterval & pi) != 0))
00405 {
00406 deviceCombo.presentIntervalList.Add(pi);
00407 }
00408 }
00409 }
00410
00414 public static void ResetPossibleDepthStencilFormats()
00415 {
00416 depthStencilPossibleList.Clear();
00417 depthStencilPossibleList.AddRange(new DepthFormat[] {
00418 DepthFormat.D16,
00419 DepthFormat.D15S1,
00420 DepthFormat.D24X8,
00421 DepthFormat.D24S8,
00422 DepthFormat.D24X4S4,
00423 DepthFormat.D32 });
00424 }
00425
00429 public static void ResetPossibleMultisampleTypeList()
00430 {
00431 multiSampleTypeList.Clear();
00432 multiSampleTypeList.AddRange(new MultiSampleType[] {
00433 MultiSampleType.None,
00434 MultiSampleType.NonMaskable,
00435 MultiSampleType.TwoSamples,
00436 MultiSampleType.ThreeSamples,
00437 MultiSampleType.FourSamples,
00438 MultiSampleType.FiveSamples,
00439 MultiSampleType.SixSamples,
00440 MultiSampleType.SevenSamples,
00441 MultiSampleType.EightSamples,
00442 MultiSampleType.NineSamples,
00443 MultiSampleType.TenSamples,
00444 MultiSampleType.ElevenSamples,
00445 MultiSampleType.TwelveSamples,
00446 MultiSampleType.ThirteenSamples,
00447 MultiSampleType.FourteenSamples,
00448 MultiSampleType.FifteenSamples,
00449 MultiSampleType.SixteenSamples });
00450 }
00451
00455 public static void ResetPossiblePresentIntervalList()
00456 {
00457 presentIntervalList.Clear();
00458 presentIntervalList.AddRange(new PresentInterval[] {
00459 PresentInterval.Immediate,
00460 PresentInterval.Default,
00461 PresentInterval.One,
00462 PresentInterval.Two,
00463 PresentInterval.Three,
00464 PresentInterval.Four });
00465 }
00466
00470 public static void SetResolutionMinMax(uint minWidth, uint minHeight, uint maxWidth, uint maxHeight)
00471 {
00472 minimumWidth = minWidth;
00473 minimumHeight = minHeight;
00474 maximumWidth = maxHeight;
00475 maximumWidth = maxWidth;
00476 }
00477
00481 public static void SetRefreshMinMax(uint minRefresh, uint maxRefresh)
00482 {
00483 minimumRefresh = minRefresh;
00484 maximumRefresh = maxRefresh;
00485 }
00486
00490 public static uint MultisampleQualityMax
00491 {
00492 get { return multisampleQualityMax; }
00493 set
00494 {
00495 if (value > 0xffff)
00496 multisampleQualityMax = 0xffff;
00497 else
00498 multisampleQualityMax = value;
00499 }
00500 }
00501
00505 public static bool IsPostPixelShaderBlendingRequred
00506 {
00507 get { return isPostPixelShaderBlendingRequired; }
00508 set { isPostPixelShaderBlendingRequired = value; }
00509 }
00510
00514 public static bool IsSoftwareVertexProcessingPossible
00515 {
00516 get { return isSoftwareVertexProcessing; }
00517 set { isSoftwareVertexProcessing = value; }
00518 }
00519
00523 public static bool IsHardwareVertexProcessingPossible
00524 {
00525 get { return isHardwareVertexProcessing; }
00526 set { isHardwareVertexProcessing = value; }
00527 }
00528
00532 public static bool IsPureHardwareVertexProcessingPossible
00533 {
00534 get { return isPureHardwareVertexProcessing; }
00535 set { isPureHardwareVertexProcessing = value; }
00536 }
00537
00541 public static bool IsMixedVertexProcessingPossible
00542 {
00543 get { return isMixedVertexProcessing; }
00544 set { isMixedVertexProcessing = value; }
00545 }
00546
00550 public static List<DepthFormat> PossibleDepthStencilFormatList
00551 {
00552 get { return depthStencilPossibleList; }
00553 }
00554
00558 public static List<MultiSampleType> PossibleMultisampleTypeList
00559 {
00560 get { return multiSampleTypeList; }
00561 }
00562
00566 public static List<PresentInterval> PossiblePresentIntervalsList
00567 {
00568 get { return presentIntervalList; }
00569 }
00570
00574 public static List<EnumAdapterInformation> AdapterInformationList
00575 {
00576 get { return adapterInformationList; }
00577 }
00578
00582 public static EnumAdapterInformation GetAdapterInformation(uint ordinal)
00583 {
00584 foreach (EnumAdapterInformation eai in adapterInformationList)
00585 {
00586 if (eai.AdapterOrdinal == ordinal)
00587 {
00588 return eai;
00589 }
00590 }
00591
00592
00593 return null;
00594 }
00595
00599 public static EnumDeviceInformation GetDeviceInfo(uint ordinal, DeviceType deviceType)
00600 {
00601 EnumAdapterInformation info = GetAdapterInformation(ordinal);
00602 if (info != null)
00603 {
00604 foreach (EnumDeviceInformation edi in info.deviceInfoList)
00605 {
00606
00607 if (edi.DeviceType == deviceType)
00608 {
00609 return edi;
00610 }
00611 }
00612 }
00613
00614
00615 return null;
00616 }
00617
00621 public static EnumDeviceSettingsCombo GetDeviceSettingsCombo(uint ordinal, DeviceType deviceType,
00622 Format adapterFormat, Format backBufferFormat, bool isWindowed)
00623 {
00624 EnumDeviceInformation info = GetDeviceInfo(ordinal, deviceType);
00625 if (info != null)
00626 {
00627 foreach (EnumDeviceSettingsCombo edsc in info.deviceSettingsList)
00628 {
00629
00630 if ((edsc.AdapterFormat == adapterFormat) &&
00631 (edsc.BackBufferFormat == backBufferFormat) &&
00632 (edsc.IsWindowed == isWindowed))
00633 {
00634 return edsc;
00635 }
00636 }
00637 }
00638
00639
00640 return null;
00641 }
00642
00646 public static EnumDeviceSettingsCombo GetDeviceSettingsCombo(DeviceSettings settings)
00647 {
00648 return GetDeviceSettingsCombo(settings.AdapterOrdinal, settings.DeviceType, settings.AdapterFormat,
00649 settings.presentParams.BackBufferFormat, settings.presentParams.IsWindowed);
00650 }
00651 }
00652
00657 public class EnumAdapterInformation
00658 {
00659 public uint AdapterOrdinal;
00660 public AdapterInformation AdapterInformation;
00661 public List<DisplayMode> displayModeList = new List<DisplayMode>();
00662 public List<EnumDeviceInformation> deviceInfoList = new List<EnumDeviceInformation>();
00663 public string UniqueDescription;
00664 }
00665
00670 public class EnumDeviceInformation
00671 {
00672 public uint AdapterOrdinal;
00673 public DeviceType DeviceType;
00674 public Capabilities Caps;
00675 public List<EnumDeviceSettingsCombo> deviceSettingsList = new List<EnumDeviceSettingsCombo>();
00676 }
00677
00683 public class EnumDeviceSettingsCombo
00684 {
00685 public uint AdapterOrdinal;
00686 public DeviceType DeviceType;
00687 public Format AdapterFormat;
00688 public Format BackBufferFormat;
00689 public bool IsWindowed;
00690
00691
00692 public List<DepthFormat> depthStencilFormatList = new List<DepthFormat>();
00693 public List<MultiSampleType> multiSampleTypeList = new List<MultiSampleType>();
00694 public List<int> multiSampleQualityList = new List<int>();
00695 public List<PresentInterval> presentIntervalList = new List<PresentInterval>();
00696 public List<EnumDepthStencilMultisampleConflict> depthStencilConflictList = new List<EnumDepthStencilMultisampleConflict>();
00697
00698 public EnumAdapterInformation adapterInformation = null;
00699 public EnumDeviceInformation deviceInformation = null;
00700 }
00701
00706 public struct EnumDepthStencilMultisampleConflict
00707 {
00708 public DepthFormat DepthStencilFormat;
00709 public MultiSampleType MultisampleType;
00710 }
00711
00715 public class DisplayModeSorter : System.Collections.Generic.IComparer<DisplayMode>
00716 {
00717 #region IComparer<DisplayMode> Members
00718 public int Compare(DisplayMode d1, DisplayMode d2)
00719 {
00720 if (d1.Width > d2.Width)
00721 return +1;
00722 if (d1.Width < d2.Width)
00723 return -1;
00724 if (d1.Height > d2.Height)
00725 return +1;
00726 if (d1.Height < d2.Height)
00727 return -1;
00728 if (d1.Format > d2.Format)
00729 return +1;
00730 if (d1.Format < d2.Format)
00731 return -1;
00732 if (d1.RefreshRate > d2.RefreshRate)
00733 return +1;
00734 if (d1.RefreshRate < d2.RefreshRate)
00735 return -1;
00736
00737
00738 return 0;
00739 }
00740 #endregion
00741 }
00742
00743 #region Helper Utility Class
00747 static class ManagedUtility
00748 {
00752 public static uint GetColorChannelBits(Format format)
00753 {
00754 switch (format)
00755 {
00756 case Format.R8G8B8:
00757 case Format.A8R8G8B8:
00758 case Format.X8R8G8B8:
00759 return 8;
00760 case Format.R5G6B5:
00761 case Format.X1R5G5B5:
00762 case Format.A1R5G5B5:
00763 return 5;
00764 case Format.A4R4G4B4:
00765 case Format.X4R4G4B4:
00766 return 4;
00767 case Format.R3G3B2:
00768 case Format.A8R3G3B2:
00769 return 2;
00770 case Format.A2B10G10R10:
00771 case Format.A2R10G10B10:
00772 return 10;
00773 default:
00774 return 0;
00775 }
00776 }
00777
00781 public static uint GetAlphaChannelBits(Format format)
00782 {
00783 switch (format)
00784 {
00785 case Format.X8R8G8B8:
00786 case Format.R8G8B8:
00787 case Format.R5G6B5:
00788 case Format.X1R5G5B5:
00789 case Format.R3G3B2:
00790 case Format.X4R4G4B4:
00791 return 0;
00792 case Format.A8R3G3B2:
00793 case Format.A8R8G8B8:
00794 return 8;
00795 case Format.A1R5G5B5:
00796 return 1;
00797 case Format.A4R4G4B4:
00798 return 4;
00799 case Format.A2B10G10R10:
00800 case Format.A2R10G10B10:
00801 return 2;
00802 default:
00803 return 0;
00804 }
00805 }
00806
00810 public static uint GetDepthBits(DepthFormat format)
00811 {
00812 switch (format)
00813 {
00814 case DepthFormat.D16:
00815 case DepthFormat.D16Lockable:
00816 return 16;
00817
00818 case DepthFormat.D15S1:
00819 return 15;
00820
00821 case DepthFormat.D24X8:
00822 case DepthFormat.D24S8:
00823 case DepthFormat.D24X4S4:
00824 case DepthFormat.D24SingleS8:
00825 return 24;
00826
00827 case DepthFormat.D32:
00828 case DepthFormat.D32SingleLockable:
00829 return 32;
00830 default:
00831 return 0;
00832 }
00833 }
00834
00838 public static uint GetStencilBits(DepthFormat format)
00839 {
00840 switch (format)
00841 {
00842 case DepthFormat.D16:
00843 case DepthFormat.D16Lockable:
00844 case DepthFormat.D24X8:
00845 case DepthFormat.D32:
00846 case DepthFormat.D32SingleLockable:
00847 return 0;
00848
00849 case DepthFormat.D15S1:
00850 return 1;
00851
00852 case DepthFormat.D24X4S4:
00853 return 4;
00854
00855 case DepthFormat.D24SingleS8:
00856 case DepthFormat.D24S8:
00857 return 8;
00858
00859 default:
00860 return 0;
00861 }
00862 }
00863 }
00864 #endregion
00865 }