1 /* 2 * COPYRIGHT: See COPYING in the top level directory 3 * PROJECT: ReactOS ReactX 4 * FILE: dll/directx/d3d9/d3d9_create.c 5 * PURPOSE: d3d9.dll internal create functions and data 6 * PROGRAMERS: Gregor Brunmar <gregor (dot) brunmar (at) home (dot) se> 7 */ 8 9 #include <d3d9.h> 10 #include "d3d9_create.h" 11 #include "d3d9_helpers.h" 12 #include "d3d9_caps.h" 13 #include <debug.h> 14 #include <ddrawi.h> 15 #include <ddrawgdi.h> 16 17 static const GUID DISPLAY_GUID = { 0x67685559, 0x3106, 0x11D0, { 0xB9, 0x71, 0x00, 0xAA, 0x00, 0x34, 0x2F, 0x9F } }; 18 19 static CHAR D3D9_PrimaryDeviceName[CCHDEVICENAME]; 20 21 static BOOL IsDirectDrawSupported() 22 { 23 HDC hDC; 24 DWORD Planes; 25 DWORD Bpp; 26 27 hDC = GetDC(NULL); 28 Planes = GetDeviceCaps(hDC, PLANES); 29 Bpp = GetDeviceCaps(hDC, BITSPIXEL); 30 ReleaseDC(NULL, hDC); 31 32 if (Planes * Bpp < 8) 33 return FALSE; 34 35 return TRUE; 36 } 37 38 static VOID SetAdapterInfo(IN OUT LPDIRECT3D9_DISPLAYADAPTER pDisplayAdapter, IN LPDISPLAY_DEVICEA pDisplayDevice) 39 { 40 memcpy(&pDisplayAdapter->DisplayGuid, &DISPLAY_GUID, sizeof(GUID)); 41 42 lstrcpynA(pDisplayAdapter->szDeviceName, pDisplayDevice->DeviceName, MAX_PATH); 43 44 pDisplayAdapter->dwStateFlags = pDisplayDevice->StateFlags; 45 pDisplayAdapter->bInUseFlag = TRUE; 46 } 47 48 static BOOL IsGDIDriver(HDC hDC) 49 { 50 COLORREF NearestBlack = GetNearestColor(hDC, RGB(0, 0, 0)); 51 COLORREF NearestWhite = GetNearestColor(hDC, RGB(255, 255, 255)); 52 53 if (NearestBlack != RGB(0, 0, 0) || NearestWhite != RGB(255, 255, 255)) 54 return TRUE; 55 56 return FALSE; 57 } 58 59 void GetDisplayAdapterFromDevice(IN OUT LPDIRECT3D9_DISPLAYADAPTER pDisplayAdapters, IN DWORD AdapterIndex, IN LPD3D9_DEVICEDATA pDeviceData) 60 { 61 LPDIRECT3D9_DISPLAYADAPTER pDisplayAdapter = &pDisplayAdapters[AdapterIndex]; 62 DWORD FormatOpIndex; 63 DWORD AdapterGroupId; 64 DWORD NumAdaptersInGroup; 65 DWORD Index; 66 67 memcpy(&pDisplayAdapter->DriverCaps, &pDeviceData->DriverCaps, sizeof(D3D9_DRIVERCAPS)); 68 69 for (FormatOpIndex = 0; FormatOpIndex < pDeviceData->DriverCaps.NumSupportedFormatOps; FormatOpIndex++) 70 { 71 LPDDSURFACEDESC pSurfaceDesc = &pDeviceData->DriverCaps.pSupportedFormatOps[FormatOpIndex]; 72 D3DFORMAT Format = pSurfaceDesc->ddpfPixelFormat.dwFourCC; 73 74 if ((pSurfaceDesc->ddpfPixelFormat.dwOperations & D3DFORMAT_OP_DISPLAYMODE) != 0 && 75 (Format == D3DFMT_R5G6B5 || Format == D3DFMT_X1R5G5B5)) 76 { 77 pDisplayAdapter->Supported16bitFormat = Format; 78 break; 79 } 80 } 81 82 NumAdaptersInGroup = 0; 83 AdapterGroupId = pDeviceData->DriverCaps.ulUniqueAdapterGroupId; 84 for (Index = 0; Index < AdapterIndex; Index++) 85 { 86 if (AdapterGroupId == pDisplayAdapters[Index].DriverCaps.ulUniqueAdapterGroupId) 87 ++NumAdaptersInGroup; 88 } 89 pDisplayAdapter->MasterAdapterIndex = AdapterIndex; 90 pDisplayAdapter->NumAdaptersInGroup = NumAdaptersInGroup + 1; /* Add self */ 91 pDisplayAdapter->AdapterIndexInGroup = NumAdaptersInGroup; 92 93 CreateDisplayModeList( 94 pDisplayAdapter->szDeviceName, 95 NULL, 96 &pDisplayAdapter->NumSupportedD3DFormats, 97 pDisplayAdapter->Supported16bitFormat, 98 pDeviceData->pUnknown6BC 99 ); 100 101 if (pDisplayAdapter->NumSupportedD3DFormats > 0) 102 { 103 pDisplayAdapter->pSupportedD3DFormats = HeapAlloc(GetProcessHeap(), 0, pDisplayAdapter->NumSupportedD3DFormats * sizeof(D3DDISPLAYMODE)); 104 105 CreateDisplayModeList( 106 pDisplayAdapter->szDeviceName, 107 pDisplayAdapter->pSupportedD3DFormats, 108 &pDisplayAdapter->NumSupportedD3DFormats, 109 pDisplayAdapter->Supported16bitFormat, 110 pDeviceData->pUnknown6BC 111 ); 112 } 113 } 114 115 BOOL CreateD3D9DeviceData(IN LPDIRECT3D9_DISPLAYADAPTER pDisplayAdapter, IN LPD3D9_DEVICEDATA pDeviceData) 116 { 117 HDC hDC; 118 119 /* Test DC creation for the display device */ 120 if (NULL == (hDC = CreateDCA(NULL, pDisplayAdapter->szDeviceName, NULL, NULL))) 121 { 122 DPRINT1("Could not create dc for display adapter: %s", pDisplayAdapter->szDeviceName); 123 return FALSE; 124 } 125 126 pDeviceData->hDC = hDC; 127 pDeviceData->DisplayGuid = pDisplayAdapter->DisplayGuid; 128 pDeviceData->DeviceType = D3DDEVTYPE_HAL; 129 lstrcpynA(pDeviceData->szDeviceName, pDisplayAdapter->szDeviceName, CCHDEVICENAME); 130 pDeviceData->szDeviceName[CCHDEVICENAME-1] = '\0'; 131 132 if (pDisplayAdapter->bInUseFlag) 133 { 134 pDeviceData->D3D9Callbacks.DeviceType = D3DDEVTYPE_HAL; 135 } 136 else if (IsGDIDriver(hDC)) 137 { 138 pDeviceData->D3D9Callbacks.DeviceType = D3DDEVTYPE_REF; 139 } 140 141 if (FALSE == GetDeviceData(pDeviceData)) 142 { 143 DPRINT1("Could not get device data for display adapter: %s", pDisplayAdapter->szDeviceName); 144 return FALSE; 145 } 146 147 return TRUE; 148 } 149 150 VOID DestroyD3D9DeviceData(IN LPD3D9_DEVICEDATA pDeviceData) 151 { 152 DeleteDC(pDeviceData->hDC); 153 HeapFree(GetProcessHeap(), 0, pDeviceData->pUnknown6BC); 154 } 155 156 static BOOL GetDirect3D9AdapterInfo(IN OUT LPDIRECT3D9_DISPLAYADAPTER pDisplayAdapters, IN DWORD AdapterIndex) 157 { 158 LPD3D9_DEVICEDATA pDeviceData; 159 160 pDeviceData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(D3D9_DEVICEDATA)); 161 if (NULL == pDeviceData) 162 { 163 DPRINT1("Out of memory, could not initialize Direct3D adapter"); 164 return FALSE; 165 } 166 167 if (FALSE == CreateD3D9DeviceData(&pDisplayAdapters[AdapterIndex], pDeviceData)) 168 { 169 DPRINT1("Could not create device data for adapter: %d", AdapterIndex); 170 return FALSE; 171 } 172 173 GetDisplayAdapterFromDevice(pDisplayAdapters, AdapterIndex, pDeviceData); 174 175 DestroyD3D9DeviceData(pDeviceData); 176 HeapFree(GetProcessHeap(), 0, pDeviceData); 177 178 return TRUE; 179 } 180 181 static BOOL GetDisplayDeviceInfo(IN OUT LPDIRECT3D9_INT pDirect3D9) 182 { 183 DISPLAY_DEVICEA DisplayDevice; 184 DWORD AdapterIndex; 185 186 memset(&DisplayDevice, 0, sizeof(DISPLAY_DEVICEA)); 187 DisplayDevice.cb = sizeof(DISPLAY_DEVICEA); 188 189 pDirect3D9->NumDisplayAdapters = 0; 190 D3D9_PrimaryDeviceName[0] = '\0'; 191 192 AdapterIndex = 0; 193 while ((EnumDisplayDevicesA(NULL, AdapterIndex, &DisplayDevice, 0) != FALSE) && 194 pDirect3D9->NumDisplayAdapters < D3D9_INT_MAX_NUM_ADAPTERS) 195 { 196 if ((DisplayDevice.StateFlags & (DISPLAY_DEVICE_DISCONNECT | DISPLAY_DEVICE_MIRRORING_DRIVER)) == 0 && 197 (DisplayDevice.StateFlags & (DISPLAY_DEVICE_PRIMARY_DEVICE | DISPLAY_DEVICE_ATTACHED_TO_DESKTOP)) != 0) 198 { 199 SetAdapterInfo(&pDirect3D9->DisplayAdapters[pDirect3D9->NumDisplayAdapters], &DisplayDevice); 200 201 if (pDirect3D9->NumDisplayAdapters == 0) 202 lstrcpynA(D3D9_PrimaryDeviceName, DisplayDevice.DeviceName, sizeof(D3D9_PrimaryDeviceName)); 203 204 ++pDirect3D9->NumDisplayAdapters; 205 break; 206 } 207 208 ++AdapterIndex; 209 } 210 211 AdapterIndex = 0; 212 while ((EnumDisplayDevicesA(NULL, AdapterIndex, &DisplayDevice, 0) != FALSE) && 213 pDirect3D9->NumDisplayAdapters < D3D9_INT_MAX_NUM_ADAPTERS) 214 { 215 if ((DisplayDevice.StateFlags & DISPLAY_DEVICE_ATTACHED_TO_DESKTOP) != 0 && 216 (DisplayDevice.StateFlags & (DISPLAY_DEVICE_MIRRORING_DRIVER | DISPLAY_DEVICE_PRIMARY_DEVICE)) == 0) 217 { 218 SetAdapterInfo(&pDirect3D9->DisplayAdapters[pDirect3D9->NumDisplayAdapters], &DisplayDevice); 219 ++pDirect3D9->NumDisplayAdapters; 220 } 221 222 ++AdapterIndex; 223 } 224 225 /* Check if minimum DirectDraw is supported */ 226 if (IsDirectDrawSupported() == FALSE) 227 return FALSE; 228 229 for (AdapterIndex = 0; AdapterIndex < pDirect3D9->NumDisplayAdapters; AdapterIndex++) 230 { 231 GetDirect3D9AdapterInfo(pDirect3D9->DisplayAdapters, AdapterIndex); 232 } 233 234 return TRUE; 235 } 236 237 HRESULT CreateD3D9(OUT LPDIRECT3D9 *ppDirect3D9, UINT SDKVersion) 238 { 239 LPDIRECT3D9_INT pDirect3D9; 240 241 if (ppDirect3D9 == 0) 242 return DDERR_INVALIDPARAMS; 243 244 if (AlignedAlloc((LPVOID *)&pDirect3D9, sizeof(DIRECT3D9_INT)) != S_OK) 245 return DDERR_OUTOFMEMORY; 246 247 if (pDirect3D9 == 0) 248 return DDERR_OUTOFMEMORY; 249 250 pDirect3D9->lpVtbl = &Direct3D9_Vtbl; 251 pDirect3D9->dwProcessId = GetCurrentThreadId(); 252 pDirect3D9->lRefCnt = 1; 253 254 pDirect3D9->SDKVersion = SDKVersion; 255 256 pDirect3D9->lpInt = pDirect3D9; 257 pDirect3D9->unknown000007 = 1; 258 259 InitializeCriticalSection(&pDirect3D9->d3d9_cs); 260 261 if (FALSE == GetDisplayDeviceInfo(pDirect3D9)) 262 { 263 DPRINT1("Could not create Direct3D9 object"); 264 AlignedFree(pDirect3D9); 265 return DDERR_GENERIC; 266 } 267 268 *ppDirect3D9 = (LPDIRECT3D9)&pDirect3D9->lpVtbl; 269 270 return D3D_OK; 271 } 272 273