Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenadapter.c
Go to the documentation of this file.
00001 /* 00002 * COPYRIGHT: See COPYING in the top level directory 00003 * PROJECT: ReactOS ReactX 00004 * FILE: dll/directx/d3d9/adapter.c 00005 * PURPOSE: d3d9.dll adapter info functions 00006 * PROGRAMERS: Gregor Brunmar <gregor (dot) brunmar (at) home (dot) se> 00007 */ 00008 00009 #include "d3d9_common.h" 00010 #include <d3d9.h> 00011 #include <ddraw.h> 00012 #include <debug.h> 00013 #include <d3dhal.h> 00014 #include "d3d9_private.h" 00015 #include "d3d9_helpers.h" 00016 #include "adapter.h" 00017 00018 #define D3D9_CAPS1 (D3DCAPS_READ_SCANLINE) 00019 #define D3D9_PRE_XP_CAPS2 (D3DCAPS2_CANAUTOGENMIPMAP | D3DCAPS2_DYNAMICTEXTURES | D3DCAPS2_RESERVED | D3DCAPS2_FULLSCREENGAMMA) 00020 #define D3D9_XP_OR_LATER_CAPS2 (D3D9_PRE_XP_CAPS2 | D3DCAPS2_CANMANAGERESOURCE) 00021 #define D3D9_CAPS3 (D3DCAPS3_ALPHA_FULLSCREEN_FLIP_OR_DISCARD | D3DCAPS3_LINEAR_TO_SRGB_PRESENTATION | D3DCAPS3_COPY_TO_VIDMEM | D3DCAPS3_COPY_TO_SYSTEMMEM) 00022 #define D3D9_DEVCAPS (D3DDEVCAPS_EXECUTESYSTEMMEMORY | D3DDEVCAPS_EXECUTEVIDEOMEMORY | D3DDEVCAPS_TLVERTEXSYSTEMMEMORY \ 00023 | D3DDEVCAPS_TLVERTEXVIDEOMEMORY | D3DDEVCAPS_TEXTURESYSTEMMEMORY | D3DDEVCAPS_TEXTUREVIDEOMEMORY \ 00024 | D3DDEVCAPS_DRAWPRIMTLVERTEX | D3DDEVCAPS_CANRENDERAFTERFLIP | D3DDEVCAPS_TEXTURENONLOCALVIDMEM \ 00025 | D3DDEVCAPS_DRAWPRIMITIVES2 | D3DDEVCAPS_SEPARATETEXTUREMEMORIES | D3DDEVCAPS_DRAWPRIMITIVES2EX \ 00026 | D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_CANBLTSYSTONONLOCAL | D3DDEVCAPS_HWRASTERIZATION \ 00027 | D3DDEVCAPS_PUREDEVICE | D3DDEVCAPS_QUINTICRTPATCHES | D3DDEVCAPS_RTPATCHES | D3DDEVCAPS_RTPATCHHANDLEZERO \ 00028 | D3DDEVCAPS_NPATCHES) 00029 00030 #define D3DCAPS2_PRESENT_INTERVAL_SEVERAL 0x00200000 00031 #define D3DCAPS2_PRESENT_INTERVAL_IMMEDIATE 0x00400000 00032 00033 #define D3DVTXPCAPS_FOGVERTEX 0x00000004 00034 00035 typedef BOOL (WINAPI *LPFN_ISWOW64PROCESS) (HANDLE, PBOOL); 00036 typedef BOOL (WINAPI *LPFN_DISABLEWOW64FSREDIRECTION) (PVOID*); 00037 typedef BOOL (WINAPI *LPFN_REVERTWOW64FSREDIRECTION) (PVOID); 00038 00039 00040 typedef struct _ADAPTERMONITOR 00041 { 00042 LPCSTR lpszDeviceName; 00043 HMONITOR hMonitor; 00044 } ADAPTERMONITOR, *LPADAPTERMONITOR; 00045 00046 00047 static BOOL GetDriverName(LPDISPLAY_DEVICEA pDisplayDevice, D3DADAPTER_IDENTIFIER9* pIdentifier) 00048 { 00049 HKEY hKey; 00050 BOOL bResult = FALSE; 00051 00052 if (ERROR_SUCCESS == RegOpenKeyExA(HKEY_LOCAL_MACHINE, pDisplayDevice->DeviceKey + strlen("\\Registry\\Machine\\"), 0, KEY_QUERY_VALUE, &hKey)) 00053 { 00054 DWORD DriverNameLength = MAX_DEVICE_IDENTIFIER_STRING - (DWORD)strlen(".dll"); 00055 DWORD Type = 0; 00056 00057 if (ERROR_SUCCESS == RegQueryValueExA(hKey, "InstalledDisplayDrivers", 0, &Type, (LPBYTE)pIdentifier->Driver, &DriverNameLength)) 00058 { 00059 pIdentifier->Driver[DriverNameLength] = '\0'; 00060 SafeAppendString(pIdentifier->Driver, MAX_DEVICE_IDENTIFIER_STRING, ".dll"); 00061 bResult = TRUE; 00062 } 00063 00064 RegCloseKey(hKey); 00065 } 00066 00067 return bResult; 00068 } 00069 00070 static void GetDriverVersion(LPDISPLAY_DEVICEA pDisplayDevice, D3DADAPTER_IDENTIFIER9* pIdentifier) 00071 { 00072 HMODULE hModule; 00073 LPFN_ISWOW64PROCESS fnIsWow64Process; 00074 BOOL bIsWow64 = FALSE; 00075 PVOID OldWow64RedirectValue; 00076 UINT DriverFileSize; 00077 00078 hModule = GetModuleHandleA("KERNEL32"); 00079 fnIsWow64Process = (LPFN_ISWOW64PROCESS)GetProcAddress(hModule, "IsWow64Process"); 00080 if (fnIsWow64Process) 00081 { 00082 fnIsWow64Process(GetCurrentProcess(), &bIsWow64); 00083 if (bIsWow64) 00084 { 00085 LPFN_DISABLEWOW64FSREDIRECTION fnDisableWow64FsRedirection; 00086 fnDisableWow64FsRedirection = (LPFN_DISABLEWOW64FSREDIRECTION)GetProcAddress(hModule, "Wow64DisableWow64FsRedirection"); 00087 fnDisableWow64FsRedirection(&OldWow64RedirectValue); 00088 } 00089 } 00090 00091 DriverFileSize = GetFileVersionInfoSizeA(pIdentifier->Driver, NULL); 00092 if (DriverFileSize > 0) 00093 { 00094 VS_FIXEDFILEINFO* FixedFileInfo = NULL; 00095 LPVOID pBlock = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, DriverFileSize); 00096 00097 if (TRUE == GetFileVersionInfoA(pIdentifier->Driver, 0, DriverFileSize, pBlock)) 00098 { 00099 if (TRUE == VerQueryValueA(pBlock, "\\", (LPVOID*)&FixedFileInfo, &DriverFileSize)) 00100 { 00101 pIdentifier->DriverVersion.HighPart = FixedFileInfo->dwFileVersionMS; 00102 pIdentifier->DriverVersion.LowPart = FixedFileInfo->dwFileVersionLS; 00103 } 00104 } 00105 00106 HeapFree(GetProcessHeap(), 0, pBlock); 00107 } 00108 00109 if (bIsWow64) 00110 { 00111 LPFN_REVERTWOW64FSREDIRECTION fnRevertWow64FsRedirection; 00112 fnRevertWow64FsRedirection = (LPFN_REVERTWOW64FSREDIRECTION)GetProcAddress(hModule, "Wow64RevertWow64FsRedirection"); 00113 fnRevertWow64FsRedirection(&OldWow64RedirectValue); 00114 } 00115 } 00116 00117 00118 static void ParseField(LPCSTR lpszDeviceKey, LPDWORD pField, LPCSTR lpszSubString) 00119 { 00120 const char* ResultStr; 00121 ResultStr = strstr(lpszDeviceKey, lpszSubString); 00122 if (ResultStr != NULL) 00123 { 00124 *pField = strtol(ResultStr + strlen(lpszSubString), NULL, 16); 00125 } 00126 } 00127 00128 static void GetDeviceId(LPCSTR lpszDeviceKey, D3DADAPTER_IDENTIFIER9* pIdentifier) 00129 { 00130 ParseField(lpszDeviceKey, &pIdentifier->VendorId, "VEN_"); 00131 ParseField(lpszDeviceKey, &pIdentifier->DeviceId, "DEV_"); 00132 ParseField(lpszDeviceKey, &pIdentifier->SubSysId, "SUBSYS_"); 00133 ParseField(lpszDeviceKey, &pIdentifier->Revision, "REV_"); 00134 } 00135 00136 static void GenerateDeviceIdentifier(D3DADAPTER_IDENTIFIER9* pIdentifier) 00137 { 00138 DWORD* dwIdentifier = (DWORD*)&pIdentifier->DeviceIdentifier; 00139 00140 pIdentifier->DeviceIdentifier = CLSID_DirectDraw; 00141 00142 dwIdentifier[0] ^= pIdentifier->VendorId; 00143 dwIdentifier[1] ^= pIdentifier->DeviceId; 00144 dwIdentifier[2] ^= pIdentifier->SubSysId; 00145 dwIdentifier[3] ^= pIdentifier->Revision; 00146 dwIdentifier[2] ^= pIdentifier->DriverVersion.LowPart; 00147 dwIdentifier[3] ^= pIdentifier->DriverVersion.HighPart; 00148 } 00149 00150 BOOL GetAdapterInfo(LPCSTR lpszDeviceName, D3DADAPTER_IDENTIFIER9* pIdentifier) 00151 { 00152 DISPLAY_DEVICEA DisplayDevice; 00153 DWORD AdapterIndex; 00154 BOOL FoundDisplayDevice; 00155 00156 memset(&DisplayDevice, 0, sizeof(DISPLAY_DEVICEA)); 00157 DisplayDevice.cb = sizeof(DISPLAY_DEVICEA); 00158 00159 AdapterIndex = 0; 00160 FoundDisplayDevice = FALSE; 00161 while (EnumDisplayDevicesA(NULL, AdapterIndex, &DisplayDevice, 0) == TRUE) 00162 { 00163 if (_stricmp(lpszDeviceName, DisplayDevice.DeviceName) == 0) 00164 { 00165 FoundDisplayDevice = TRUE; 00166 break; 00167 } 00168 00169 ++AdapterIndex; 00170 } 00171 00172 /* No matching display device found? */ 00173 if (FALSE == FoundDisplayDevice) 00174 return FALSE; 00175 00176 lstrcpynA(pIdentifier->Description, DisplayDevice.DeviceString, MAX_DEVICE_IDENTIFIER_STRING); 00177 lstrcpynA(pIdentifier->DeviceName, DisplayDevice.DeviceName, CCHDEVICENAME); 00178 00179 if (GetDriverName(&DisplayDevice, pIdentifier) == TRUE) 00180 GetDriverVersion(&DisplayDevice, pIdentifier); 00181 00182 GetDeviceId(DisplayDevice.DeviceID, pIdentifier); 00183 00184 GenerateDeviceIdentifier(pIdentifier); 00185 00186 return TRUE; 00187 } 00188 00189 00190 00191 static BOOL IsWindowsXPorLaterCompatible() 00192 { 00193 OSVERSIONINFOA osvi; 00194 00195 ZeroMemory(&osvi, sizeof(OSVERSIONINFOA)); 00196 osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOA); 00197 00198 if (GetVersionExA(&osvi) != 0) 00199 { 00200 return ( (osvi.dwMajorVersion > 5) || 00201 ( (osvi.dwMajorVersion == 5) && (osvi.dwMinorVersion >= 1) )); 00202 } 00203 00204 return FALSE; 00205 } 00206 00207 static void CopyDriverCaps(const D3DCAPS9* pSrcCaps, D3DCAPS9* pDstCaps) 00208 { 00209 *pDstCaps = *pSrcCaps; 00210 00211 pDstCaps->Caps = pSrcCaps->Caps & D3D9_CAPS1; 00212 00213 /* TODO: Fit in D3DCAPS2_CANCALIBRATEGAMMA somewhere here */ 00214 if (IsWindowsXPorLaterCompatible()) 00215 pDstCaps->Caps2 = pSrcCaps->Caps2 & D3D9_XP_OR_LATER_CAPS2; 00216 else 00217 pDstCaps->Caps2 = pSrcCaps->Caps2 & D3D9_PRE_XP_CAPS2; 00218 00219 pDstCaps->Caps3 = pSrcCaps->Caps3 & D3D9_CAPS3; 00220 pDstCaps->DevCaps = pSrcCaps->DevCaps & D3D9_DEVCAPS; 00221 00222 pDstCaps->PresentationIntervals = D3DPRESENT_INTERVAL_ONE; 00223 if (pSrcCaps->Caps2 & D3DCAPS2_PRESENT_INTERVAL_SEVERAL) 00224 pDstCaps->PresentationIntervals |= (D3DPRESENT_INTERVAL_TWO | D3DPRESENT_INTERVAL_THREE | D3DPRESENT_INTERVAL_FOUR); 00225 if (pSrcCaps->Caps2 & D3DCAPS2_PRESENT_INTERVAL_IMMEDIATE) 00226 pDstCaps->PresentationIntervals |= D3DPRESENT_INTERVAL_IMMEDIATE; 00227 00228 pDstCaps->PrimitiveMiscCaps = pSrcCaps->PrimitiveMiscCaps & ~D3DPMISCCAPS_FOGINFVF; 00229 00230 if (pSrcCaps->VertexProcessingCaps & D3DVTXPCAPS_FOGVERTEX) 00231 { 00232 pDstCaps->RasterCaps |= D3DPRASTERCAPS_FOGVERTEX; 00233 pDstCaps->VertexProcessingCaps &= ~D3DVTXPCAPS_FOGVERTEX; 00234 } 00235 00236 if (pSrcCaps->MaxPointSize < 0.0f) 00237 pDstCaps->MaxPointSize = 1.0f; 00238 } 00239 00240 HRESULT GetAdapterCaps(const LPDIRECT3D9_DISPLAYADAPTER pDisplayAdapter, D3DDEVTYPE DeviceType, D3DCAPS9* pDstCaps) 00241 { 00242 HRESULT hResult = D3DERR_INVALIDDEVICE; 00243 D3DCAPS9* pDriverCaps = NULL; 00244 00245 ZeroMemory(pDstCaps, sizeof(D3DCAPS9)); 00246 00247 switch (DeviceType) 00248 { 00249 case D3DDEVTYPE_HAL: 00250 pDriverCaps = &pDisplayAdapter->DriverCaps.DriverCaps9; 00251 hResult = D3D_OK; 00252 break; 00253 00254 case D3DDEVTYPE_REF: 00255 case D3DDEVTYPE_SW: 00256 case D3DDEVTYPE_NULLREF: 00257 UNIMPLEMENTED; 00258 hResult = D3D_OK; 00259 break; 00260 00261 default: 00262 DPRINT1("Unknown DeviceType argument"); 00263 break; 00264 } 00265 00266 if (pDriverCaps != NULL) 00267 { 00268 CopyDriverCaps(pDriverCaps, pDstCaps); 00269 } 00270 00271 if (SUCCEEDED(hResult)) 00272 { 00273 pDstCaps->DeviceType = DeviceType; 00274 pDstCaps->MasterAdapterOrdinal = pDisplayAdapter->MasterAdapterIndex; 00275 pDstCaps->AdapterOrdinalInGroup = pDisplayAdapter->AdapterIndexInGroup; 00276 pDstCaps->NumberOfAdaptersInGroup = pDisplayAdapter->NumAdaptersInGroup; 00277 } 00278 00279 return hResult; 00280 } 00281 00282 00283 00284 static D3DFORMAT Get16BitD3DFormat(LPCSTR lpszDeviceName) 00285 { 00286 HDC hDC; 00287 HBITMAP hBitmap; 00288 LPBITMAPINFO pBitmapInfo; 00289 D3DFORMAT Format = D3DFMT_R5G6B5; 00290 00291 if (NULL == (hDC = CreateDCA(NULL, lpszDeviceName, NULL, NULL))) 00292 { 00293 return Format; 00294 } 00295 00296 if (NULL == (hBitmap = CreateCompatibleBitmap(hDC, 1, 1))) 00297 { 00298 DeleteDC(hDC); 00299 return Format; 00300 } 00301 00302 pBitmapInfo = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(BITMAPINFOHEADER) + 4 * sizeof(RGBQUAD)); 00303 if (NULL == pBitmapInfo) 00304 { 00305 DeleteObject(hBitmap); 00306 DeleteDC(hDC); 00307 return Format; 00308 } 00309 00310 pBitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); 00311 if (GetDIBits(hDC, hBitmap, 0, 0, NULL, pBitmapInfo, DIB_RGB_COLORS) > 0) 00312 { 00313 if (pBitmapInfo->bmiHeader.biCompression == BI_BITFIELDS) 00314 { 00315 if (GetDIBits(hDC, hBitmap, 0, pBitmapInfo->bmiHeader.biHeight, NULL, pBitmapInfo, DIB_RGB_COLORS) > 0) 00316 { 00317 /* Check if the green field is 6 bits long */ 00318 if (*(DWORD*)(&pBitmapInfo->bmiColors[1]) == 0x000003E0) 00319 { 00320 Format = D3DFMT_X1R5G5B5; 00321 } 00322 } 00323 } 00324 } 00325 00326 HeapFree(GetProcessHeap(), 0, pBitmapInfo); 00327 DeleteObject(hBitmap); 00328 DeleteDC(hDC); 00329 00330 return Format; 00331 } 00332 00333 BOOL GetAdapterMode(LPCSTR lpszDeviceName, D3DDISPLAYMODE* pMode) 00334 { 00335 DEVMODEA DevMode; 00336 00337 memset(&DevMode, 0, sizeof(DEVMODEA)); 00338 DevMode.dmSize = sizeof(DEVMODEA); 00339 if (FALSE == EnumDisplaySettingsA(lpszDeviceName, ENUM_CURRENT_SETTINGS, &DevMode)) 00340 return FALSE; 00341 00342 pMode->Width = DevMode.dmPelsWidth; 00343 pMode->Height = DevMode.dmPelsHeight; 00344 pMode->RefreshRate = DevMode.dmDisplayFrequency; 00345 00346 switch (DevMode.dmBitsPerPel) 00347 { 00348 case 8: 00349 pMode->Format = D3DFMT_P8; 00350 break; 00351 00352 case 16: 00353 pMode->Format = Get16BitD3DFormat(lpszDeviceName); 00354 break; 00355 00356 case 24: 00357 pMode->Format = D3DFMT_R8G8B8; 00358 break; 00359 00360 case 32: 00361 pMode->Format = D3DFMT_X8R8G8B8; 00362 break; 00363 00364 default: 00365 pMode->Format = D3DFMT_UNKNOWN; 00366 break; 00367 } 00368 00369 return TRUE; 00370 } 00371 00372 00373 00374 static BOOL CALLBACK AdapterMonitorEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) 00375 { 00376 MONITORINFOEXA MonitorInfoEx; 00377 LPADAPTERMONITOR lpAdapterMonitor = (LPADAPTERMONITOR)dwData; 00378 00379 memset(&MonitorInfoEx, 0, sizeof(MONITORINFOEXA)); 00380 MonitorInfoEx.cbSize = sizeof(MONITORINFOEXA); 00381 00382 GetMonitorInfoA(hMonitor, (LPMONITORINFO)&MonitorInfoEx); 00383 00384 if (_stricmp(lpAdapterMonitor->lpszDeviceName, MonitorInfoEx.szDevice) == 0) 00385 { 00386 lpAdapterMonitor->hMonitor = hMonitor; 00387 return FALSE; 00388 } 00389 00390 return TRUE; 00391 } 00392 00393 HMONITOR GetAdapterMonitor(LPCSTR lpszDeviceName) 00394 { 00395 ADAPTERMONITOR AdapterMonitor; 00396 AdapterMonitor.lpszDeviceName = lpszDeviceName; 00397 AdapterMonitor.hMonitor = NULL; 00398 00399 EnumDisplayMonitors(NULL, NULL, AdapterMonitorEnumProc, (LPARAM)&AdapterMonitor); 00400 00401 return AdapterMonitor.hMonitor; 00402 } 00403 00404 00405 00406 UINT GetDisplayFormatCount(D3DFORMAT Format, const D3DDISPLAYMODE* pSupportedDisplayModes, UINT NumDisplayModes) 00407 { 00408 UINT DisplayModeIndex; 00409 UINT FormatIndex = 0; 00410 00411 for (DisplayModeIndex = 0; DisplayModeIndex < NumDisplayModes; DisplayModeIndex++) 00412 { 00413 if (pSupportedDisplayModes[DisplayModeIndex].Format == Format) 00414 { 00415 ++FormatIndex; 00416 } 00417 } 00418 00419 return FormatIndex; 00420 } 00421 00422 const D3DDISPLAYMODE* FindDisplayFormat(D3DFORMAT Format, UINT ModeIndex, const D3DDISPLAYMODE* pSupportedDisplayModes, UINT NumDisplayModes) 00423 { 00424 UINT DisplayModeIndex; 00425 UINT FormatIndex = 0; 00426 00427 for (DisplayModeIndex = 0; DisplayModeIndex < NumDisplayModes; DisplayModeIndex++) 00428 { 00429 if (pSupportedDisplayModes[DisplayModeIndex].Format == Format) 00430 { 00431 if (ModeIndex == FormatIndex) 00432 return &pSupportedDisplayModes[DisplayModeIndex]; 00433 00434 ++FormatIndex; 00435 } 00436 } 00437 00438 if (FormatIndex == 0) 00439 { 00440 DPRINT1("No modes with the specified format found"); 00441 } 00442 else if (FormatIndex < ModeIndex) 00443 { 00444 DPRINT1("Invalid mode index"); 00445 } 00446 00447 return NULL; 00448 } Generated on Sun May 27 2012 04:21:13 for ReactOS by
1.7.6.1
|