xref: /reactos/dll/directx/d3d9/d3d9_create.c (revision 9393fc32)
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 
IsDirectDrawSupported()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 
SetAdapterInfo(IN OUT LPDIRECT3D9_DISPLAYADAPTER pDisplayAdapter,IN LPDISPLAY_DEVICEA pDisplayDevice)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 
IsGDIDriver(HDC hDC)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 
GetDisplayAdapterFromDevice(IN OUT LPDIRECT3D9_DISPLAYADAPTER pDisplayAdapters,IN DWORD AdapterIndex,IN LPD3D9_DEVICEDATA pDeviceData)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 
CreateD3D9DeviceData(IN LPDIRECT3D9_DISPLAYADAPTER pDisplayAdapter,IN LPD3D9_DEVICEDATA pDeviceData)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 
DestroyD3D9DeviceData(IN LPD3D9_DEVICEDATA pDeviceData)150 VOID DestroyD3D9DeviceData(IN LPD3D9_DEVICEDATA pDeviceData)
151 {
152     DeleteDC(pDeviceData->hDC);
153     HeapFree(GetProcessHeap(), 0, pDeviceData->pUnknown6BC);
154 }
155 
GetDirect3D9AdapterInfo(IN OUT LPDIRECT3D9_DISPLAYADAPTER pDisplayAdapters,IN DWORD AdapterIndex)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 
GetDisplayDeviceInfo(IN OUT LPDIRECT3D9_INT pDirect3D9)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 
CreateD3D9(OUT LPDIRECT3D9 * ppDirect3D9,UINT SDKVersion)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