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