VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/VBoxTray/VBoxDispIf.cpp@ 32687

Last change on this file since 32687 was 32622, checked in by vboxsync, 14 years ago

wddm: VBOXWDDM->VBOX_WITH_WDDM

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.9 KB
Line 
1/** @file
2 * VBoxTray - Display Settings Interface abstraction for XPDM & WDDM
3 */
4
5/*
6 * Copyright (C) 2006-2010 Oracle Corporation
7 *
8 * This file is part of VirtualBox Open Source Edition (OSE), as
9 * available from http://www.virtualbox.org. This file is free software;
10 * you can redistribute it and/or modify it under the terms of the GNU
11 * General Public License (GPL) as published by the Free Software
12 * Foundation, in version 2 as it comes in the "COPYING" file of the
13 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
14 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
15 */
16
17#include "VBoxDispIf.h"
18
19#include <iprt/log.h>
20#include <iprt/err.h>
21#include <iprt/assert.h>
22
23/* display driver interface abstraction for XPDM & WDDM
24 * with WDDM we can not use ExtEscape to communicate with our driver
25 * because we do not have XPDM display driver any more, i.e. escape requests are handled by cdd
26 * that knows nothing about us */
27DWORD VBoxDispIfInit(PVBOXDISPIF pIf)
28{
29 pIf->enmMode = VBOXDISPIF_MODE_XPDM;
30 return NO_ERROR;
31}
32
33DWORD VBoxDispIfTerm(PVBOXDISPIF pIf)
34{
35 pIf->enmMode = VBOXDISPIF_MODE_UNKNOWN;
36 return NO_ERROR;
37}
38
39static DWORD vboxDispIfEscapeXPDM(PCVBOXDISPIF pIf, PVBOXDISPIFESCAPE pEscape, int cbData)
40{
41 HDC hdc = GetDC(HWND_DESKTOP);
42 VOID *pvData = cbData ? VBOXDISPIFESCAPE_DATA(pEscape, VOID) : NULL;
43 int iRet = ExtEscape(hdc, pEscape->escapeCode, cbData, (LPCSTR)pvData, 0, NULL);
44 ReleaseDC(HWND_DESKTOP, hdc);
45 if (iRet > 0)
46 return VINF_SUCCESS;
47 else if (iRet == 0)
48 return ERROR_NOT_SUPPORTED;
49 /* else */
50 return ERROR_GEN_FAILURE;
51}
52
53#ifdef VBOX_WITH_WDDM
54static DWORD vboxDispIfSwitchToWDDM(PVBOXDISPIF pIf)
55{
56 DWORD err = NO_ERROR;
57 OSVERSIONINFO OSinfo;
58 OSinfo.dwOSVersionInfoSize = sizeof (OSinfo);
59 GetVersionEx (&OSinfo);
60 if (OSinfo.dwMajorVersion >= 6)
61 {
62 /* this is vista and up */
63 Log((__FUNCTION__": this is vista and up\n"));
64 HMODULE hGdi32 = GetModuleHandle("gdi32");
65 if (hGdi32 != NULL)
66 {
67 bool bSupported = true;
68 pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromHdc = (PFND3DKMT_OPENADAPTERFROMHDC)GetProcAddress(hGdi32, "D3DKMTOpenAdapterFromHdc");
69 Log((__FUNCTION__"pfnD3DKMTOpenAdapterFromHdc = %p\n", pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromHdc));
70 bSupported &= !!(pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromHdc);
71
72 pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromGdiDisplayName = (PFND3DKMT_OPENADAPTERFROMGDIDISPLAYNAME)GetProcAddress(hGdi32, "D3DKMTOpenAdapterFromGdiDisplayName");
73 Log((__FUNCTION__": pfnD3DKMTOpenAdapterFromGdiDisplayName = %p\n", pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromGdiDisplayName));
74 bSupported &= !!(pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromGdiDisplayName);
75
76 pIf->modeData.wddm.pfnD3DKMTCloseAdapter = (PFND3DKMT_CLOSEADAPTER)GetProcAddress(hGdi32, "D3DKMTCloseAdapter");
77 Log((__FUNCTION__": pfnD3DKMTCloseAdapter = %p\n", pIf->modeData.wddm.pfnD3DKMTCloseAdapter));
78 bSupported &= !!(pIf->modeData.wddm.pfnD3DKMTCloseAdapter);
79
80 pIf->modeData.wddm.pfnD3DKMTEscape = (PFND3DKMT_ESCAPE)GetProcAddress(hGdi32, "D3DKMTEscape");
81 Log((__FUNCTION__": pfnD3DKMTEscape = %p\n", pIf->modeData.wddm.pfnD3DKMTEscape));
82 bSupported &= !!(pIf->modeData.wddm.pfnD3DKMTCloseAdapter);
83
84 pIf->modeData.wddm.pfnD3DKMTInvalidateActiveVidPn = (PFND3DKMT_INVALIDATEACTIVEVIDPN)GetProcAddress(hGdi32, "D3DKMTInvalidateActiveVidPn");
85 Log((__FUNCTION__": pfnD3DKMTInvalidateActiveVidPn = %p\n", pIf->modeData.wddm.pfnD3DKMTInvalidateActiveVidPn));
86 bSupported &= !!(pIf->modeData.wddm.pfnD3DKMTInvalidateActiveVidPn);
87
88 if (!bSupported)
89 {
90 Log((__FUNCTION__": one of pfnD3DKMT function pointers failed to initialize\n"));
91 err = ERROR_NOT_SUPPORTED;
92 }
93 }
94 else
95 {
96 Log((__FUNCTION__": GetModuleHandle(gdi32) failed, err(%d)\n", GetLastError()));
97 err = ERROR_NOT_SUPPORTED;
98 }
99 }
100 else
101 {
102 Log((__FUNCTION__": can not switch to VBOXDISPIF_MODE_WDDM, because os is not Vista or upper\n"));
103 err = ERROR_NOT_SUPPORTED;
104 }
105
106 return err;
107}
108
109typedef DECLCALLBACK(BOOLEAN) FNVBOXDISPIFWDDM_ADAPTEROP(PCVBOXDISPIF pIf, D3DKMT_HANDLE hAdapter, LPCWSTR pDevName, PVOID pContext);
110typedef FNVBOXDISPIFWDDM_ADAPTEROP *PFNVBOXDISPIFWDDM_ADAPTEROP;
111static DWORD vboxDispIfWDDMAdapterOp(PCVBOXDISPIF pIf, LPCWSTR pDevName, PFNVBOXDISPIFWDDM_ADAPTEROP pfnOp, PVOID pContext)
112{
113 D3DKMT_OPENADAPTERFROMGDIDISPLAYNAME OpenAdapterData = {0};
114 wcsncpy(OpenAdapterData.DeviceName, pDevName, RT_ELEMENTS(OpenAdapterData.DeviceName) - 1 /* the last one is always \0 */);
115 DWORD err = NO_ERROR;
116 NTSTATUS Status = pIf->modeData.wddm.pfnD3DKMTOpenAdapterFromGdiDisplayName(&OpenAdapterData);
117 if (!Status)
118 {
119 BOOLEAN bCloseAdapter = pfnOp(pIf, OpenAdapterData.hAdapter, OpenAdapterData.DeviceName, pContext);
120
121 if (bCloseAdapter)
122 {
123 D3DKMT_CLOSEADAPTER ClosaAdapterData = {0};
124 ClosaAdapterData.hAdapter = OpenAdapterData.hAdapter;
125 Status = pIf->modeData.wddm.pfnD3DKMTCloseAdapter(&ClosaAdapterData);
126 if (Status)
127 {
128 Log((__FUNCTION__": pfnD3DKMTCloseAdapter failed, Status (0x%x)\n", Status));
129 /* ignore */
130 Status = 0;
131 }
132 }
133 }
134 else
135 {
136 Log((__FUNCTION__": pfnD3DKMTOpenAdapterFromGdiDisplayName failed, Status (0x%x)\n", Status));
137 err = ERROR_GEN_FAILURE;
138 }
139
140 return err;
141}
142
143typedef struct
144{
145 NTSTATUS Status;
146 PVBOXDISPIFESCAPE pEscape;
147 int cbData;
148} VBOXDISPIFWDDM_ESCAPEOP_CONTEXT, *PVBOXDISPIFWDDM_ESCAPEOP_CONTEXT;
149
150DECLCALLBACK(BOOLEAN) vboxDispIfEscapeWDDMOp(PCVBOXDISPIF pIf, D3DKMT_HANDLE hAdapter, LPCWSTR pDevName, PVOID pContext)
151{
152 PVBOXDISPIFWDDM_ESCAPEOP_CONTEXT pCtx = (PVBOXDISPIFWDDM_ESCAPEOP_CONTEXT)pContext;
153
154 D3DKMT_ESCAPE EscapeData = {0};
155 EscapeData.hAdapter = hAdapter;
156 //EscapeData.hDevice = NULL;
157 EscapeData.Type = D3DKMT_ESCAPE_DRIVERPRIVATE;
158 EscapeData.Flags.HardwareAccess = 1;
159 EscapeData.pPrivateDriverData = pCtx->pEscape;
160 EscapeData.PrivateDriverDataSize = VBOXDISPIFESCAPE_SIZE(pCtx->cbData);
161 //EscapeData.hContext = NULL;
162
163 pCtx->Status = pIf->modeData.wddm.pfnD3DKMTEscape(&EscapeData);
164
165 return TRUE;
166}
167
168static DWORD vboxDispIfEscapeWDDM(PCVBOXDISPIF pIf, PVBOXDISPIFESCAPE pEscape, int cbData)
169{
170 VBOXDISPIFWDDM_ESCAPEOP_CONTEXT Ctx = {0};
171 Ctx.pEscape = pEscape;
172 Ctx.cbData = cbData;
173 DWORD err = vboxDispIfWDDMAdapterOp(pIf, L"\\\\.\\DISPLAY1", vboxDispIfEscapeWDDMOp, &Ctx);
174 if (err == NO_ERROR)
175 {
176 if (!Ctx.Status)
177 err = NO_ERROR;
178 else
179 {
180 if (Ctx.Status == 0xC00000BBL) /* not supported */
181 err = ERROR_NOT_SUPPORTED;
182 else
183 err = ERROR_GEN_FAILURE;
184 Log((__FUNCTION__": pfnD3DKMTEscape failed, Status (0x%x)\n", Ctx.Status));
185 }
186 }
187 else
188 Log((__FUNCTION__": vboxDispIfWDDMAdapterOp failed, err (%d)\n", err));
189
190 return err;
191}
192
193typedef struct
194{
195 NTSTATUS Status;
196 VBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO Info;
197} VBOXDISPIFWDDM_RESIZEOP_CONTEXT, *PVBOXDISPIFWDDM_RESIZEOP_CONTEXT;
198
199DECLCALLBACK(BOOLEAN) vboxDispIfResizeWDDMOp(PCVBOXDISPIF pIf, D3DKMT_HANDLE hAdapter, LPCWSTR pDevName, PVOID pContext)
200{
201 PVBOXDISPIFWDDM_RESIZEOP_CONTEXT pCtx = (PVBOXDISPIFWDDM_RESIZEOP_CONTEXT)pContext;
202
203 D3DKMT_INVALIDATEACTIVEVIDPN IAVidPnData = {0};
204 uint32_t cbData = VBOXWDDM_RECOMMENDVIDPN_SIZE(1);
205 PVBOXWDDM_RECOMMENDVIDPN pData = (PVBOXWDDM_RECOMMENDVIDPN)malloc(cbData);
206 if (pData)
207 {
208 memset(pData, 0, cbData);
209 pData->cScreenInfos = 1;
210 memcpy(&pData->aScreenInfos[0], &pCtx->Info, sizeof (VBOXWDDM_RECOMMENDVIDPN_SCREEN_INFO));
211
212 IAVidPnData.hAdapter = hAdapter;
213 IAVidPnData.pPrivateDriverData = pData;
214 IAVidPnData.PrivateDriverDataSize = cbData;
215
216 pCtx->Status = pIf->modeData.wddm.pfnD3DKMTInvalidateActiveVidPn(&IAVidPnData);
217 if (pCtx->Status)
218 Log((__FUNCTION__": pfnD3DKMTInvalidateActiveVidPn failed, Status (0x%x)\n", pCtx->Status));
219
220 free(pData);
221 }
222 else
223 {
224 Log((__FUNCTION__": malloc failed\n"));
225 pCtx->Status = -1;
226 }
227
228 return TRUE;
229}
230
231static DWORD vboxDispIfResizeWDDM(PCVBOXDISPIF const pIf, ULONG Id, DWORD Width, DWORD Height, DWORD BitsPerPixel)
232{
233 VBOXDISPIFWDDM_RESIZEOP_CONTEXT Ctx = {0};
234 Ctx.Info.Id = Id;
235 Ctx.Info.Width = Width;
236 Ctx.Info.Height = Height;
237 Ctx.Info.BitsPerPixel = BitsPerPixel;
238 DWORD err = vboxDispIfWDDMAdapterOp(pIf, L"\\\\.\\DISPLAY1", vboxDispIfResizeWDDMOp, &Ctx);
239 if (err == NO_ERROR)
240 {
241 if (!Ctx.Status)
242 err = NO_ERROR;
243 else
244 {
245 if (Ctx.Status == 0xC00000BBL) /* not supported */
246 err = ERROR_NOT_SUPPORTED;
247 else
248 err = ERROR_GEN_FAILURE;
249 Log((__FUNCTION__": vboxDispIfResizeWDDMOp failed, Status (0x%x)\n", Ctx.Status));
250 }
251 }
252 else
253 Log((__FUNCTION__": vboxDispIfWDDMAdapterOp failed, err (%d)\n", err));
254
255 return err;
256}
257#endif
258
259DWORD VBoxDispIfEscape(PCVBOXDISPIF pIf, PVBOXDISPIFESCAPE pEscape, int cbData)
260{
261 switch (pIf->enmMode)
262 {
263 case VBOXDISPIF_MODE_XPDM_NT4:
264 case VBOXDISPIF_MODE_XPDM:
265 return vboxDispIfEscapeXPDM(pIf, pEscape, cbData);
266#ifdef VBOX_WITH_WDDM
267 case VBOXDISPIF_MODE_WDDM:
268 return vboxDispIfEscapeWDDM(pIf, pEscape, cbData);
269#endif
270 default:
271 Log((__FUNCTION__": unknown mode (%d)\n", pIf->enmMode));
272 return ERROR_INVALID_PARAMETER;
273 }
274}
275
276static DWORD vboxDispIfResizeXPDM(PCVBOXDISPIF const pIf, ULONG Id, DWORD Width, DWORD Height, DWORD BitsPerPixel)
277{
278 return ERROR_NOT_SUPPORTED;
279}
280
281DWORD VBoxDispIfResize(PCVBOXDISPIF const pIf, ULONG Id, DWORD Width, DWORD Height, DWORD BitsPerPixel)
282{
283 switch (pIf->enmMode)
284 {
285 case VBOXDISPIF_MODE_XPDM_NT4:
286 return ERROR_NOT_SUPPORTED;
287 case VBOXDISPIF_MODE_XPDM:
288 return vboxDispIfResizeXPDM(pIf, Id, Width, Height, BitsPerPixel);
289#ifdef VBOX_WITH_WDDM
290 case VBOXDISPIF_MODE_WDDM:
291 return vboxDispIfResizeWDDM(pIf, Id, Width, Height, BitsPerPixel);
292#endif
293 default:
294 Log((__FUNCTION__": unknown mode (%d)\n", pIf->enmMode));
295 return ERROR_INVALID_PARAMETER;
296 }
297}
298
299static DWORD vboxDispIfSwitchToXPDM_NT4(PVBOXDISPIF pIf)
300{
301 return NO_ERROR;
302}
303
304static DWORD vboxDispIfSwitchToXPDM(PVBOXDISPIF pIf)
305{
306 DWORD err = NO_ERROR;
307 AssertBreakpoint();
308 OSVERSIONINFO OSinfo;
309 OSinfo.dwOSVersionInfoSize = sizeof (OSinfo);
310 GetVersionEx (&OSinfo);
311 if (OSinfo.dwMajorVersion >= 5)
312 {
313 HMODULE hUser = GetModuleHandle("USER32");
314 if (NULL != hUser)
315 {
316 bool bSupported = true;
317 *(uintptr_t *)&pIf->modeData.xpdm.pfnChangeDisplaySettingsEx = (uintptr_t)GetProcAddress(hUser, "ChangeDisplaySettingsExA");
318 Log((__FUNCTION__": pfnChangeDisplaySettingsEx = %p\n", pIf->modeData.xpdm.pfnChangeDisplaySettingsEx));
319 bSupported &= !!(pIf->modeData.xpdm.pfnChangeDisplaySettingsEx);
320
321 if (!bSupported)
322 {
323 Log((__FUNCTION__": pfnChangeDisplaySettingsEx function pointer failed to initialize\n"));
324 err = ERROR_NOT_SUPPORTED;
325 }
326 }
327 else
328 {
329 Log((__FUNCTION__": failed to get USER32 handle, err (%d)\n", GetLastError()));
330 err = ERROR_NOT_SUPPORTED;
331 }
332 }
333 else
334 {
335 Log((__FUNCTION__": can not switch to VBOXDISPIF_MODE_XPDM, because os is not >= w2k\n"));
336 err = ERROR_NOT_SUPPORTED;
337 }
338
339 return err;
340}
341
342DWORD VBoxDispIfSwitchMode(PVBOXDISPIF pIf, VBOXDISPIF_MODE enmMode, VBOXDISPIF_MODE *penmOldMode)
343{
344 /* @todo: may need to addd synchronization in case we want to change modes dynamically
345 * i.e. currently the mode is supposed to be initialized once on service initialization */
346 if (penmOldMode)
347 *penmOldMode = pIf->enmMode;
348
349 if (enmMode == pIf->enmMode)
350 return VINF_ALREADY_INITIALIZED;
351
352 DWORD err = NO_ERROR;
353 switch (enmMode)
354 {
355 case VBOXDISPIF_MODE_XPDM_NT4:
356 Log((__FUNCTION__": request to switch to VBOXDISPIF_MODE_XPDM_NT4\n"));
357 err = vboxDispIfSwitchToXPDM_NT4(pIf);
358 if (err == NO_ERROR)
359 {
360 Log((__FUNCTION__": successfully switched to XPDM_NT4 mode\n"));
361 pIf->enmMode = VBOXDISPIF_MODE_XPDM_NT4;
362 }
363 else
364 Log((__FUNCTION__": failed to switch to XPDM_NT4 mode, err (%d)\n", err));
365 break;
366 case VBOXDISPIF_MODE_XPDM:
367 Log((__FUNCTION__": request to switch to VBOXDISPIF_MODE_XPDM\n"));
368 err = vboxDispIfSwitchToXPDM(pIf);
369 if (err == NO_ERROR)
370 {
371 Log((__FUNCTION__": successfully switched to XPDM mode\n"));
372 pIf->enmMode = VBOXDISPIF_MODE_XPDM;
373 }
374 else
375 Log((__FUNCTION__": failed to switch to XPDM mode, err (%d)\n", err));
376 break;
377#ifdef VBOX_WITH_WDDM
378 case VBOXDISPIF_MODE_WDDM:
379 {
380 Log((__FUNCTION__": request to switch to VBOXDISPIF_MODE_WDDM\n"));
381 err = vboxDispIfSwitchToWDDM(pIf);
382 if (err == NO_ERROR)
383 {
384 Log((__FUNCTION__": successfully switched to WDDM mode\n"));
385 pIf->enmMode = VBOXDISPIF_MODE_WDDM;
386 }
387 else
388 Log((__FUNCTION__": failed to switch to WDDM mode, err (%d)\n", err));
389 break;
390 }
391#endif
392 default:
393 err = ERROR_INVALID_PARAMETER;
394 break;
395 }
396 return err;
397}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette