VirtualBox

source: vbox/trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPWddm.cpp@ 89361

Last change on this file since 89361 was 86632, checked in by vboxsync, 4 years ago

3D: Invoke RTR0Term as a final step of VBoxWddm|DxgkDdiUnload

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 186.1 KB
Line 
1/* $Id: VBoxMPWddm.cpp 86632 2020-10-19 19:38:37Z vboxsync $ */
2/** @file
3 * VBox WDDM Miniport driver
4 */
5
6/*
7 * Copyright (C) 2011-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include "VBoxMPWddm.h"
19#include "common/VBoxMPCommon.h"
20#include "common/VBoxMPHGSMI.h"
21#ifdef VBOX_WITH_VIDEOHWACCEL
22# include "VBoxMPVhwa.h"
23#endif
24#include "VBoxMPVidPn.h"
25#include "VBoxMPLegacy.h"
26
27#include <iprt/alloc.h>
28#include <iprt/asm.h>
29#include <iprt/param.h>
30#include <iprt/initterm.h>
31#include <iprt/utf16.h>
32
33#include <VBox/VBoxGuestLib.h>
34#include <VBox/VMMDev.h> /* for VMMDevVideoSetVisibleRegion */
35#include <VBoxVideo.h>
36#include <wingdi.h> /* needed for RGNDATA definition */
37#include <VBoxDisplay.h> /* this is from Additions/WINNT/include/ to include escape codes */
38#include <VBoxVideoVBE.h>
39#include <VBox/Version.h>
40
41#ifdef VBOX_WITH_MESA3D
42#include "gallium/VBoxMPGaWddm.h"
43#endif
44
45#ifdef DEBUG
46DWORD g_VBoxLogUm = VBOXWDDM_CFG_LOG_UM_BACKDOOR;
47#else
48DWORD g_VBoxLogUm = 0;
49#endif
50DWORD g_RefreshRate = 0;
51
52/* Whether the driver is display-only (no 3D) for Windows 8 or newer guests. */
53DWORD g_VBoxDisplayOnly = 0;
54
55#define VBOXWDDM_MEMTAG 'MDBV'
56PVOID vboxWddmMemAlloc(IN SIZE_T cbSize)
57{
58 POOL_TYPE enmPoolType = (VBoxQueryWinVersion(NULL) >= WINVERSION_8) ? NonPagedPoolNx : NonPagedPool;
59 return ExAllocatePoolWithTag(enmPoolType, cbSize, VBOXWDDM_MEMTAG);
60}
61
62PVOID vboxWddmMemAllocZero(IN SIZE_T cbSize)
63{
64 PVOID pvMem = vboxWddmMemAlloc(cbSize);
65 if (pvMem)
66 memset(pvMem, 0, cbSize);
67 return pvMem;
68}
69
70
71VOID vboxWddmMemFree(PVOID pvMem)
72{
73 ExFreePool(pvMem);
74}
75
76DECLINLINE(void) VBoxWddmOaHostIDReleaseLocked(PVBOXWDDM_OPENALLOCATION pOa)
77{
78 Assert(pOa->cHostIDRefs);
79 PVBOXWDDM_ALLOCATION pAllocation = pOa->pAllocation;
80 Assert(pAllocation->AllocData.cHostIDRefs >= pOa->cHostIDRefs);
81 Assert(pAllocation->AllocData.hostID);
82 --pOa->cHostIDRefs;
83 --pAllocation->AllocData.cHostIDRefs;
84 if (!pAllocation->AllocData.cHostIDRefs)
85 pAllocation->AllocData.hostID = 0;
86}
87
88DECLINLINE(void) VBoxWddmOaHostIDCheckReleaseLocked(PVBOXWDDM_OPENALLOCATION pOa)
89{
90 if (pOa->cHostIDRefs)
91 VBoxWddmOaHostIDReleaseLocked(pOa);
92}
93
94DECLINLINE(void) VBoxWddmOaRelease(PVBOXWDDM_OPENALLOCATION pOa)
95{
96 PVBOXWDDM_ALLOCATION pAllocation = pOa->pAllocation;
97 KIRQL OldIrql;
98 KeAcquireSpinLock(&pAllocation->OpenLock, &OldIrql);
99 Assert(pAllocation->cOpens);
100 VBoxWddmOaHostIDCheckReleaseLocked(pOa);
101 --pAllocation->cOpens;
102 uint32_t cOpens = --pOa->cOpens;
103 Assert(cOpens < UINT32_MAX/2);
104 if (!cOpens)
105 {
106 RemoveEntryList(&pOa->ListEntry);
107 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
108 vboxWddmMemFree(pOa);
109 }
110 else
111 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
112}
113
114DECLINLINE(PVBOXWDDM_OPENALLOCATION) VBoxWddmOaSearchLocked(PVBOXWDDM_DEVICE pDevice, PVBOXWDDM_ALLOCATION pAllocation)
115{
116 for (PLIST_ENTRY pCur = pAllocation->OpenList.Flink; pCur != &pAllocation->OpenList; pCur = pCur->Flink)
117 {
118 PVBOXWDDM_OPENALLOCATION pCurOa = CONTAINING_RECORD(pCur, VBOXWDDM_OPENALLOCATION, ListEntry);
119 if (pCurOa->pDevice == pDevice)
120 {
121 return pCurOa;
122 }
123 }
124 return NULL;
125}
126
127DECLINLINE(PVBOXWDDM_OPENALLOCATION) VBoxWddmOaSearch(PVBOXWDDM_DEVICE pDevice, PVBOXWDDM_ALLOCATION pAllocation)
128{
129 PVBOXWDDM_OPENALLOCATION pOa;
130 KIRQL OldIrql;
131 KeAcquireSpinLock(&pAllocation->OpenLock, &OldIrql);
132 pOa = VBoxWddmOaSearchLocked(pDevice, pAllocation);
133 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
134 return pOa;
135}
136
137DECLINLINE(int) VBoxWddmOaSetHostID(PVBOXWDDM_DEVICE pDevice, PVBOXWDDM_ALLOCATION pAllocation, uint32_t hostID, uint32_t *pHostID)
138{
139 PVBOXWDDM_OPENALLOCATION pOa;
140 KIRQL OldIrql;
141 int rc = VINF_SUCCESS;
142 KeAcquireSpinLock(&pAllocation->OpenLock, &OldIrql);
143 pOa = VBoxWddmOaSearchLocked(pDevice, pAllocation);
144 if (!pOa)
145 {
146 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);;
147 WARN(("no open allocation!"));
148 return VERR_INVALID_STATE;
149 }
150
151 if (hostID)
152 {
153 if (pAllocation->AllocData.hostID == 0)
154 {
155 pAllocation->AllocData.hostID = hostID;
156 }
157 else if (pAllocation->AllocData.hostID != hostID)
158 {
159 WARN(("hostID differ: alloc(%d), trying to assign(%d)", pAllocation->AllocData.hostID, hostID));
160 hostID = pAllocation->AllocData.hostID;
161 rc = VERR_NOT_EQUAL;
162 }
163
164 ++pAllocation->AllocData.cHostIDRefs;
165 ++pOa->cHostIDRefs;
166 }
167 else
168 VBoxWddmOaHostIDCheckReleaseLocked(pOa);
169
170 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
171
172 if (pHostID)
173 *pHostID = hostID;
174
175 return rc;
176}
177
178DECLINLINE(PVBOXWDDM_ALLOCATION) vboxWddmGetAllocationFromHandle(PVBOXMP_DEVEXT pDevExt, D3DKMT_HANDLE hAllocation)
179{
180 DXGKARGCB_GETHANDLEDATA GhData;
181 GhData.hObject = hAllocation;
182 GhData.Type = DXGK_HANDLE_ALLOCATION;
183 GhData.Flags.Value = 0;
184 return (PVBOXWDDM_ALLOCATION)pDevExt->u.primary.DxgkInterface.DxgkCbGetHandleData(&GhData);
185}
186
187int vboxWddmGhDisplayPostInfoScreen(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData, const POINT * pVScreenPos, uint16_t fFlags)
188{
189 VBVAINFOSCREEN RT_UNTRUSTED_VOLATILE_HOST *pScreen =
190 (VBVAINFOSCREEN RT_UNTRUSTED_VOLATILE_HOST *)VBoxHGSMIBufferAlloc(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx,
191 sizeof(VBVAINFOSCREEN),
192 HGSMI_CH_VBVA,
193 VBVA_INFO_SCREEN);
194 if (!pScreen != NULL)
195 {
196 WARN(("VBoxHGSMIBufferAlloc failed"));
197 return VERR_OUT_OF_RESOURCES;
198 }
199
200 int rc = vboxWddmScreenInfoInit(pScreen, pAllocData, pVScreenPos, fFlags);
201 if (RT_SUCCESS(rc))
202 {
203 pScreen->u32StartOffset = 0; //(uint32_t)offVram; /* we pretend the view is located at the start of each framebuffer */
204
205 rc = VBoxHGSMIBufferSubmit(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, pScreen);
206 if (RT_FAILURE(rc))
207 WARN(("VBoxHGSMIBufferSubmit failed %d", rc));
208 }
209 else
210 WARN(("VBoxHGSMIBufferSubmit failed %d", rc));
211
212 VBoxHGSMIBufferFree(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, pScreen);
213
214 return rc;
215}
216
217int vboxWddmGhDisplayPostInfoView(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData)
218{
219 VBOXVIDEOOFFSET offVram = vboxWddmAddrFramOffset(&pAllocData->Addr);
220 if (offVram == VBOXVIDEOOFFSET_VOID)
221 {
222 WARN(("offVram == VBOXVIDEOOFFSET_VOID"));
223 return VERR_INVALID_PARAMETER;
224 }
225
226 /* Issue the screen info command. */
227 VBVAINFOVIEW RT_UNTRUSTED_VOLATILE_HOST *pView =
228 (VBVAINFOVIEW RT_UNTRUSTED_VOLATILE_HOST *)VBoxHGSMIBufferAlloc(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx,
229 sizeof(VBVAINFOVIEW), HGSMI_CH_VBVA, VBVA_INFO_VIEW);
230 if (!pView)
231 {
232 WARN(("VBoxHGSMIBufferAlloc failed"));
233 return VERR_OUT_OF_RESOURCES;
234 }
235 pView->u32ViewIndex = pAllocData->SurfDesc.VidPnSourceId;
236 pView->u32ViewOffset = (uint32_t)offVram; /* we pretend the view is located at the start of each framebuffer */
237 pView->u32ViewSize = vboxWddmVramCpuVisibleSegmentSize(pDevExt)/VBoxCommonFromDeviceExt(pDevExt)->cDisplays;
238 pView->u32MaxScreenSize = pView->u32ViewSize;
239
240 int rc = VBoxHGSMIBufferSubmit (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, pView);
241 if (RT_FAILURE(rc))
242 WARN(("VBoxHGSMIBufferSubmit failed %d", rc));
243
244 VBoxHGSMIBufferFree(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, pView);
245 return rc;
246}
247
248NTSTATUS vboxWddmGhDisplayPostResizeLegacy(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData, const POINT * pVScreenPos, uint16_t fFlags)
249{
250 int rc;
251
252 if (!(fFlags & (VBVA_SCREEN_F_DISABLED | VBVA_SCREEN_F_BLANK2)))
253 {
254 rc = vboxWddmGhDisplayPostInfoView(pDevExt, pAllocData);
255 if (RT_FAILURE(rc))
256 {
257 WARN(("vboxWddmGhDisplayPostInfoView failed %d", rc));
258 return STATUS_UNSUCCESSFUL;
259 }
260 }
261
262 rc = vboxWddmGhDisplayPostInfoScreen(pDevExt, pAllocData, pVScreenPos, fFlags);
263 if (RT_FAILURE(rc))
264 {
265 WARN(("vboxWddmGhDisplayPostInfoScreen failed %d", rc));
266 return STATUS_UNSUCCESSFUL;
267 }
268
269 return STATUS_SUCCESS;
270}
271
272NTSTATUS vboxWddmGhDisplayPostResizeNew(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData, const uint32_t *pTargetMap, const POINT * pVScreenPos, uint16_t fFlags)
273{
274 RT_NOREF(pDevExt, pAllocData, pTargetMap, pVScreenPos, fFlags);
275 AssertFailed(); // Should not be here.
276 return STATUS_UNSUCCESSFUL;
277}
278
279NTSTATUS vboxWddmGhDisplaySetMode(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData)
280{
281 RT_NOREF(pDevExt);
282 VBOXVIDEOOFFSET offVram = vboxWddmAddrFramOffset(&pAllocData->Addr);;
283 if (offVram == VBOXVIDEOOFFSET_VOID)
284 {
285 WARN(("offVram == VBOXVIDEOOFFSET_VOID"));
286 return STATUS_UNSUCCESSFUL;
287 }
288
289 USHORT width = pAllocData->SurfDesc.width;
290 USHORT height = pAllocData->SurfDesc.height;
291 USHORT bpp = pAllocData->SurfDesc.bpp;
292 ULONG cbLine = VBOXWDDM_ROUNDBOUND(((width * bpp) + 7) / 8, 4);
293 ULONG yOffset = (ULONG)offVram / cbLine;
294 ULONG xOffset = (ULONG)offVram % cbLine;
295
296 if (bpp == 4)
297 {
298 xOffset <<= 1;
299 }
300 else
301 {
302 Assert(!(xOffset%((bpp + 7) >> 3)));
303 xOffset /= ((bpp + 7) >> 3);
304 }
305 Assert(xOffset <= 0xffff);
306 Assert(yOffset <= 0xffff);
307
308 VBoxVideoSetModeRegisters(width, height, width, bpp, 0, (uint16_t)xOffset, (uint16_t)yOffset);
309 /** @todo read back from port to check if mode switch was successful */
310
311 return STATUS_SUCCESS;
312}
313
314static uint16_t vboxWddmCalcScreenFlags(PVBOXMP_DEVEXT pDevExt, bool fValidAlloc, bool fPowerOff, bool fDisabled)
315{
316 uint16_t u16Flags;
317
318 if (fValidAlloc)
319 {
320 u16Flags = VBVA_SCREEN_F_ACTIVE;
321 }
322 else
323 {
324 if ( !fDisabled
325 && fPowerOff
326 && RT_BOOL(VBoxCommonFromDeviceExt(pDevExt)->u16SupportedScreenFlags & VBVA_SCREEN_F_BLANK2))
327 {
328 u16Flags = VBVA_SCREEN_F_ACTIVE | VBVA_SCREEN_F_BLANK2;
329 }
330 else
331 {
332 u16Flags = VBVA_SCREEN_F_DISABLED;
333 }
334 }
335
336 return u16Flags;
337}
338
339NTSTATUS vboxWddmGhDisplaySetInfoLegacy(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData, const POINT * pVScreenPos, uint8_t u8CurCyncState, bool fPowerOff, bool fDisabled)
340{
341 RT_NOREF(u8CurCyncState);
342 NTSTATUS Status = STATUS_SUCCESS;
343 bool fValidAlloc = pAllocData->SurfDesc.width > 0 && pAllocData->SurfDesc.height > 0;
344 uint16_t fu16Flags = vboxWddmCalcScreenFlags(pDevExt, fValidAlloc, fPowerOff, fDisabled);
345
346 if (fValidAlloc)
347 {
348 if (pAllocData->SurfDesc.VidPnSourceId == 0)
349 Status = vboxWddmGhDisplaySetMode(pDevExt, pAllocData);
350 }
351
352 if (NT_SUCCESS(Status))
353 {
354 Status = vboxWddmGhDisplayPostResizeLegacy(pDevExt, pAllocData, pVScreenPos,
355 fu16Flags);
356 if (NT_SUCCESS(Status))
357 {
358 return STATUS_SUCCESS;
359 }
360 else
361 WARN(("vboxWddmGhDisplayPostResize failed, Status 0x%x", Status));
362 }
363 else
364 WARN(("vboxWddmGhDisplaySetMode failed, Status 0x%x", Status));
365
366 return Status;
367}
368
369NTSTATUS vboxWddmGhDisplaySetInfoNew(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData, const uint32_t *pTargetMap, const POINT * pVScreenPos, uint8_t u8CurCyncState, bool fPowerOff, bool fDisabled)
370{
371 RT_NOREF(u8CurCyncState);
372 NTSTATUS Status = STATUS_SUCCESS;
373 bool fValidAlloc = pAllocData->SurfDesc.width > 0 && pAllocData->SurfDesc.height > 0;
374 uint16_t fu16Flags = vboxWddmCalcScreenFlags(pDevExt, fValidAlloc, fPowerOff, fDisabled);
375
376 if (fValidAlloc)
377 {
378 if (ASMBitTest(pTargetMap, 0))
379 Status = vboxWddmGhDisplaySetMode(pDevExt, pAllocData);
380 }
381
382 if (NT_SUCCESS(Status))
383 {
384 Status = vboxWddmGhDisplayPostResizeNew(pDevExt, pAllocData, pTargetMap, pVScreenPos, fu16Flags);
385 if (NT_SUCCESS(Status))
386 {
387 return STATUS_SUCCESS;
388 }
389 else
390 WARN(("vboxWddmGhDisplayPostResizeNew failed, Status 0x%x", Status));
391 }
392 else
393 WARN(("vboxWddmGhDisplaySetMode failed, Status 0x%x", Status));
394
395 return Status;
396}
397
398bool vboxWddmGhDisplayCheckSetInfoFromSourceNew(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource, bool fReportTargets)
399{
400 if (pSource->u8SyncState == VBOXWDDM_HGSYNC_F_SYNCED_ALL)
401 {
402 if (!pSource->fTargetsReported && fReportTargets)
403 pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_TOPOLOGY;
404 else
405 return false;
406 }
407
408 if (!pSource->AllocData.Addr.SegmentId && pSource->AllocData.SurfDesc.width)
409 return false;
410
411 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aTargetMap);
412 uint32_t *pTargetMap;
413 if (fReportTargets)
414 pTargetMap = pSource->aTargetMap;
415 else
416 {
417 memset(aTargetMap, 0, sizeof (aTargetMap));
418 pTargetMap = aTargetMap;
419 }
420
421 NTSTATUS Status = vboxWddmGhDisplaySetInfoNew(pDevExt, &pSource->AllocData, pTargetMap, &pSource->VScreenPos, pSource->u8SyncState, RT_BOOL(pSource->bBlankedByPowerOff), false);
422 if (NT_SUCCESS(Status))
423 {
424 if (fReportTargets && (pSource->u8SyncState & VBOXWDDM_HGSYNC_F_CHANGED_LOCATION_ONLY) != VBOXWDDM_HGSYNC_F_CHANGED_LOCATION_ONLY)
425 {
426 VBOXWDDM_TARGET_ITER Iter;
427 VBoxVidPnStTIterInit(pSource, pDevExt->aTargets, VBoxCommonFromDeviceExt(pDevExt)->cDisplays, &Iter);
428
429 for (PVBOXWDDM_TARGET pTarget = VBoxVidPnStTIterNext(&Iter);
430 pTarget;
431 pTarget = VBoxVidPnStTIterNext(&Iter))
432 {
433 pTarget->u8SyncState = VBOXWDDM_HGSYNC_F_SYNCED_ALL;
434 }
435 }
436
437 pSource->u8SyncState = VBOXWDDM_HGSYNC_F_SYNCED_ALL;
438 pSource->fTargetsReported = !!fReportTargets;
439 return true;
440 }
441
442 WARN(("vboxWddmGhDisplaySetInfoNew failed, Status (0x%x)", Status));
443 return false;
444}
445
446bool vboxWddmGhDisplayCheckSetInfoFromSourceLegacy(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource, bool fReportTargets)
447{
448 if (!fReportTargets)
449 return false;
450
451 if (pSource->u8SyncState == VBOXWDDM_HGSYNC_F_SYNCED_ALL)
452 return false;
453
454 if (!pSource->AllocData.Addr.SegmentId)
455 return false;
456
457 VBOXWDDM_TARGET_ITER Iter;
458 VBoxVidPnStTIterInit(pSource, pDevExt->aTargets, VBoxCommonFromDeviceExt(pDevExt)->cDisplays, &Iter);
459 uint8_t u8SyncState = VBOXWDDM_HGSYNC_F_SYNCED_ALL;
460 VBOXWDDM_ALLOC_DATA AllocData = pSource->AllocData;
461
462 for (PVBOXWDDM_TARGET pTarget = VBoxVidPnStTIterNext(&Iter);
463 pTarget;
464 pTarget = VBoxVidPnStTIterNext(&Iter))
465 {
466 AllocData.SurfDesc.VidPnSourceId = pTarget->u32Id;
467 NTSTATUS Status = vboxWddmGhDisplaySetInfoLegacy(pDevExt, &AllocData, &pSource->VScreenPos, pSource->u8SyncState | pTarget->u8SyncState, pTarget->fBlankedByPowerOff, pTarget->fDisabled);
468 if (NT_SUCCESS(Status))
469 pTarget->u8SyncState = VBOXWDDM_HGSYNC_F_SYNCED_ALL;
470 else
471 {
472 WARN(("vboxWddmGhDisplaySetInfoLegacy failed, Status (0x%x)", Status));
473 u8SyncState = 0;
474 }
475 }
476
477 pSource->u8SyncState |= u8SyncState;
478
479 return true;
480}
481
482bool vboxWddmGhDisplayCheckSetInfoFromSourceEx(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource, bool fReportTargets)
483{
484 if (pDevExt->fCmdVbvaEnabled)
485 return vboxWddmGhDisplayCheckSetInfoFromSourceNew(pDevExt, pSource, fReportTargets);
486 return vboxWddmGhDisplayCheckSetInfoFromSourceLegacy(pDevExt, pSource, fReportTargets);
487}
488
489bool vboxWddmGhDisplayCheckSetInfoFromSource(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource)
490{
491 bool fReportTargets = !pDevExt->fDisableTargetUpdate;
492 return vboxWddmGhDisplayCheckSetInfoFromSourceEx(pDevExt, pSource, fReportTargets);
493}
494
495bool vboxWddmGhDisplayCheckSetInfoForDisabledTargetsNew(PVBOXMP_DEVEXT pDevExt)
496{
497 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aTargetMap);
498
499 memset(aTargetMap, 0, sizeof (aTargetMap));
500
501 bool fFound = false;
502 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
503 {
504 VBOXWDDM_TARGET *pTarget = &pDevExt->aTargets[i];
505 Assert(pTarget->u32Id == (unsigned)i);
506 if (pTarget->VidPnSourceId != D3DDDI_ID_UNINITIALIZED)
507 {
508 Assert(pTarget->VidPnSourceId < (D3DDDI_VIDEO_PRESENT_SOURCE_ID)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
509 continue;
510 }
511
512 /* Explicitely disabled targets must not be skipped. */
513 if (pTarget->fBlankedByPowerOff && !pTarget->fDisabled)
514 {
515 LOG(("Skip doing DISABLED request for PowerOff tgt %d", pTarget->u32Id));
516 continue;
517 }
518
519 if (pTarget->u8SyncState != VBOXWDDM_HGSYNC_F_SYNCED_ALL)
520 {
521 ASMBitSet(aTargetMap, i);
522 fFound = true;
523 }
524 }
525
526 if (!fFound)
527 return false;
528
529 POINT VScreenPos = {0};
530 VBOXWDDM_ALLOC_DATA AllocData;
531 VBoxVidPnAllocDataInit(&AllocData, D3DDDI_ID_UNINITIALIZED);
532 NTSTATUS Status = vboxWddmGhDisplaySetInfoNew(pDevExt, &AllocData, aTargetMap, &VScreenPos, 0, false, true);
533 if (!NT_SUCCESS(Status))
534 {
535 WARN(("vboxWddmGhDisplaySetInfoNew failed %#x", Status));
536 return false;
537 }
538
539 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
540 {
541 VBOXWDDM_TARGET *pTarget = &pDevExt->aTargets[i];
542 if (pTarget->VidPnSourceId != D3DDDI_ID_UNINITIALIZED)
543 {
544 Assert(pTarget->VidPnSourceId < (D3DDDI_VIDEO_PRESENT_SOURCE_ID)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
545 continue;
546 }
547
548 pTarget->u8SyncState = VBOXWDDM_HGSYNC_F_SYNCED_ALL;
549 }
550
551 return true;
552}
553
554bool vboxWddmGhDisplayCheckSetInfoForDisabledTargetsLegacy(PVBOXMP_DEVEXT pDevExt)
555{
556 POINT VScreenPos = {0};
557 bool fFound = false;
558 VBOXWDDM_ALLOC_DATA AllocData;
559 VBoxVidPnAllocDataInit(&AllocData, D3DDDI_ID_UNINITIALIZED);
560
561 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
562 {
563 VBOXWDDM_TARGET *pTarget = &pDevExt->aTargets[i];
564 Assert(pTarget->u32Id == (unsigned)i);
565 if (pTarget->VidPnSourceId != D3DDDI_ID_UNINITIALIZED)
566 {
567 Assert(pTarget->VidPnSourceId < (D3DDDI_VIDEO_PRESENT_SOURCE_ID)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
568 continue;
569 }
570
571 if (pTarget->u8SyncState == VBOXWDDM_HGSYNC_F_SYNCED_ALL)
572 continue;
573
574 fFound = true;
575 AllocData.SurfDesc.VidPnSourceId = i;
576 NTSTATUS Status = vboxWddmGhDisplaySetInfoLegacy(pDevExt, &AllocData, &VScreenPos, 0, pTarget->fBlankedByPowerOff, pTarget->fDisabled);
577 if (NT_SUCCESS(Status))
578 pTarget->u8SyncState = VBOXWDDM_HGSYNC_F_SYNCED_ALL;
579 else
580 WARN(("vboxWddmGhDisplaySetInfoLegacy failed, Status (0x%x)", Status));
581 }
582
583 return fFound;
584}
585
586void vboxWddmGhDisplayCheckSetInfoForDisabledTargets(PVBOXMP_DEVEXT pDevExt)
587{
588 if (pDevExt->fCmdVbvaEnabled)
589 vboxWddmGhDisplayCheckSetInfoForDisabledTargetsNew(pDevExt);
590 else
591 vboxWddmGhDisplayCheckSetInfoForDisabledTargetsLegacy(pDevExt);
592}
593
594void vboxWddmGhDisplayCheckSetInfoForDisabledTargetsCheck(PVBOXMP_DEVEXT pDevExt)
595{
596 bool fReportTargets = !pDevExt->fDisableTargetUpdate;
597
598 if (fReportTargets)
599 vboxWddmGhDisplayCheckSetInfoForDisabledTargets(pDevExt);
600}
601
602void vboxWddmGhDisplayCheckSetInfoEx(PVBOXMP_DEVEXT pDevExt, bool fReportTargets)
603{
604 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
605 {
606 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[i];
607 vboxWddmGhDisplayCheckSetInfoFromSourceEx(pDevExt, pSource, fReportTargets);
608 }
609
610 if (fReportTargets)
611 vboxWddmGhDisplayCheckSetInfoForDisabledTargets(pDevExt);
612}
613
614void vboxWddmGhDisplayCheckSetInfo(PVBOXMP_DEVEXT pDevExt)
615{
616 bool fReportTargets = !pDevExt->fDisableTargetUpdate;
617 vboxWddmGhDisplayCheckSetInfoEx(pDevExt, fReportTargets);
618}
619
620PVBOXSHGSMI vboxWddmHgsmiGetHeapFromCmdOffset(PVBOXMP_DEVEXT pDevExt, HGSMIOFFSET offCmd)
621{
622 if (HGSMIAreaContainsOffset(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx.Heap.area, offCmd))
623 return &VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx;
624 return NULL;
625}
626
627NTSTATUS vboxWddmPickResources(PVBOXMP_DEVEXT pDevExt, PDXGK_DEVICE_INFO pDeviceInfo, PVBOXWDDM_HWRESOURCES pHwResources)
628{
629 RT_NOREF(pDevExt);
630 NTSTATUS Status = STATUS_SUCCESS;
631 USHORT DispiId;
632 memset(pHwResources, 0, sizeof (*pHwResources));
633 pHwResources->cbVRAM = VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES;
634
635 VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
636 VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID2);
637 DispiId = VBVO_PORT_READ_U16(VBE_DISPI_IOPORT_DATA);
638 if (DispiId == VBE_DISPI_ID2)
639 {
640 LOGREL(("found the VBE card"));
641 /*
642 * Write some hardware information to registry, so that
643 * it's visible in Windows property dialog.
644 */
645
646 /*
647 * Query the adapter's memory size. It's a bit of a hack, we just read
648 * an ULONG from the data port without setting an index before.
649 */
650 pHwResources->cbVRAM = VBVO_PORT_READ_U32(VBE_DISPI_IOPORT_DATA);
651 if (VBoxHGSMIIsSupported ())
652 {
653 PCM_RESOURCE_LIST pRcList = pDeviceInfo->TranslatedResourceList;
654 /** @todo verify resources */
655 for (ULONG i = 0; i < pRcList->Count; ++i)
656 {
657 PCM_FULL_RESOURCE_DESCRIPTOR pFRc = &pRcList->List[i];
658 for (ULONG j = 0; j < pFRc->PartialResourceList.Count; ++j)
659 {
660 PCM_PARTIAL_RESOURCE_DESCRIPTOR pPRc = &pFRc->PartialResourceList.PartialDescriptors[j];
661 switch (pPRc->Type)
662 {
663 case CmResourceTypePort:
664#ifdef VBOX_WITH_MESA3D
665 AssertBreak(pHwResources->phIO.QuadPart == 0);
666 pHwResources->phIO = pPRc->u.Port.Start;
667 pHwResources->cbIO = pPRc->u.Port.Length;
668#endif
669 break;
670 case CmResourceTypeInterrupt:
671 break;
672 case CmResourceTypeMemory:
673#ifdef VBOX_WITH_MESA3D
674 if (pHwResources->phVRAM.QuadPart)
675 {
676 AssertBreak(pHwResources->phFIFO.QuadPart == 0);
677 pHwResources->phFIFO = pPRc->u.Memory.Start;
678 pHwResources->cbFIFO = pPRc->u.Memory.Length;
679 break;
680 }
681#else
682 /* we assume there is one memory segment */
683 AssertBreak(pHwResources->phVRAM.QuadPart == 0);
684#endif
685 pHwResources->phVRAM = pPRc->u.Memory.Start;
686 Assert(pHwResources->phVRAM.QuadPart != 0);
687 pHwResources->ulApertureSize = pPRc->u.Memory.Length;
688 Assert(pHwResources->cbVRAM <= pHwResources->ulApertureSize);
689 break;
690 case CmResourceTypeDma:
691 break;
692 case CmResourceTypeDeviceSpecific:
693 break;
694 case CmResourceTypeBusNumber:
695 break;
696 default:
697 break;
698 }
699 }
700 }
701 }
702 else
703 {
704 LOGREL(("HGSMI unsupported, returning err"));
705 /** @todo report a better status */
706 Status = STATUS_UNSUCCESSFUL;
707 }
708 }
709 else
710 {
711 LOGREL(("VBE card not found, returning err"));
712 Status = STATUS_UNSUCCESSFUL;
713 }
714
715
716 return Status;
717}
718
719static void vboxWddmDevExtZeroinit(PVBOXMP_DEVEXT pDevExt, CONST PDEVICE_OBJECT pPDO)
720{
721 memset(pDevExt, 0, sizeof (VBOXMP_DEVEXT));
722 pDevExt->pPDO = pPDO;
723 PWCHAR pName = (PWCHAR)(((uint8_t*)pDevExt) + VBOXWDDM_ROUNDBOUND(sizeof(VBOXMP_DEVEXT), 8));
724 RtlInitUnicodeString(&pDevExt->RegKeyName, pName);
725
726 VBoxVidPnSourcesInit(pDevExt->aSources, RT_ELEMENTS(pDevExt->aSources), 0);
727
728 VBoxVidPnTargetsInit(pDevExt->aTargets, RT_ELEMENTS(pDevExt->aTargets), 0);
729
730 BOOLEAN f3DSupported = FALSE;
731 uint32_t u32 = 0;
732 if (VBoxVGACfgAvailable())
733 {
734 VBoxVGACfgQuery(VBE_DISPI_CFG_ID_3D, &u32, 0);
735 f3DSupported = RT_BOOL(u32);
736
737 VBoxVGACfgQuery(VBE_DISPI_CFG_ID_VMSVGA, &u32, 0);
738 }
739
740 pDevExt->enmHwType = u32 ? VBOXVIDEO_HWTYPE_VMSVGA : VBOXVIDEO_HWTYPE_VBOX;
741
742 if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VBOX)
743 {
744 pDevExt->f3DEnabled = FALSE;
745 }
746 else if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VMSVGA)
747 {
748 pDevExt->f3DEnabled = f3DSupported;
749 }
750 else
751 {
752 /* No supported 3D hardware, Fallback to VBox 2D only. */
753 pDevExt->enmHwType = VBOXVIDEO_HWTYPE_VBOX;
754 pDevExt->f3DEnabled = FALSE;
755 }
756}
757
758static void vboxWddmSetupDisplaysLegacy(PVBOXMP_DEVEXT pDevExt)
759{
760 /* For WDDM, we simply store the number of monitors as we will deal with
761 * VidPN stuff later */
762 int rc = STATUS_SUCCESS;
763
764 if (VBoxCommonFromDeviceExt(pDevExt)->bHGSMI)
765 {
766 ULONG ulAvailable = VBoxCommonFromDeviceExt(pDevExt)->cbVRAM
767 - VBoxCommonFromDeviceExt(pDevExt)->cbMiniportHeap
768 - VBVA_ADAPTER_INFORMATION_SIZE;
769
770 ULONG ulSize;
771 ULONG offset;
772 offset = ulAvailable;
773 rc = vboxVdmaCreate (pDevExt, &pDevExt->u.primary.Vdma
774 );
775 AssertRC(rc);
776 if (RT_SUCCESS(rc))
777 {
778 /* can enable it right away since the host does not need any screen/FB info
779 * for basic DMA functionality */
780 rc = vboxVdmaEnable(pDevExt, &pDevExt->u.primary.Vdma);
781 AssertRC(rc);
782 if (RT_FAILURE(rc))
783 vboxVdmaDestroy(pDevExt, &pDevExt->u.primary.Vdma);
784 }
785
786 ulAvailable = offset;
787 ulSize = ulAvailable/2;
788 offset = ulAvailable - ulSize;
789
790 NTSTATUS Status = vboxVideoAMgrCreate(pDevExt, &pDevExt->AllocMgr, offset, ulSize);
791 AssertNtStatusSuccess(Status);
792 if (Status != STATUS_SUCCESS)
793 {
794 offset = ulAvailable;
795 }
796
797#ifdef VBOXWDDM_RENDER_FROM_SHADOW
798 if (RT_SUCCESS(rc))
799 {
800 ulAvailable = offset;
801 ulSize = ulAvailable / 2;
802 ulSize /= VBoxCommonFromDeviceExt(pDevExt)->cDisplays;
803 Assert(ulSize > VBVA_MIN_BUFFER_SIZE);
804 if (ulSize > VBVA_MIN_BUFFER_SIZE)
805 {
806 ULONG ulRatio = ulSize/VBVA_MIN_BUFFER_SIZE;
807 ulRatio >>= 4; /* /= 16; */
808 if (ulRatio)
809 ulSize = VBVA_MIN_BUFFER_SIZE * ulRatio;
810 else
811 ulSize = VBVA_MIN_BUFFER_SIZE;
812 }
813 else
814 {
815 /** @todo ?? */
816 }
817
818 ulSize &= ~0xFFF;
819 Assert(ulSize);
820
821 Assert(ulSize * VBoxCommonFromDeviceExt(pDevExt)->cDisplays < ulAvailable);
822
823 for (int i = VBoxCommonFromDeviceExt(pDevExt)->cDisplays-1; i >= 0; --i)
824 {
825 offset -= ulSize;
826 rc = vboxVbvaCreate(pDevExt, &pDevExt->aSources[i].Vbva, offset, ulSize, i);
827 AssertRC(rc);
828 if (RT_SUCCESS(rc))
829 {
830 rc = vboxVbvaEnable(pDevExt, &pDevExt->aSources[i].Vbva);
831 AssertRC(rc);
832 if (RT_FAILURE(rc))
833 {
834 /** @todo de-initialize */
835 }
836 }
837 }
838 }
839#endif
840
841 /* vboxWddmVramCpuVisibleSize uses this value */
842 pDevExt->cbVRAMCpuVisible = offset;
843
844 rc = VBoxMPCmnMapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt), (void**)&pDevExt->pvVisibleVram,
845 0, vboxWddmVramCpuVisibleSize(pDevExt));
846 Assert(rc == VINF_SUCCESS);
847 if (rc != VINF_SUCCESS)
848 pDevExt->pvVisibleVram = NULL;
849
850 if (RT_FAILURE(rc))
851 VBoxCommonFromDeviceExt(pDevExt)->bHGSMI = FALSE;
852 }
853}
854
855static NTSTATUS vboxWddmSetupDisplaysNew(PVBOXMP_DEVEXT pDevExt)
856{
857 if (!VBoxCommonFromDeviceExt(pDevExt)->bHGSMI)
858 return STATUS_UNSUCCESSFUL;
859
860 ULONG cbAvailable = VBoxCommonFromDeviceExt(pDevExt)->cbVRAM
861 - VBoxCommonFromDeviceExt(pDevExt)->cbMiniportHeap
862 - VBVA_ADAPTER_INFORMATION_SIZE;
863
864 /* vboxWddmVramCpuVisibleSize uses this value */
865 pDevExt->cbVRAMCpuVisible = cbAvailable;
866
867 int rc = VBoxMPCmnMapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt), (void**)&pDevExt->pvVisibleVram,
868 0, vboxWddmVramCpuVisibleSize(pDevExt));
869 if (RT_FAILURE(rc))
870 {
871 WARN(("VBoxMPCmnMapAdapterMemory failed, rc %d", rc));
872 return STATUS_UNSUCCESSFUL;
873 }
874
875 return STATUS_SUCCESS;
876}
877
878static NTSTATUS vboxWddmSetupDisplays(PVBOXMP_DEVEXT pDevExt)
879{
880 if (pDevExt->fCmdVbvaEnabled)
881 {
882 NTSTATUS Status = vboxWddmSetupDisplaysNew(pDevExt);
883 if (!NT_SUCCESS(Status))
884 VBoxCommonFromDeviceExt(pDevExt)->bHGSMI = FALSE;
885 return Status;
886 }
887
888 vboxWddmSetupDisplaysLegacy(pDevExt);
889 return VBoxCommonFromDeviceExt(pDevExt)->bHGSMI ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
890}
891
892static int vboxWddmFreeDisplays(PVBOXMP_DEVEXT pDevExt)
893{
894 int rc = VINF_SUCCESS;
895
896 Assert(pDevExt->pvVisibleVram);
897 if (pDevExt->pvVisibleVram)
898 VBoxMPCmnUnmapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt), (void**)&pDevExt->pvVisibleVram);
899
900 if (!pDevExt->fCmdVbvaEnabled)
901 {
902 for (int i = VBoxCommonFromDeviceExt(pDevExt)->cDisplays-1; i >= 0; --i)
903 {
904 rc = vboxVbvaDisable(pDevExt, &pDevExt->aSources[i].Vbva);
905 AssertRC(rc);
906 if (RT_SUCCESS(rc))
907 {
908 rc = vboxVbvaDestroy(pDevExt, &pDevExt->aSources[i].Vbva);
909 AssertRC(rc);
910 if (RT_FAILURE(rc))
911 {
912 /** @todo */
913 }
914 }
915 }
916
917 vboxVideoAMgrDestroy(pDevExt, &pDevExt->AllocMgr);
918
919 rc = vboxVdmaDisable(pDevExt, &pDevExt->u.primary.Vdma);
920 AssertRC(rc);
921 if (RT_SUCCESS(rc))
922 {
923 rc = vboxVdmaDestroy(pDevExt, &pDevExt->u.primary.Vdma);
924 AssertRC(rc);
925 }
926 }
927
928 return rc;
929}
930
931
932/* driver callbacks */
933NTSTATUS DxgkDdiAddDevice(
934 IN CONST PDEVICE_OBJECT PhysicalDeviceObject,
935 OUT PVOID *MiniportDeviceContext
936 )
937{
938 /* The DxgkDdiAddDevice function should be made pageable. */
939 PAGED_CODE();
940
941 LOGF(("ENTER, pdo(0x%x)", PhysicalDeviceObject));
942
943 vboxVDbgBreakFv();
944
945 NTSTATUS Status = STATUS_SUCCESS;
946 PVBOXMP_DEVEXT pDevExt = NULL;
947
948 WCHAR RegKeyBuf[512];
949 ULONG cbRegKeyBuf = sizeof (RegKeyBuf);
950
951 Status = IoGetDeviceProperty (PhysicalDeviceObject,
952 DevicePropertyDriverKeyName,
953 cbRegKeyBuf,
954 RegKeyBuf,
955 &cbRegKeyBuf);
956 AssertNtStatusSuccess(Status);
957 if (Status == STATUS_SUCCESS)
958 {
959 pDevExt = (PVBOXMP_DEVEXT)vboxWddmMemAllocZero(VBOXWDDM_ROUNDBOUND(sizeof(VBOXMP_DEVEXT), 8) + cbRegKeyBuf);
960 if (pDevExt)
961 {
962 PWCHAR pName = (PWCHAR)(((uint8_t*)pDevExt) + VBOXWDDM_ROUNDBOUND(sizeof(VBOXMP_DEVEXT), 8));
963 memcpy(pName, RegKeyBuf, cbRegKeyBuf);
964 vboxWddmDevExtZeroinit(pDevExt, PhysicalDeviceObject);
965 *MiniportDeviceContext = pDevExt;
966 }
967 else
968 {
969 Status = STATUS_NO_MEMORY;
970 LOGREL(("ERROR, failed to create context"));
971 }
972 }
973
974 LOGF(("LEAVE, Status(0x%x), pDevExt(0x%x)", Status, pDevExt));
975
976 return Status;
977}
978
979NTSTATUS DxgkDdiStartDevice(
980 IN CONST PVOID MiniportDeviceContext,
981 IN PDXGK_START_INFO DxgkStartInfo,
982 IN PDXGKRNL_INTERFACE DxgkInterface,
983 OUT PULONG NumberOfVideoPresentSources,
984 OUT PULONG NumberOfChildren
985 )
986{
987 /* The DxgkDdiStartDevice function should be made pageable. */
988 PAGED_CODE();
989
990 NTSTATUS Status;
991
992 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
993
994 vboxVDbgBreakFv();
995
996 if ( ARGUMENT_PRESENT(MiniportDeviceContext) &&
997 ARGUMENT_PRESENT(DxgkInterface) &&
998 ARGUMENT_PRESENT(DxgkStartInfo) &&
999 ARGUMENT_PRESENT(NumberOfVideoPresentSources) &&
1000 ARGUMENT_PRESENT(NumberOfChildren)
1001 )
1002 {
1003 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1004
1005 vboxWddmVGuidGet(pDevExt);
1006
1007 /* Save DeviceHandle and function pointers supplied by the DXGKRNL_INTERFACE structure passed to DxgkInterface. */
1008 memcpy(&pDevExt->u.primary.DxgkInterface, DxgkInterface, sizeof (DXGKRNL_INTERFACE));
1009
1010 /* Allocate a DXGK_DEVICE_INFO structure, and call DxgkCbGetDeviceInformation to fill in the members of that structure, which include the registry path, the PDO, and a list of translated resources for the display adapter represented by MiniportDeviceContext. Save selected members (ones that the display miniport driver will need later)
1011 * of the DXGK_DEVICE_INFO structure in the context block represented by MiniportDeviceContext. */
1012 DXGK_DEVICE_INFO DeviceInfo;
1013 Status = pDevExt->u.primary.DxgkInterface.DxgkCbGetDeviceInformation (pDevExt->u.primary.DxgkInterface.DeviceHandle, &DeviceInfo);
1014 if (Status == STATUS_SUCCESS)
1015 {
1016 Status = vboxWddmPickResources(pDevExt, &DeviceInfo, &pDevExt->HwResources);
1017 if (Status == STATUS_SUCCESS)
1018 {
1019 /* Figure out the host capabilities. Start with nothing. */
1020 pDevExt->fCmdVbvaEnabled = FALSE;
1021 pDevExt->fComplexTopologiesEnabled = TRUE;
1022
1023 if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VBOX)
1024 {
1025 pDevExt->f3DEnabled = FALSE;
1026 }
1027#ifdef VBOX_WITH_MESA3D
1028 else if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VMSVGA)
1029 {
1030 if (pDevExt->f3DEnabled)
1031 {
1032 /// @todo This enables legacy code which is shared with VMSVGA, for example displays setup.
1033 // Must be removed eventually.
1034 pDevExt->fCmdVbvaEnabled = TRUE;
1035 pDevExt->fComplexTopologiesEnabled = TRUE; /** @todo Implement clones support. */
1036 }
1037 }
1038#endif /* VBOX_WITH_MESA3D */
1039 else
1040 {
1041 pDevExt->f3DEnabled = FALSE;
1042 }
1043
1044 LOGREL(("Handling complex topologies %s", pDevExt->fComplexTopologiesEnabled ? "enabled" : "disabled"));
1045
1046 /* Guest supports only HGSMI, the old VBVA via VMMDev is not supported.
1047 * The host will however support both old and new interface to keep compatibility
1048 * with old guest additions.
1049 */
1050 VBoxSetupDisplaysHGSMI(VBoxCommonFromDeviceExt(pDevExt),
1051 pDevExt->HwResources.phVRAM, pDevExt->HwResources.ulApertureSize, pDevExt->HwResources.cbVRAM,
1052 VBVACAPS_COMPLETEGCMD_BY_IOREAD | VBVACAPS_IRQ);
1053 if (VBoxCommonFromDeviceExt(pDevExt)->bHGSMI)
1054 {
1055 vboxWddmSetupDisplays(pDevExt);
1056 if (!VBoxCommonFromDeviceExt(pDevExt)->bHGSMI)
1057 VBoxFreeDisplaysHGSMI(VBoxCommonFromDeviceExt(pDevExt));
1058 }
1059 if (VBoxCommonFromDeviceExt(pDevExt)->bHGSMI)
1060 {
1061 LOGREL(("using HGSMI"));
1062 *NumberOfVideoPresentSources = VBoxCommonFromDeviceExt(pDevExt)->cDisplays;
1063 *NumberOfChildren = VBoxCommonFromDeviceExt(pDevExt)->cDisplays;
1064 LOG(("sources(%d), children(%d)", *NumberOfVideoPresentSources, *NumberOfChildren));
1065
1066 vboxVdmaDdiNodesInit(pDevExt);
1067 vboxVideoCmInit(&pDevExt->CmMgr);
1068 vboxVideoCmInit(&pDevExt->SeamlessCtxMgr);
1069 pDevExt->cContexts3D = 0;
1070 pDevExt->cContexts2D = 0;
1071 pDevExt->cContextsDispIfResize = 0;
1072 pDevExt->cUnlockedVBVADisabled = 0;
1073 pDevExt->fDisableTargetUpdate = 0;
1074 VBOXWDDM_CTXLOCK_INIT(pDevExt);
1075 KeInitializeSpinLock(&pDevExt->SynchLock);
1076
1077 VBoxCommonFromDeviceExt(pDevExt)->fAnyX = VBoxVideoAnyWidthAllowed();
1078#if 0
1079 vboxShRcTreeInit(pDevExt);
1080#endif
1081
1082#ifdef VBOX_WITH_VIDEOHWACCEL
1083 vboxVhwaInit(pDevExt);
1084#endif
1085 VBoxWddmSlInit(pDevExt);
1086
1087 for (UINT i = 0; i < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
1088 {
1089 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[i];
1090 KeInitializeSpinLock(&pSource->AllocationLock);
1091 }
1092
1093 DWORD dwVal = VBOXWDDM_CFG_DRV_DEFAULT;
1094 HANDLE hKey = NULL;
1095
1096 Status = IoOpenDeviceRegistryKey(pDevExt->pPDO, PLUGPLAY_REGKEY_DRIVER, GENERIC_READ, &hKey);
1097 if (!NT_SUCCESS(Status))
1098 {
1099 WARN(("IoOpenDeviceRegistryKey failed, Status = 0x%x", Status));
1100 hKey = NULL;
1101 }
1102
1103
1104 if (hKey)
1105 {
1106 Status = vboxWddmRegQueryValueDword(hKey, VBOXWDDM_REG_DRV_FLAGS_NAME, &dwVal);
1107 if (!NT_SUCCESS(Status))
1108 {
1109 LOG(("vboxWddmRegQueryValueDword failed, Status = 0x%x", Status));
1110 dwVal = VBOXWDDM_CFG_DRV_DEFAULT;
1111 }
1112 }
1113
1114 pDevExt->dwDrvCfgFlags = dwVal;
1115
1116 for (UINT i = 0; i < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
1117 {
1118 PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[i];
1119 if (i == 0 || (pDevExt->dwDrvCfgFlags & VBOXWDDM_CFG_DRV_SECONDARY_TARGETS_CONNECTED) || !hKey)
1120 {
1121 pTarget->fConnected = true;
1122 pTarget->fConfigured = true;
1123 }
1124 else if (hKey)
1125 {
1126 WCHAR wszNameBuf[sizeof(VBOXWDDM_REG_DRV_DISPFLAGS_PREFIX) / sizeof(WCHAR) + 32];
1127 RTUtf16Printf(wszNameBuf, RT_ELEMENTS(wszNameBuf), "%ls%u", VBOXWDDM_REG_DRV_DISPFLAGS_PREFIX, i);
1128 Status = vboxWddmRegQueryValueDword(hKey, wszNameBuf, &dwVal);
1129 if (NT_SUCCESS(Status))
1130 {
1131 pTarget->fConnected = !!(dwVal & VBOXWDDM_CFG_DRVTARGET_CONNECTED);
1132 pTarget->fConfigured = true;
1133 }
1134 else
1135 {
1136 WARN(("vboxWddmRegQueryValueDword failed, Status = 0x%x", Status));
1137 pTarget->fConnected = false;
1138 pTarget->fConfigured = false;
1139 }
1140 }
1141 }
1142
1143 if (hKey)
1144 {
1145 NTSTATUS rcNt2 = ZwClose(hKey);
1146 Assert(rcNt2 == STATUS_SUCCESS); NOREF(rcNt2);
1147 }
1148
1149 Status = STATUS_SUCCESS;
1150
1151 if (VBoxQueryWinVersion(NULL) >= WINVERSION_8)
1152 {
1153 DXGK_DISPLAY_INFORMATION DisplayInfo;
1154 Status = pDevExt->u.primary.DxgkInterface.DxgkCbAcquirePostDisplayOwnership(pDevExt->u.primary.DxgkInterface.DeviceHandle,
1155 &DisplayInfo);
1156 if (NT_SUCCESS(Status))
1157 {
1158 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[0];
1159 PHYSICAL_ADDRESS PhAddr;
1160 /* display info may sometimes not be valid, e.g. on from-full-graphics wddm driver update
1161 * ensure we have something meaningful here */
1162 if (!DisplayInfo.Width)
1163 {
1164 PhAddr = VBoxCommonFromDeviceExt(pDevExt)->phVRAM;
1165 vboxWddmDiInitDefault(&DisplayInfo, PhAddr, 0);
1166 }
1167 else
1168 {
1169 PhAddr = DisplayInfo.PhysicAddress;
1170 DisplayInfo.TargetId = 0;
1171 }
1172
1173 vboxWddmDiToAllocData(pDevExt, &DisplayInfo, &pSource->AllocData);
1174
1175 /* init the rest source infos with some default values */
1176 for (UINT i = 1; i < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
1177 {
1178 PhAddr.QuadPart += pSource->AllocData.SurfDesc.cbSize;
1179 PhAddr.QuadPart = ROUND_TO_PAGES(PhAddr.QuadPart);
1180 vboxWddmDiInitDefault(&DisplayInfo, PhAddr, i);
1181 pSource = &pDevExt->aSources[i];
1182 vboxWddmDiToAllocData(pDevExt, &DisplayInfo, &pSource->AllocData);
1183 }
1184 }
1185 else
1186 {
1187 WARN(("DxgkCbAcquirePostDisplayOwnership failed, Status 0x%x", Status));
1188 }
1189 }
1190
1191 VBoxWddmVModesInit(pDevExt);
1192
1193#ifdef VBOX_WITH_MESA3D
1194 if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VMSVGA)
1195 {
1196 LOGREL(("WDDM: VRAM %#RX64/%#RX32, FIFO %#RX64/%#RX32, IO %#RX64/%#RX32",
1197 pDevExt->HwResources.phVRAM.QuadPart, pDevExt->HwResources.cbVRAM,
1198 pDevExt->HwResources.phFIFO.QuadPart, pDevExt->HwResources.cbFIFO,
1199 pDevExt->HwResources.phIO.QuadPart, pDevExt->HwResources.cbIO));
1200
1201 Status = GaAdapterStart(pDevExt);
1202 if (Status == STATUS_SUCCESS)
1203 { /* likely */ }
1204 else
1205 LOGREL(("WDDM: GaAdapterStart failed Status(0x%x)", Status));
1206 }
1207#endif
1208 }
1209 else
1210 {
1211 LOGREL(("HGSMI failed to initialize, returning err"));
1212
1213 /** @todo report a better status */
1214 Status = STATUS_UNSUCCESSFUL;
1215 }
1216 }
1217 else
1218 {
1219 LOGREL(("vboxWddmPickResources failed Status(0x%x), returning err", Status));
1220 Status = STATUS_UNSUCCESSFUL;
1221 }
1222 }
1223 else
1224 {
1225 LOGREL(("DxgkCbGetDeviceInformation failed Status(0x%x), returning err", Status));
1226 }
1227 }
1228 else
1229 {
1230 LOGREL(("invalid parameter, returning err"));
1231 Status = STATUS_INVALID_PARAMETER;
1232 }
1233
1234 LOGF(("LEAVE, status(0x%x)", Status));
1235
1236 return Status;
1237}
1238
1239NTSTATUS DxgkDdiStopDevice(
1240 IN CONST PVOID MiniportDeviceContext
1241 )
1242{
1243 /* The DxgkDdiStopDevice function should be made pageable. */
1244 PAGED_CODE();
1245
1246 LOGF(("ENTER, context(0x%p)", MiniportDeviceContext));
1247
1248 vboxVDbgBreakFv();
1249
1250 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1251 NTSTATUS Status = STATUS_SUCCESS;
1252
1253#ifdef VBOX_WITH_MESA3D
1254 if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VMSVGA)
1255 {
1256 GaAdapterStop(pDevExt);
1257 }
1258#endif
1259
1260 VBoxWddmSlTerm(pDevExt);
1261
1262 vboxVideoCmTerm(&pDevExt->CmMgr);
1263
1264 vboxVideoCmTerm(&pDevExt->SeamlessCtxMgr);
1265
1266 /* do everything we did on DxgkDdiStartDevice in the reverse order */
1267#ifdef VBOX_WITH_VIDEOHWACCEL
1268 vboxVhwaFree(pDevExt);
1269#endif
1270#if 0
1271 vboxShRcTreeTerm(pDevExt);
1272#endif
1273
1274 int rc = vboxWddmFreeDisplays(pDevExt);
1275 if (RT_SUCCESS(rc))
1276 VBoxFreeDisplaysHGSMI(VBoxCommonFromDeviceExt(pDevExt));
1277 AssertRC(rc);
1278 if (RT_SUCCESS(rc))
1279 {
1280 vboxWddmVGuidFree(pDevExt);
1281
1282 VBoxWddmVModesCleanup();
1283 /* revert back to the state we were right after the DxgkDdiAddDevice */
1284 vboxWddmDevExtZeroinit(pDevExt, pDevExt->pPDO);
1285 }
1286 else
1287 Status = STATUS_UNSUCCESSFUL;
1288
1289 return Status;
1290}
1291
1292NTSTATUS DxgkDdiRemoveDevice(
1293 IN CONST PVOID MiniportDeviceContext
1294 )
1295{
1296 /* DxgkDdiRemoveDevice should be made pageable. */
1297 PAGED_CODE();
1298
1299 LOGF(("ENTER, context(0x%p)", MiniportDeviceContext));
1300
1301 vboxVDbgBreakFv();
1302
1303 vboxWddmMemFree(MiniportDeviceContext);
1304
1305 LOGF(("LEAVE, context(0x%p)", MiniportDeviceContext));
1306
1307 return STATUS_SUCCESS;
1308}
1309
1310NTSTATUS DxgkDdiDispatchIoRequest(
1311 IN CONST PVOID MiniportDeviceContext,
1312 IN ULONG VidPnSourceId,
1313 IN PVIDEO_REQUEST_PACKET VideoRequestPacket
1314 )
1315{
1316 LOGF(("ENTER, context(0x%p), ctl(0x%x)", MiniportDeviceContext, VideoRequestPacket->IoControlCode));
1317
1318 AssertBreakpoint();
1319#if 0
1320 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1321
1322 switch (VideoRequestPacket->IoControlCode)
1323 {
1324 case IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES:
1325 {
1326 if (VideoRequestPacket->OutputBufferLength < sizeof(VIDEO_COLOR_CAPABILITIES))
1327 {
1328 AssertBreakpoint();
1329 VideoRequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1330 return TRUE;
1331 }
1332 VIDEO_COLOR_CAPABILITIES *pCaps = (VIDEO_COLOR_CAPABILITIES*)VideoRequestPacket->OutputBuffer;
1333
1334 pCaps->Length = sizeof (VIDEO_COLOR_CAPABILITIES);
1335 pCaps->AttributeFlags = VIDEO_DEVICE_COLOR;
1336 pCaps->RedPhosphoreDecay = 0;
1337 pCaps->GreenPhosphoreDecay = 0;
1338 pCaps->BluePhosphoreDecay = 0;
1339 pCaps->WhiteChromaticity_x = 3127;
1340 pCaps->WhiteChromaticity_y = 3290;
1341 pCaps->WhiteChromaticity_Y = 0;
1342 pCaps->RedChromaticity_x = 6700;
1343 pCaps->RedChromaticity_y = 3300;
1344 pCaps->GreenChromaticity_x = 2100;
1345 pCaps->GreenChromaticity_y = 7100;
1346 pCaps->BlueChromaticity_x = 1400;
1347 pCaps->BlueChromaticity_y = 800;
1348 pCaps->WhiteGamma = 0;
1349 pCaps->RedGamma = 20000;
1350 pCaps->GreenGamma = 20000;
1351 pCaps->BlueGamma = 20000;
1352
1353 VideoRequestPacket->StatusBlock->Status = NO_ERROR;
1354 VideoRequestPacket->StatusBlock->Information = sizeof (VIDEO_COLOR_CAPABILITIES);
1355 break;
1356 }
1357#if 0
1358 case IOCTL_VIDEO_HANDLE_VIDEOPARAMETERS:
1359 {
1360 if (VideoRequestPacket->OutputBufferLength < sizeof(VIDEOPARAMETERS)
1361 || VideoRequestPacket->InputBufferLength < sizeof(VIDEOPARAMETERS))
1362 {
1363 AssertBreakpoint();
1364 VideoRequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1365 return TRUE;
1366 }
1367
1368 Result = VBoxVideoResetDevice((PVBOXMP_DEVEXT)HwDeviceExtension,
1369 RequestPacket->StatusBlock);
1370 break;
1371 }
1372#endif
1373 default:
1374 AssertBreakpoint();
1375 VideoRequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1376 VideoRequestPacket->StatusBlock->Information = 0;
1377 }
1378#else
1379 RT_NOREF(MiniportDeviceContext, VidPnSourceId, VideoRequestPacket);
1380#endif
1381 LOGF(("LEAVE, context(0x%p), ctl(0x%x)", MiniportDeviceContext, VideoRequestPacket->IoControlCode));
1382
1383 return STATUS_SUCCESS;
1384}
1385
1386NTSTATUS DxgkDdiQueryChildRelations(
1387 IN CONST PVOID MiniportDeviceContext,
1388 IN OUT PDXGK_CHILD_DESCRIPTOR ChildRelations,
1389 IN ULONG ChildRelationsSize
1390 )
1391{
1392 RT_NOREF(ChildRelationsSize);
1393 /* The DxgkDdiQueryChildRelations function should be made pageable. */
1394 PAGED_CODE();
1395
1396 vboxVDbgBreakFv();
1397
1398 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1399
1400 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
1401 Assert(ChildRelationsSize == (VBoxCommonFromDeviceExt(pDevExt)->cDisplays + 1)*sizeof(DXGK_CHILD_DESCRIPTOR));
1402 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
1403 {
1404 ChildRelations[i].ChildDeviceType = TypeVideoOutput;
1405 ChildRelations[i].ChildCapabilities.Type.VideoOutput.InterfaceTechnology = D3DKMDT_VOT_HD15; /* VGA */
1406 ChildRelations[i].ChildCapabilities.Type.VideoOutput.MonitorOrientationAwareness = D3DKMDT_MOA_NONE; //D3DKMDT_MOA_INTERRUPTIBLE; /* ?? D3DKMDT_MOA_NONE*/
1407 ChildRelations[i].ChildCapabilities.Type.VideoOutput.SupportsSdtvModes = FALSE;
1408 ChildRelations[i].ChildCapabilities.HpdAwareness = HpdAwarenessInterruptible; /* ?? HpdAwarenessAlwaysConnected; */
1409 ChildRelations[i].AcpiUid = 0; /* */
1410 ChildRelations[i].ChildUid = i; /* should be == target id */
1411 }
1412 LOGF(("LEAVE, context(0x%x)", MiniportDeviceContext));
1413 return STATUS_SUCCESS;
1414}
1415
1416NTSTATUS DxgkDdiQueryChildStatus(
1417 IN CONST PVOID MiniportDeviceContext,
1418 IN PDXGK_CHILD_STATUS ChildStatus,
1419 IN BOOLEAN NonDestructiveOnly
1420 )
1421{
1422 RT_NOREF(NonDestructiveOnly);
1423 /* The DxgkDdiQueryChildStatus should be made pageable. */
1424 PAGED_CODE();
1425
1426 vboxVDbgBreakFv();
1427
1428 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
1429
1430 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1431
1432 if (ChildStatus->ChildUid >= (uint32_t)VBoxCommonFromDeviceExt(pDevExt)->cDisplays)
1433 {
1434 WARN(("Invalid child id %d", ChildStatus->ChildUid));
1435 return STATUS_INVALID_PARAMETER;
1436 }
1437
1438 NTSTATUS Status = STATUS_SUCCESS;
1439 switch (ChildStatus->Type)
1440 {
1441 case StatusConnection:
1442 {
1443 LOGF(("StatusConnection"));
1444 VBOXWDDM_TARGET *pTarget = &pDevExt->aTargets[ChildStatus->ChildUid];
1445 BOOLEAN Connected = !!pTarget->fConnected;
1446 if (!Connected)
1447 LOGREL(("Tgt[%d] DISCONNECTED!!", ChildStatus->ChildUid));
1448 ChildStatus->HotPlug.Connected = !!pTarget->fConnected;
1449 break;
1450 }
1451 case StatusRotation:
1452 LOGF(("StatusRotation"));
1453 ChildStatus->Rotation.Angle = 0;
1454 break;
1455 default:
1456 WARN(("ERROR: status type: %d", ChildStatus->Type));
1457 Status = STATUS_INVALID_PARAMETER;
1458 break;
1459 }
1460
1461 LOGF(("LEAVE, context(0x%x)", MiniportDeviceContext));
1462
1463 return Status;
1464}
1465
1466NTSTATUS DxgkDdiQueryDeviceDescriptor(
1467 IN CONST PVOID MiniportDeviceContext,
1468 IN ULONG ChildUid,
1469 IN OUT PDXGK_DEVICE_DESCRIPTOR DeviceDescriptor
1470 )
1471{
1472 RT_NOREF(MiniportDeviceContext, ChildUid, DeviceDescriptor);
1473 /* The DxgkDdiQueryDeviceDescriptor should be made pageable. */
1474 PAGED_CODE();
1475
1476 vboxVDbgBreakFv();
1477
1478 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
1479
1480 LOGF(("LEAVE, context(0x%x)", MiniportDeviceContext));
1481
1482 /* we do not support EDID */
1483 return STATUS_MONITOR_NO_DESCRIPTOR;
1484}
1485
1486NTSTATUS DxgkDdiSetPowerState(
1487 IN CONST PVOID MiniportDeviceContext,
1488 IN ULONG DeviceUid,
1489 IN DEVICE_POWER_STATE DevicePowerState,
1490 IN POWER_ACTION ActionType
1491 )
1492{
1493 RT_NOREF(MiniportDeviceContext, DeviceUid, DevicePowerState, ActionType);
1494 /* The DxgkDdiSetPowerState function should be made pageable. */
1495 PAGED_CODE();
1496
1497 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
1498
1499 vboxVDbgBreakFv();
1500
1501 LOGF(("LEAVE, context(0x%x)", MiniportDeviceContext));
1502
1503 return STATUS_SUCCESS;
1504}
1505
1506NTSTATUS DxgkDdiNotifyAcpiEvent(
1507 IN CONST PVOID MiniportDeviceContext,
1508 IN DXGK_EVENT_TYPE EventType,
1509 IN ULONG Event,
1510 IN PVOID Argument,
1511 OUT PULONG AcpiFlags
1512 )
1513{
1514 RT_NOREF(MiniportDeviceContext, EventType, Event, Argument, AcpiFlags);
1515 LOGF(("ENTER, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
1516
1517 vboxVDbgBreakF();
1518
1519 LOGF(("LEAVE, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
1520
1521 return STATUS_SUCCESS;
1522}
1523
1524VOID DxgkDdiResetDevice(
1525 IN CONST PVOID MiniportDeviceContext
1526 )
1527{
1528 RT_NOREF(MiniportDeviceContext);
1529 /* DxgkDdiResetDevice can be called at any IRQL, so it must be in nonpageable memory. */
1530 vboxVDbgBreakF();
1531
1532
1533
1534 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
1535 LOGF(("LEAVE, context(0x%x)", MiniportDeviceContext));
1536}
1537
1538VOID DxgkDdiUnload(
1539 VOID
1540 )
1541{
1542 /* DxgkDdiUnload should be made pageable. */
1543 PAGED_CODE();
1544 LOGF((": unloading"));
1545
1546 vboxVDbgBreakFv();
1547
1548 VbglR0TerminateClient();
1549
1550 PRTLOGGER pLogger = RTLogRelSetDefaultInstance(NULL);
1551 if (pLogger)
1552 {
1553 RTLogDestroy(pLogger);
1554 }
1555 pLogger = RTLogSetDefaultInstance(NULL);
1556 if (pLogger)
1557 {
1558 RTLogDestroy(pLogger);
1559 }
1560
1561 RTR0Term();
1562}
1563
1564NTSTATUS DxgkDdiQueryInterface(
1565 IN CONST PVOID MiniportDeviceContext,
1566 IN PQUERY_INTERFACE QueryInterface
1567 )
1568{
1569 RT_NOREF(MiniportDeviceContext, QueryInterface);
1570 LOGF(("ENTER, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
1571
1572 vboxVDbgBreakFv();
1573
1574 LOGF(("LEAVE, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
1575
1576 return STATUS_NOT_SUPPORTED;
1577}
1578
1579VOID DxgkDdiControlEtwLogging(
1580 IN BOOLEAN Enable,
1581 IN ULONG Flags,
1582 IN UCHAR Level
1583 )
1584{
1585 RT_NOREF(Enable, Flags, Level);
1586 LOGF(("ENTER"));
1587
1588 vboxVDbgBreakF();
1589
1590 LOGF(("LEAVE"));
1591}
1592
1593/**
1594 * DxgkDdiQueryAdapterInfo
1595 */
1596NTSTATUS APIENTRY DxgkDdiQueryAdapterInfo(
1597 CONST HANDLE hAdapter,
1598 CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo)
1599{
1600 /* The DxgkDdiQueryAdapterInfo should be made pageable. */
1601 PAGED_CODE();
1602
1603 LOGF(("ENTER, context(0x%x), Query type (%d)", hAdapter, pQueryAdapterInfo->Type));
1604 NTSTATUS Status = STATUS_SUCCESS;
1605 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
1606
1607 vboxVDbgBreakFv();
1608
1609 switch (pQueryAdapterInfo->Type)
1610 {
1611 case DXGKQAITYPE_DRIVERCAPS:
1612 {
1613 DXGK_DRIVERCAPS *pCaps = (DXGK_DRIVERCAPS*)pQueryAdapterInfo->pOutputData;
1614 memset(pCaps, 0, sizeof (*pCaps));
1615
1616 pCaps->HighestAcceptableAddress.LowPart = ~0UL;
1617#ifdef RT_ARCH_AMD64
1618 /* driver talks to host in terms of page numbers when reffering to RAM
1619 * we use uint32_t field to pass page index to host, so max would be (~0UL) << PAGE_OFFSET,
1620 * which seems quite enough */
1621 pCaps->HighestAcceptableAddress.HighPart = PAGE_OFFSET_MASK;
1622#endif
1623 pCaps->MaxPointerWidth = VBOXWDDM_C_POINTER_MAX_WIDTH;
1624 pCaps->MaxPointerHeight = VBOXWDDM_C_POINTER_MAX_HEIGHT;
1625#ifdef VBOX_WITH_MESA3D
1626 if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VBOX)
1627 {
1628 pCaps->MaxPointerWidth = VBOXWDDM_C_POINTER_MAX_WIDTH_LEGACY;
1629 pCaps->MaxPointerHeight = VBOXWDDM_C_POINTER_MAX_HEIGHT_LEGACY;
1630 }
1631#endif
1632 pCaps->PointerCaps.Value = 3; /* Monochrome , Color*/ /* MaskedColor == Value | 4, disable for now */
1633 if (!g_VBoxDisplayOnly)
1634 {
1635 pCaps->MaxAllocationListSlotId = 16;
1636 pCaps->ApertureSegmentCommitLimit = 0;
1637 pCaps->InterruptMessageNumber = 0;
1638 pCaps->NumberOfSwizzlingRanges = 0;
1639 pCaps->MaxOverlays = 0;
1640#ifdef VBOX_WITH_VIDEOHWACCEL
1641 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
1642 {
1643 if ( pDevExt->aSources[i].Vhwa.Settings.fFlags & VBOXVHWA_F_ENABLED)
1644 pCaps->MaxOverlays += pDevExt->aSources[i].Vhwa.Settings.cOverlaysSupported;
1645 }
1646#endif
1647 pCaps->GammaRampCaps.Value = 0;
1648 pCaps->PresentationCaps.Value = 0;
1649 pCaps->PresentationCaps.NoScreenToScreenBlt = 1;
1650 pCaps->PresentationCaps.NoOverlapScreenBlt = 1;
1651 pCaps->PresentationCaps.AlignmentShift = 2;
1652 pCaps->PresentationCaps.MaxTextureWidthShift = 2; /* Up to 8196 */
1653 pCaps->PresentationCaps.MaxTextureHeightShift = 2; /* Up to 8196 */
1654 pCaps->MaxQueuedFlipOnVSync = 0; /* do we need it? */
1655 pCaps->FlipCaps.Value = 0;
1656 /* ? pCaps->FlipCaps.FlipOnVSyncWithNoWait = 1; */
1657 pCaps->SchedulingCaps.Value = 0;
1658 /* we might need it for Aero.
1659 * Setting this flag means we support DeviceContext, i.e.
1660 * DxgkDdiCreateContext and DxgkDdiDestroyContext
1661 */
1662 pCaps->SchedulingCaps.MultiEngineAware = 1;
1663 pCaps->MemoryManagementCaps.Value = 0;
1664 /** @todo this correlates with pCaps->SchedulingCaps.MultiEngineAware */
1665 pCaps->MemoryManagementCaps.PagingNode = 0;
1666 /** @todo this correlates with pCaps->SchedulingCaps.MultiEngineAware */
1667 pCaps->GpuEngineTopology.NbAsymetricProcessingNodes = VBOXWDDM_NUM_NODES;
1668#ifdef VBOX_WITH_MESA3D
1669 if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VMSVGA)
1670 {
1671 /* The Gallium node has NodeOrdinal == 0, because:
1672 * GDI context is created with it;
1673 * we generate commands for the context;
1674 * there seems to be no easy way to distinguish which node a fence was completed for.
1675 *
1676 * GDI context is used for example for copying between D3DKMDT_STANDARDALLOCATION_SHADOWSURFACE
1677 * and D3DKMDT_STANDARDALLOCATION_SHAREDPRIMARYSURFACE.
1678 */
1679 pCaps->GpuEngineTopology.NbAsymetricProcessingNodes = 1;
1680 }
1681#endif
1682
1683 if (VBoxQueryWinVersion(NULL) >= WINVERSION_8)
1684 pCaps->WDDMVersion = DXGKDDI_WDDMv1_2;
1685 }
1686 else
1687 {
1688 pCaps->WDDMVersion = DXGKDDI_WDDMv1_2;
1689 }
1690 break;
1691 }
1692 case DXGKQAITYPE_QUERYSEGMENT:
1693 {
1694 if (!g_VBoxDisplayOnly)
1695 {
1696 /* no need for DXGK_QUERYSEGMENTIN as it contains AGP aperture info, which (AGP aperture) we do not support
1697 * DXGK_QUERYSEGMENTIN *pQsIn = (DXGK_QUERYSEGMENTIN*)pQueryAdapterInfo->pInputData; */
1698 DXGK_QUERYSEGMENTOUT *pQsOut = (DXGK_QUERYSEGMENTOUT*)pQueryAdapterInfo->pOutputData;
1699# define VBOXWDDM_SEGMENTS_COUNT 2
1700 if (!pQsOut->pSegmentDescriptor)
1701 {
1702 /* we are requested to provide the number of segments we support */
1703 pQsOut->NbSegment = VBOXWDDM_SEGMENTS_COUNT;
1704 }
1705 else if (pQsOut->NbSegment != VBOXWDDM_SEGMENTS_COUNT)
1706 {
1707 WARN(("NbSegment (%d) != 1", pQsOut->NbSegment));
1708 Status = STATUS_INVALID_PARAMETER;
1709 }
1710 else
1711 {
1712 DXGK_SEGMENTDESCRIPTOR* pDr = pQsOut->pSegmentDescriptor;
1713 /* we are requested to provide segment information */
1714 pDr->BaseAddress.QuadPart = 0;
1715 pDr->CpuTranslatedAddress = VBoxCommonFromDeviceExt(pDevExt)->phVRAM;
1716 /* make sure the size is page aligned */
1717 /** @todo need to setup VBVA buffers and adjust the mem size here */
1718 pDr->Size = vboxWddmVramCpuVisibleSegmentSize(pDevExt);
1719 pDr->NbOfBanks = 0;
1720 pDr->pBankRangeTable = 0;
1721 pDr->CommitLimit = pDr->Size;
1722 pDr->Flags.Value = 0;
1723 pDr->Flags.CpuVisible = 1;
1724
1725 ++pDr;
1726 /* create cpu-invisible segment of the same size */
1727 pDr->BaseAddress.QuadPart = 0;
1728 pDr->CpuTranslatedAddress.QuadPart = 0;
1729 /* make sure the size is page aligned */
1730 /** @todo need to setup VBVA buffers and adjust the mem size here */
1731 pDr->Size = vboxWddmVramCpuInvisibleSegmentSize(pDevExt);
1732 pDr->NbOfBanks = 0;
1733 pDr->pBankRangeTable = 0;
1734 pDr->CommitLimit = pDr->Size;
1735 pDr->Flags.Value = 0;
1736
1737 pQsOut->PagingBufferSegmentId = 0;
1738 pQsOut->PagingBufferSize = PAGE_SIZE;
1739 pQsOut->PagingBufferPrivateDataSize = PAGE_SIZE;
1740 }
1741 }
1742 else
1743 {
1744 WARN(("unsupported Type (%d)", pQueryAdapterInfo->Type));
1745 Status = STATUS_NOT_SUPPORTED;
1746 }
1747
1748 break;
1749 }
1750 case DXGKQAITYPE_UMDRIVERPRIVATE:
1751 if (!g_VBoxDisplayOnly)
1752 {
1753 if (pQueryAdapterInfo->OutputDataSize >= sizeof(VBOXWDDM_QAI))
1754 {
1755 VBOXWDDM_QAI *pQAI = (VBOXWDDM_QAI *)pQueryAdapterInfo->pOutputData;
1756 memset(pQAI, 0, sizeof(VBOXWDDM_QAI));
1757
1758 pQAI->u32Version = VBOXVIDEOIF_VERSION;
1759 pQAI->enmHwType = pDevExt->enmHwType;
1760 pQAI->u32AdapterCaps = pDevExt->f3DEnabled ? VBOXWDDM_QAI_CAP_3D : 0;
1761 pQAI->u32AdapterCaps |= VBOXWDDM_QAI_CAP_DXVA; /** @todo Fetch from registry. */
1762 if (VBoxQueryWinVersion(NULL) >= WINVERSION_7)
1763 {
1764 pQAI->u32AdapterCaps |= VBOXWDDM_QAI_CAP_WIN7;
1765 // pQAI->u32AdapterCaps |= VBOXWDDM_QAI_CAP_DXVAHD; /** @todo Fetch from registry. */
1766 }
1767
1768 static int cLoggedCaps = 0;
1769 if (cLoggedCaps < 1)
1770 {
1771 ++cLoggedCaps;
1772 LOGREL_EXACT(("WDDM: adapter capabilities 0x%08X\n", pQAI->u32AdapterCaps));
1773 }
1774
1775 if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VBOX)
1776 {
1777 pQAI->u.vbox.u32VBox3DCaps = 0;
1778 }
1779#ifdef VBOX_WITH_MESA3D
1780 else if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VMSVGA)
1781 GaQueryInfo(pDevExt->pGa, pDevExt->enmHwType, &pQAI->u.vmsvga.HWInfo);
1782#endif
1783
1784#ifdef VBOX_WITH_VIDEOHWACCEL
1785 pQAI->cInfos = VBoxCommonFromDeviceExt(pDevExt)->cDisplays;
1786 for (uint32_t i = 0; i < pQAI->cInfos; ++i)
1787 {
1788 pQAI->aInfos[i] = pDevExt->aSources[i].Vhwa.Settings;
1789 }
1790#endif
1791 }
1792 else
1793 {
1794 WARN(("incorrect buffer size %d, expected %d", pQueryAdapterInfo->OutputDataSize, sizeof(VBOXWDDM_QAI)));
1795 Status = STATUS_BUFFER_TOO_SMALL;
1796 }
1797 }
1798 else
1799 {
1800 WARN(("unsupported Type (%d)", pQueryAdapterInfo->Type));
1801 Status = STATUS_NOT_SUPPORTED;
1802 }
1803 break;
1804
1805 case DXGKQAITYPE_QUERYSEGMENT3:
1806 LOGREL(("DXGKQAITYPE_QUERYSEGMENT3 treating as unsupported!"));
1807 Status = STATUS_NOT_SUPPORTED;
1808 break;
1809
1810 default:
1811 WARN(("unsupported Type (%d)", pQueryAdapterInfo->Type));
1812 Status = STATUS_NOT_SUPPORTED;
1813 break;
1814 }
1815 LOGF(("LEAVE, context(0x%x), Status(0x%x)", hAdapter, Status));
1816 return Status;
1817}
1818
1819/**
1820 * DxgkDdiCreateDevice
1821 */
1822NTSTATUS APIENTRY DxgkDdiCreateDevice(
1823 CONST HANDLE hAdapter,
1824 DXGKARG_CREATEDEVICE* pCreateDevice)
1825{
1826 /* DxgkDdiCreateDevice should be made pageable. */
1827 PAGED_CODE();
1828
1829 LOGF(("ENTER, context(0x%x)", hAdapter));
1830 NTSTATUS Status = STATUS_SUCCESS;
1831 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
1832
1833 vboxVDbgBreakFv();
1834
1835 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)vboxWddmMemAllocZero(sizeof (VBOXWDDM_DEVICE));
1836 if (!pDevice)
1837 {
1838 WARN(("vboxWddmMemAllocZero failed for WDDM device structure"));
1839 return STATUS_NO_MEMORY;
1840 }
1841
1842 pDevice->pAdapter = pDevExt;
1843 pDevice->hDevice = pCreateDevice->hDevice;
1844
1845 pCreateDevice->hDevice = pDevice;
1846 if (pCreateDevice->Flags.SystemDevice)
1847 pDevice->enmType = VBOXWDDM_DEVICE_TYPE_SYSTEM;
1848
1849 pCreateDevice->pInfo = NULL;
1850
1851#ifdef VBOX_WITH_MESA3D
1852 if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VMSVGA)
1853 {
1854 Status = GaDeviceCreate(pDevExt->pGa, pDevice);
1855 if (Status != STATUS_SUCCESS)
1856 {
1857 vboxWddmMemFree(pDevice);
1858 }
1859 }
1860#endif
1861
1862 LOGF(("LEAVE, context(0x%x), Status(0x%x)", hAdapter, Status));
1863
1864 return Status;
1865}
1866
1867PVBOXWDDM_RESOURCE vboxWddmResourceCreate(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_RCINFO pRcInfo)
1868{
1869 RT_NOREF(pDevExt);
1870 PVBOXWDDM_RESOURCE pResource = (PVBOXWDDM_RESOURCE)vboxWddmMemAllocZero(RT_UOFFSETOF_DYN(VBOXWDDM_RESOURCE,
1871 aAllocations[pRcInfo->cAllocInfos]));
1872 if (!pResource)
1873 {
1874 AssertFailed();
1875 return NULL;
1876 }
1877 pResource->cRefs = 1;
1878 pResource->cAllocations = pRcInfo->cAllocInfos;
1879 pResource->fFlags = pRcInfo->fFlags;
1880 pResource->RcDesc = pRcInfo->RcDesc;
1881 return pResource;
1882}
1883
1884VOID vboxWddmResourceRetain(PVBOXWDDM_RESOURCE pResource)
1885{
1886 ASMAtomicIncU32(&pResource->cRefs);
1887}
1888
1889static VOID vboxWddmResourceDestroy(PVBOXWDDM_RESOURCE pResource)
1890{
1891 vboxWddmMemFree(pResource);
1892}
1893
1894VOID vboxWddmResourceWaitDereference(PVBOXWDDM_RESOURCE pResource)
1895{
1896 vboxWddmCounterU32Wait(&pResource->cRefs, 1);
1897}
1898
1899VOID vboxWddmResourceRelease(PVBOXWDDM_RESOURCE pResource)
1900{
1901 uint32_t cRefs = ASMAtomicDecU32(&pResource->cRefs);
1902 Assert(cRefs < UINT32_MAX/2);
1903 if (!cRefs)
1904 {
1905 vboxWddmResourceDestroy(pResource);
1906 }
1907}
1908
1909void vboxWddmAllocationDeleteFromResource(PVBOXWDDM_RESOURCE pResource, PVBOXWDDM_ALLOCATION pAllocation)
1910{
1911 Assert(pAllocation->pResource == pResource);
1912 if (pResource)
1913 {
1914 Assert(&pResource->aAllocations[pAllocation->iIndex] == pAllocation);
1915 vboxWddmResourceRelease(pResource);
1916 }
1917 else
1918 {
1919 vboxWddmMemFree(pAllocation);
1920 }
1921}
1922
1923VOID vboxWddmAllocationCleanupAssignment(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pAllocation)
1924{
1925 switch (pAllocation->enmType)
1926 {
1927 case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
1928 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
1929 {
1930 if (pAllocation->bAssigned)
1931 {
1932 /** @todo do we need to notify host? */
1933 vboxWddmAssignPrimary(&pDevExt->aSources[pAllocation->AllocData.SurfDesc.VidPnSourceId], NULL, pAllocation->AllocData.SurfDesc.VidPnSourceId);
1934 }
1935 break;
1936 }
1937 default:
1938 break;
1939 }
1940}
1941
1942VOID vboxWddmAllocationCleanup(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pAllocation)
1943{
1944 RT_NOREF(pDevExt);
1945 switch (pAllocation->enmType)
1946 {
1947 case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
1948 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
1949 {
1950#if 0
1951 if (pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC)
1952 {
1953 if (pAllocation->hSharedHandle)
1954 {
1955 vboxShRcTreeRemove(pDevExt, pAllocation);
1956 }
1957 }
1958#endif
1959 break;
1960 }
1961 case VBOXWDDM_ALLOC_TYPE_UMD_HGSMI_BUFFER:
1962 {
1963 break;
1964 }
1965 default:
1966 break;
1967 }
1968}
1969
1970VOID vboxWddmAllocationDestroy(PVBOXWDDM_ALLOCATION pAllocation)
1971{
1972 PAGED_CODE();
1973
1974 vboxWddmAllocationDeleteFromResource(pAllocation->pResource, pAllocation);
1975}
1976
1977PVBOXWDDM_ALLOCATION vboxWddmAllocationCreateFromResource(PVBOXWDDM_RESOURCE pResource, uint32_t iIndex)
1978{
1979 PVBOXWDDM_ALLOCATION pAllocation = NULL;
1980 if (pResource)
1981 {
1982 Assert(iIndex < pResource->cAllocations);
1983 if (iIndex < pResource->cAllocations)
1984 {
1985 pAllocation = &pResource->aAllocations[iIndex];
1986 memset(pAllocation, 0, sizeof (VBOXWDDM_ALLOCATION));
1987 }
1988 vboxWddmResourceRetain(pResource);
1989 }
1990 else
1991 pAllocation = (PVBOXWDDM_ALLOCATION)vboxWddmMemAllocZero(sizeof (VBOXWDDM_ALLOCATION));
1992
1993 if (pAllocation)
1994 {
1995 if (pResource)
1996 {
1997 pAllocation->pResource = pResource;
1998 pAllocation->iIndex = iIndex;
1999 }
2000 }
2001
2002 return pAllocation;
2003}
2004
2005NTSTATUS vboxWddmAllocationCreate(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_RESOURCE pResource, uint32_t iIndex, DXGK_ALLOCATIONINFO* pAllocationInfo)
2006{
2007 PAGED_CODE();
2008
2009 NTSTATUS Status = STATUS_SUCCESS;
2010
2011 Assert(pAllocationInfo->PrivateDriverDataSize == sizeof (VBOXWDDM_ALLOCINFO));
2012 if (pAllocationInfo->PrivateDriverDataSize >= sizeof (VBOXWDDM_ALLOCINFO))
2013 {
2014 PVBOXWDDM_ALLOCINFO pAllocInfo = (PVBOXWDDM_ALLOCINFO)pAllocationInfo->pPrivateDriverData;
2015 PVBOXWDDM_ALLOCATION pAllocation = vboxWddmAllocationCreateFromResource(pResource, iIndex);
2016 Assert(pAllocation);
2017 if (pAllocation)
2018 {
2019 pAllocationInfo->pPrivateDriverData = NULL;
2020 pAllocationInfo->PrivateDriverDataSize = 0;
2021 pAllocationInfo->Alignment = 0;
2022 pAllocationInfo->PitchAlignedSize = 0;
2023 pAllocationInfo->HintedBank.Value = 0;
2024 pAllocationInfo->PreferredSegment.Value = 0;
2025 pAllocationInfo->SupportedReadSegmentSet = 1;
2026 pAllocationInfo->SupportedWriteSegmentSet = 1;
2027 pAllocationInfo->EvictionSegmentSet = 0;
2028 pAllocationInfo->MaximumRenamingListLength = 0;
2029 pAllocationInfo->hAllocation = pAllocation;
2030 pAllocationInfo->Flags.Value = 0;
2031 pAllocationInfo->pAllocationUsageHint = NULL;
2032 pAllocationInfo->AllocationPriority = D3DDDI_ALLOCATIONPRIORITY_NORMAL;
2033
2034 pAllocation->enmType = pAllocInfo->enmType;
2035 pAllocation->AllocData.Addr.SegmentId = 0;
2036 pAllocation->AllocData.Addr.offVram = VBOXVIDEOOFFSET_VOID;
2037 pAllocation->bVisible = FALSE;
2038 pAllocation->bAssigned = FALSE;
2039 KeInitializeSpinLock(&pAllocation->OpenLock);
2040 InitializeListHead(&pAllocation->OpenList);
2041
2042 switch (pAllocInfo->enmType)
2043 {
2044 case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
2045 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
2046 case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
2047 case VBOXWDDM_ALLOC_TYPE_STD_STAGINGSURFACE:
2048 {
2049 pAllocation->fRcFlags = pAllocInfo->fFlags;
2050 pAllocation->AllocData.SurfDesc = pAllocInfo->SurfDesc;
2051 pAllocation->AllocData.hostID = pAllocInfo->hostID;
2052
2053 pAllocationInfo->Size = pAllocInfo->SurfDesc.cbSize;
2054
2055 switch (pAllocInfo->enmType)
2056 {
2057 case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
2058 break;
2059 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
2060#ifdef VBOX_WITH_VIDEOHWACCEL
2061 if (pAllocInfo->fFlags.Overlay)
2062 {
2063 /* actually we can not "properly" issue create overlay commands to the host here
2064 * because we do not know source VidPn id here, i.e.
2065 * the primary which is supposed to be overlayed,
2066 * however we need to get some info like pitch & size from the host here */
2067 int rc = vboxVhwaHlpGetSurfInfo(pDevExt, pAllocation);
2068 AssertRC(rc);
2069 if (RT_SUCCESS(rc))
2070 {
2071 pAllocationInfo->Flags.Overlay = 1;
2072 pAllocationInfo->Flags.CpuVisible = 1;
2073 pAllocationInfo->Size = pAllocation->AllocData.SurfDesc.cbSize;
2074
2075 pAllocationInfo->AllocationPriority = D3DDDI_ALLOCATIONPRIORITY_HIGH;
2076 }
2077 else
2078 Status = STATUS_UNSUCCESSFUL;
2079 }
2080 else
2081#endif
2082 {
2083 RT_NOREF(pDevExt);
2084
2085 Assert(pAllocation->AllocData.SurfDesc.bpp);
2086 Assert(pAllocation->AllocData.SurfDesc.pitch);
2087 Assert(pAllocation->AllocData.SurfDesc.cbSize);
2088
2089 /*
2090 * Mark the allocation as visible to the CPU so we can
2091 * lock it in the user mode driver for SYSTEM pool allocations.
2092 * See @bugref{8040} for further information.
2093 */
2094 if (!pAllocInfo->fFlags.SharedResource && !pAllocInfo->hostID)
2095 pAllocationInfo->Flags.CpuVisible = 1;
2096
2097 if (pAllocInfo->fFlags.SharedResource)
2098 {
2099 pAllocation->hSharedHandle = (HANDLE)pAllocInfo->hSharedHandle;
2100#if 0
2101 if (pAllocation->hSharedHandle)
2102 {
2103 vboxShRcTreePut(pDevExt, pAllocation);
2104 }
2105#endif
2106 }
2107
2108#if 0
2109 /* Allocation from the CPU invisible second segment does not
2110 * work apparently and actually fails on Vista.
2111 *
2112 * @todo Find out what exactly is wrong.
2113 */
2114// if (pAllocInfo->hostID)
2115 {
2116 pAllocationInfo->SupportedReadSegmentSet = 2;
2117 pAllocationInfo->SupportedWriteSegmentSet = 2;
2118 }
2119#endif
2120 }
2121 break;
2122 case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
2123 case VBOXWDDM_ALLOC_TYPE_STD_STAGINGSURFACE:
2124 pAllocationInfo->Flags.CpuVisible = 1;
2125 break;
2126 default: AssertFailedBreak(); /* Shut up MSC.*/
2127 }
2128
2129 if (Status == STATUS_SUCCESS)
2130 {
2131 pAllocation->UsageHint.Version = 0;
2132 pAllocation->UsageHint.v1.Flags.Value = 0;
2133 pAllocation->UsageHint.v1.Format = pAllocInfo->SurfDesc.format;
2134 pAllocation->UsageHint.v1.SwizzledFormat = 0;
2135 pAllocation->UsageHint.v1.ByteOffset = 0;
2136 pAllocation->UsageHint.v1.Width = pAllocation->AllocData.SurfDesc.width;
2137 pAllocation->UsageHint.v1.Height = pAllocation->AllocData.SurfDesc.height;
2138 pAllocation->UsageHint.v1.Pitch = pAllocation->AllocData.SurfDesc.pitch;
2139 pAllocation->UsageHint.v1.Depth = 0;
2140 pAllocation->UsageHint.v1.SlicePitch = 0;
2141
2142 Assert(!pAllocationInfo->pAllocationUsageHint);
2143 pAllocationInfo->pAllocationUsageHint = &pAllocation->UsageHint;
2144 }
2145
2146 break;
2147 }
2148 case VBOXWDDM_ALLOC_TYPE_UMD_HGSMI_BUFFER:
2149 {
2150 pAllocationInfo->Size = pAllocInfo->cbBuffer;
2151 pAllocation->fUhgsmiType = pAllocInfo->fUhgsmiType;
2152 pAllocation->AllocData.SurfDesc.cbSize = pAllocInfo->cbBuffer;
2153 pAllocationInfo->Flags.CpuVisible = 1;
2154// pAllocationInfo->Flags.SynchronousPaging = 1;
2155 pAllocationInfo->AllocationPriority = D3DDDI_ALLOCATIONPRIORITY_MAXIMUM;
2156 break;
2157 }
2158
2159 default:
2160 LOGREL(("ERROR: invalid alloc info type(%d)", pAllocInfo->enmType));
2161 AssertBreakpoint();
2162 Status = STATUS_INVALID_PARAMETER;
2163 break;
2164
2165 }
2166
2167 if (Status != STATUS_SUCCESS)
2168 vboxWddmAllocationDeleteFromResource(pResource, pAllocation);
2169 }
2170 else
2171 {
2172 LOGREL(("ERROR: failed to create allocation description"));
2173 Status = STATUS_NO_MEMORY;
2174 }
2175
2176 }
2177 else
2178 {
2179 LOGREL(("ERROR: PrivateDriverDataSize(%d) less than header size(%d)", pAllocationInfo->PrivateDriverDataSize, sizeof (VBOXWDDM_ALLOCINFO)));
2180 Status = STATUS_INVALID_PARAMETER;
2181 }
2182
2183 return Status;
2184}
2185
2186NTSTATUS APIENTRY DxgkDdiCreateAllocation(
2187 CONST HANDLE hAdapter,
2188 DXGKARG_CREATEALLOCATION* pCreateAllocation)
2189{
2190 /* DxgkDdiCreateAllocation should be made pageable. */
2191 PAGED_CODE();
2192
2193 LOGF(("ENTER, context(0x%x)", hAdapter));
2194
2195 vboxVDbgBreakFv();
2196
2197 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
2198 NTSTATUS Status = STATUS_SUCCESS;
2199 PVBOXWDDM_RESOURCE pResource = NULL;
2200
2201 if (pCreateAllocation->PrivateDriverDataSize)
2202 {
2203 Assert(pCreateAllocation->PrivateDriverDataSize == sizeof (VBOXWDDM_RCINFO));
2204 Assert(pCreateAllocation->pPrivateDriverData);
2205 if (pCreateAllocation->PrivateDriverDataSize < sizeof (VBOXWDDM_RCINFO))
2206 {
2207 WARN(("invalid private data size (%d)", pCreateAllocation->PrivateDriverDataSize));
2208 return STATUS_INVALID_PARAMETER;
2209 }
2210
2211 PVBOXWDDM_RCINFO pRcInfo = (PVBOXWDDM_RCINFO)pCreateAllocation->pPrivateDriverData;
2212// Assert(pRcInfo->RcDesc.VidPnSourceId < VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
2213 if (pRcInfo->cAllocInfos != pCreateAllocation->NumAllocations)
2214 {
2215 WARN(("invalid number of allocations passed in, (%d), expected (%d)", pRcInfo->cAllocInfos, pCreateAllocation->NumAllocations));
2216 return STATUS_INVALID_PARAMETER;
2217 }
2218
2219 /* a check to ensure we do not get the allocation size which is too big to overflow the 32bit value */
2220 if (VBOXWDDM_TRAILARRAY_MAXELEMENTSU32(VBOXWDDM_RESOURCE, aAllocations) < pRcInfo->cAllocInfos)
2221 {
2222 WARN(("number of allocations passed too big (%d), max is (%d)", pRcInfo->cAllocInfos, VBOXWDDM_TRAILARRAY_MAXELEMENTSU32(VBOXWDDM_RESOURCE, aAllocations)));
2223 return STATUS_INVALID_PARAMETER;
2224 }
2225
2226 pResource = (PVBOXWDDM_RESOURCE)vboxWddmMemAllocZero(RT_UOFFSETOF_DYN(VBOXWDDM_RESOURCE, aAllocations[pRcInfo->cAllocInfos]));
2227 if (!pResource)
2228 {
2229 WARN(("vboxWddmMemAllocZero failed for (%d) allocations", pRcInfo->cAllocInfos));
2230 return STATUS_NO_MEMORY;
2231 }
2232
2233 pResource->cRefs = 1;
2234 pResource->cAllocations = pRcInfo->cAllocInfos;
2235 pResource->fFlags = pRcInfo->fFlags;
2236 pResource->RcDesc = pRcInfo->RcDesc;
2237 }
2238
2239
2240 for (UINT i = 0; i < pCreateAllocation->NumAllocations; ++i)
2241 {
2242 Status = vboxWddmAllocationCreate(pDevExt, pResource, i, &pCreateAllocation->pAllocationInfo[i]);
2243 if (Status != STATUS_SUCCESS)
2244 {
2245 WARN(("vboxWddmAllocationCreate(%d) failed, Status(0x%x)", i, Status));
2246 /* note: i-th allocation is expected to be cleared in a fail handling code above */
2247 for (UINT j = 0; j < i; ++j)
2248 {
2249 PVBOXWDDM_ALLOCATION pAllocation = (PVBOXWDDM_ALLOCATION)pCreateAllocation->pAllocationInfo[j].hAllocation;
2250 vboxWddmAllocationCleanup(pDevExt, pAllocation);
2251 vboxWddmAllocationDestroy(pAllocation);
2252 }
2253 break;
2254 }
2255 }
2256
2257 if (Status == STATUS_SUCCESS)
2258 {
2259 pCreateAllocation->hResource = pResource;
2260 }
2261 else
2262 {
2263 if (pResource)
2264 vboxWddmResourceRelease(pResource);
2265 }
2266
2267 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
2268
2269 return Status;
2270}
2271
2272NTSTATUS
2273APIENTRY
2274DxgkDdiDestroyAllocation(
2275 CONST HANDLE hAdapter,
2276 CONST DXGKARG_DESTROYALLOCATION* pDestroyAllocation)
2277{
2278 /* DxgkDdiDestroyAllocation should be made pageable. */
2279 PAGED_CODE();
2280
2281 LOGF(("ENTER, context(0x%x)", hAdapter));
2282
2283 vboxVDbgBreakFv();
2284
2285 NTSTATUS Status = STATUS_SUCCESS;
2286
2287 PVBOXWDDM_RESOURCE pRc = (PVBOXWDDM_RESOURCE)pDestroyAllocation->hResource;
2288 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
2289
2290 if (pRc)
2291 {
2292 Assert(pRc->cAllocations == pDestroyAllocation->NumAllocations);
2293 }
2294
2295 for (UINT i = 0; i < pDestroyAllocation->NumAllocations; ++i)
2296 {
2297 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pDestroyAllocation->pAllocationList[i];
2298 Assert(pAlloc->pResource == pRc);
2299 vboxWddmAllocationCleanupAssignment(pDevExt, pAlloc);
2300 /* wait for all current allocation-related ops are completed */
2301 vboxWddmAllocationCleanup(pDevExt, pAlloc);
2302 vboxWddmAllocationDestroy(pAlloc);
2303 }
2304
2305 if (pRc)
2306 {
2307 /* wait for all current resource-related ops are completed */
2308 vboxWddmResourceWaitDereference(pRc);
2309 vboxWddmResourceRelease(pRc);
2310 }
2311
2312 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
2313
2314 return Status;
2315}
2316
2317/**
2318 * DxgkDdiDescribeAllocation
2319 */
2320NTSTATUS
2321APIENTRY
2322DxgkDdiDescribeAllocation(
2323 CONST HANDLE hAdapter,
2324 DXGKARG_DESCRIBEALLOCATION* pDescribeAllocation)
2325{
2326 RT_NOREF(hAdapter);
2327// LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
2328
2329 vboxVDbgBreakFv();
2330
2331 PVBOXWDDM_ALLOCATION pAllocation = (PVBOXWDDM_ALLOCATION)pDescribeAllocation->hAllocation;
2332 pDescribeAllocation->Width = pAllocation->AllocData.SurfDesc.width;
2333 pDescribeAllocation->Height = pAllocation->AllocData.SurfDesc.height;
2334 pDescribeAllocation->Format = pAllocation->AllocData.SurfDesc.format;
2335 memset (&pDescribeAllocation->MultisampleMethod, 0, sizeof (pDescribeAllocation->MultisampleMethod));
2336 pDescribeAllocation->RefreshRate.Numerator = g_RefreshRate * 1000;
2337 pDescribeAllocation->RefreshRate.Denominator = 1000;
2338 pDescribeAllocation->PrivateDriverFormatAttribute = 0;
2339
2340// LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
2341
2342 return STATUS_SUCCESS;
2343}
2344
2345/**
2346 * DxgkDdiGetStandardAllocationDriverData
2347 */
2348NTSTATUS
2349APIENTRY
2350DxgkDdiGetStandardAllocationDriverData(
2351 CONST HANDLE hAdapter,
2352 DXGKARG_GETSTANDARDALLOCATIONDRIVERDATA* pGetStandardAllocationDriverData)
2353{
2354 RT_NOREF(hAdapter);
2355 /* DxgkDdiGetStandardAllocationDriverData should be made pageable. */
2356 PAGED_CODE();
2357
2358 LOGF(("ENTER, context(0x%x)", hAdapter));
2359
2360 vboxVDbgBreakFv();
2361
2362 NTSTATUS Status = STATUS_SUCCESS;
2363 PVBOXWDDM_ALLOCINFO pAllocInfo = NULL;
2364
2365 switch (pGetStandardAllocationDriverData->StandardAllocationType)
2366 {
2367 case D3DKMDT_STANDARDALLOCATION_SHAREDPRIMARYSURFACE:
2368 {
2369 LOGF(("D3DKMDT_STANDARDALLOCATION_SHAREDPRIMARYSURFACE"));
2370 if(pGetStandardAllocationDriverData->pAllocationPrivateDriverData)
2371 {
2372 pAllocInfo = (PVBOXWDDM_ALLOCINFO)pGetStandardAllocationDriverData->pAllocationPrivateDriverData;
2373 memset (pAllocInfo, 0, sizeof (VBOXWDDM_ALLOCINFO));
2374 pAllocInfo->enmType = VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE;
2375 pAllocInfo->SurfDesc.width = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Width;
2376 pAllocInfo->SurfDesc.height = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Height;
2377 pAllocInfo->SurfDesc.format = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Format;
2378 pAllocInfo->SurfDesc.bpp = vboxWddmCalcBitsPerPixel(pAllocInfo->SurfDesc.format);
2379 pAllocInfo->SurfDesc.pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Width, pAllocInfo->SurfDesc.format);
2380 pAllocInfo->SurfDesc.cbSize = vboxWddmCalcSize(pAllocInfo->SurfDesc.pitch, pAllocInfo->SurfDesc.height, pAllocInfo->SurfDesc.format);
2381 pAllocInfo->SurfDesc.depth = 0;
2382 pAllocInfo->SurfDesc.slicePitch = 0;
2383 pAllocInfo->SurfDesc.RefreshRate = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->RefreshRate;
2384 pAllocInfo->SurfDesc.VidPnSourceId = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->VidPnSourceId;
2385 }
2386 pGetStandardAllocationDriverData->AllocationPrivateDriverDataSize = sizeof (VBOXWDDM_ALLOCINFO);
2387
2388 pGetStandardAllocationDriverData->ResourcePrivateDriverDataSize = 0;
2389 break;
2390 }
2391 case D3DKMDT_STANDARDALLOCATION_SHADOWSURFACE:
2392 {
2393 LOGF(("D3DKMDT_STANDARDALLOCATION_SHADOWSURFACE"));
2394 UINT bpp = vboxWddmCalcBitsPerPixel(pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format);
2395 Assert(bpp);
2396 if (bpp != 0)
2397 {
2398 UINT Pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Width, pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format);
2399 pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Pitch = Pitch;
2400
2401 /** @todo need [d/q]word align?? */
2402
2403 if (pGetStandardAllocationDriverData->pAllocationPrivateDriverData)
2404 {
2405 pAllocInfo = (PVBOXWDDM_ALLOCINFO)pGetStandardAllocationDriverData->pAllocationPrivateDriverData;
2406 pAllocInfo->enmType = VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE;
2407 pAllocInfo->SurfDesc.width = pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Width;
2408 pAllocInfo->SurfDesc.height = pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Height;
2409 pAllocInfo->SurfDesc.format = pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format;
2410 pAllocInfo->SurfDesc.bpp = vboxWddmCalcBitsPerPixel(pAllocInfo->SurfDesc.format);
2411 pAllocInfo->SurfDesc.pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Width, pAllocInfo->SurfDesc.format);
2412 pAllocInfo->SurfDesc.cbSize = vboxWddmCalcSize(pAllocInfo->SurfDesc.pitch, pAllocInfo->SurfDesc.height, pAllocInfo->SurfDesc.format);
2413 pAllocInfo->SurfDesc.depth = 0;
2414 pAllocInfo->SurfDesc.slicePitch = 0;
2415 pAllocInfo->SurfDesc.RefreshRate.Numerator = 0;
2416 pAllocInfo->SurfDesc.RefreshRate.Denominator = 1000;
2417 pAllocInfo->SurfDesc.VidPnSourceId = D3DDDI_ID_UNINITIALIZED;
2418
2419 pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Pitch = pAllocInfo->SurfDesc.pitch;
2420 }
2421 pGetStandardAllocationDriverData->AllocationPrivateDriverDataSize = sizeof (VBOXWDDM_ALLOCINFO);
2422
2423 pGetStandardAllocationDriverData->ResourcePrivateDriverDataSize = 0;
2424 }
2425 else
2426 {
2427 LOGREL(("Invalid format (%d)", pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format));
2428 Status = STATUS_INVALID_PARAMETER;
2429 }
2430 break;
2431 }
2432 case D3DKMDT_STANDARDALLOCATION_STAGINGSURFACE:
2433 {
2434 LOGF(("D3DKMDT_STANDARDALLOCATION_STAGINGSURFACE"));
2435 if(pGetStandardAllocationDriverData->pAllocationPrivateDriverData)
2436 {
2437 pAllocInfo = (PVBOXWDDM_ALLOCINFO)pGetStandardAllocationDriverData->pAllocationPrivateDriverData;
2438 pAllocInfo->enmType = VBOXWDDM_ALLOC_TYPE_STD_STAGINGSURFACE;
2439 pAllocInfo->SurfDesc.width = pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Width;
2440 pAllocInfo->SurfDesc.height = pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Height;
2441 pAllocInfo->SurfDesc.format = D3DDDIFMT_X8R8G8B8; /* staging has always always D3DDDIFMT_X8R8G8B8 */
2442 pAllocInfo->SurfDesc.bpp = vboxWddmCalcBitsPerPixel(pAllocInfo->SurfDesc.format);
2443 pAllocInfo->SurfDesc.pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Width, pAllocInfo->SurfDesc.format);
2444 pAllocInfo->SurfDesc.cbSize = vboxWddmCalcSize(pAllocInfo->SurfDesc.pitch, pAllocInfo->SurfDesc.height, pAllocInfo->SurfDesc.format);
2445 pAllocInfo->SurfDesc.depth = 0;
2446 pAllocInfo->SurfDesc.slicePitch = 0;
2447 pAllocInfo->SurfDesc.RefreshRate.Numerator = 0;
2448 pAllocInfo->SurfDesc.RefreshRate.Denominator = 1000;
2449 pAllocInfo->SurfDesc.VidPnSourceId = D3DDDI_ID_UNINITIALIZED;
2450
2451 pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Pitch = pAllocInfo->SurfDesc.pitch;
2452 }
2453 pGetStandardAllocationDriverData->AllocationPrivateDriverDataSize = sizeof (VBOXWDDM_ALLOCINFO);
2454
2455 pGetStandardAllocationDriverData->ResourcePrivateDriverDataSize = 0;
2456 break;
2457 }
2458//#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
2459// case D3DKMDT_STANDARDALLOCATION_GDISURFACE:
2460//# error port to Win7 DDI
2461// break;
2462//#endif
2463 default:
2464 LOGREL(("Invalid allocation type (%d)", pGetStandardAllocationDriverData->StandardAllocationType));
2465 Status = STATUS_INVALID_PARAMETER;
2466 break;
2467 }
2468
2469 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
2470
2471 return Status;
2472}
2473
2474NTSTATUS
2475APIENTRY
2476DxgkDdiAcquireSwizzlingRange(
2477 CONST HANDLE hAdapter,
2478 DXGKARG_ACQUIRESWIZZLINGRANGE* pAcquireSwizzlingRange)
2479{
2480 RT_NOREF(hAdapter, pAcquireSwizzlingRange);
2481 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
2482
2483 AssertBreakpoint();
2484
2485 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
2486
2487 return STATUS_SUCCESS;
2488}
2489
2490NTSTATUS
2491APIENTRY
2492DxgkDdiReleaseSwizzlingRange(
2493 CONST HANDLE hAdapter,
2494 CONST DXGKARG_RELEASESWIZZLINGRANGE* pReleaseSwizzlingRange)
2495{
2496 RT_NOREF(hAdapter, pReleaseSwizzlingRange);
2497 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
2498
2499 AssertBreakpoint();
2500
2501 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
2502
2503 return STATUS_SUCCESS;
2504}
2505
2506typedef struct VBOXWDDM_CALL_ISR
2507{
2508 PVBOXMP_DEVEXT pDevExt;
2509 ULONG MessageNumber;
2510} VBOXWDDM_CALL_ISR, *PVBOXWDDM_CALL_ISR;
2511
2512static BOOLEAN vboxWddmCallIsrCb(PVOID Context)
2513{
2514 PVBOXWDDM_CALL_ISR pdc = (PVBOXWDDM_CALL_ISR)Context;
2515 PVBOXMP_DEVEXT pDevExt = pdc->pDevExt;
2516 if (pDevExt->fCmdVbvaEnabled)
2517 {
2518#ifdef DEBUG_sunlover
2519 /** @todo Remove VBOX_WITH_VIDEOHWACCEL code, because the host does not support it anymore. */
2520 AssertFailed(); /* Should not be here, because this is not used with 3D gallium driver. */
2521#endif
2522 return FALSE;
2523 }
2524 return DxgkDdiInterruptRoutineLegacy(pDevExt, pdc->MessageNumber);
2525}
2526
2527NTSTATUS vboxWddmCallIsr(PVBOXMP_DEVEXT pDevExt)
2528{
2529 VBOXWDDM_CALL_ISR context;
2530 context.pDevExt = pDevExt;
2531 context.MessageNumber = 0;
2532 BOOLEAN bRet;
2533 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
2534 pDevExt->u.primary.DxgkInterface.DeviceHandle,
2535 vboxWddmCallIsrCb,
2536 &context,
2537 0, /* IN ULONG MessageNumber */
2538 &bRet);
2539 AssertNtStatusSuccess(Status);
2540 return Status;
2541}
2542
2543
2544NTSTATUS
2545APIENTRY
2546DxgkDdiSetPalette(
2547 CONST HANDLE hAdapter,
2548 CONST DXGKARG_SETPALETTE* pSetPalette
2549 )
2550{
2551 RT_NOREF(hAdapter, pSetPalette);
2552 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
2553
2554 AssertBreakpoint();
2555 /** @todo fixme: implement */
2556
2557 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
2558
2559 return STATUS_SUCCESS;
2560}
2561
2562/** Find which area of a 32 bit mouse pointer bitmap is actually used.
2563 * Zero pixels on the right and the bottom of the bitmap are considered unused.
2564 *
2565 * @param pPixels The bitmap.
2566 * @param Pitch The bitmap scanline size in bytes.
2567 * @param Width The bitmap width.
2568 * @param Height The bitmap height.
2569 * @param piMaxFilledPixel Where to store the maximum index of non-zero pixel within a scanline.
2570 * @param piMaxFilledScanline Where to store the zero based index of the last scanline with non-zero pixels.
2571 */
2572static void vboxWddmPointerFindDimensionsColor(void const *pPixels, UINT Pitch, UINT Width, UINT Height,
2573 LONG *piMaxFilledPixel, LONG *piMaxFilledScanline)
2574{
2575 /* Windows always uses the maximum pointer size VBOXWDDM_C_POINTER_MAX_*
2576 * Exclude zero pixels (which are transparent anyway) from the right and the bottom of the bitmap.
2577 */
2578 DWORD const *pdwScanline = (DWORD *)pPixels;
2579 LONG iMaxFilledScanline = -1;
2580 LONG iMaxFilledPixel = -1;
2581 for (ULONG y = 0; y < Height; ++y)
2582 {
2583 LONG iLastFilledPixel = -1;
2584 for (ULONG x = 0; x < Width; ++x)
2585 {
2586 if (pdwScanline[x])
2587 iLastFilledPixel = x;
2588 }
2589
2590 iMaxFilledPixel = RT_MAX(iMaxFilledPixel, iLastFilledPixel);
2591
2592 if (iLastFilledPixel >= 0)
2593 {
2594 /* Scanline contains non-zero pixels. */
2595 iMaxFilledScanline = y;
2596 }
2597
2598 pdwScanline = (DWORD *)((uint8_t *)pdwScanline + Pitch);
2599 }
2600
2601 *piMaxFilledPixel = iMaxFilledPixel;
2602 *piMaxFilledScanline = iMaxFilledScanline;
2603}
2604
2605/** Find which area of a 1 bit AND/XOR mask bitmap is actually used, i.e. filled with actual data.
2606 * For the AND mask the bytes with a value 0xff on the right and the bottom of the bitmap are considered unused.
2607 * For the XOR mask the blank value is 0x00.
2608 *
2609 * @param pPixels The 1bit bitmap.
2610 * @param Pitch The 1bit bitmap scanline size in bytes.
2611 * @param Width The bitmap width.
2612 * @param Height The bitmap height.
2613 * @param Blank The value of the unused bytes in the supplied bitmap.
2614 * @param piMaxFilledPixel Where to store the maximum index of a filled pixel within a scanline.
2615 * @param piMaxFilledScanline Where to store the zero based index of the last scanline with filled pixels.
2616 */
2617static void vboxWddmPointerFindDimensionsMono(void const *pPixels, UINT Pitch, UINT Width, UINT Height, BYTE Blank,
2618 LONG *piMaxFilledPixel, LONG *piMaxFilledScanline)
2619{
2620 /* Windows always uses the maximum pointer size VBOXWDDM_C_POINTER_MAX_*
2621 * Exclude the blank pixels (which are transparent anyway) from the right and the bottom of the bitmap.
2622 */
2623 BYTE const *pbScanline = (BYTE *)pPixels;
2624 LONG iMaxFilledScanline = -1;
2625 LONG iMaxFilledByte = -1;
2626 for (ULONG y = 0; y < Height; ++y)
2627 {
2628 LONG iLastFilledByte = -1;
2629 for (ULONG x = 0; x < Width / 8; ++x)
2630 {
2631 if (pbScanline[x] != Blank)
2632 iLastFilledByte = x;
2633 }
2634
2635 iMaxFilledByte = RT_MAX(iMaxFilledByte, iLastFilledByte);
2636
2637 if (iLastFilledByte >= 0)
2638 {
2639 /* Scanline contains filled pixels. */
2640 iMaxFilledScanline = y;
2641 }
2642
2643 pbScanline += Pitch;
2644 }
2645
2646 *piMaxFilledPixel = iMaxFilledByte * 8;
2647 *piMaxFilledScanline = iMaxFilledScanline;
2648}
2649
2650/** Adjust the width and the height of the mouse pointer bitmap.
2651 * See comments in the function for the adjustment criteria.
2652 *
2653 * @param iMaxX The index of the rightmost pixel which we want to keep.
2654 * @param iMaxY The index of the bottom-most pixel which we want to keep.
2655 * @param XHot The mouse pointer hot spot.
2656 * @param YHot The mouse pointer hot spot.
2657 * @param pWidth Where to store the bitmap width.
2658 * @param pHeight Where to store the bitmap height.
2659 */
2660static void vboxWddmPointerAdjustDimensions(LONG iMaxX, LONG iMaxY, UINT XHot, UINT YHot,
2661 ULONG *pWidth, ULONG *pHeight)
2662{
2663 /* Both input parameters are zero based indexes, add 1 to get a width and a height. */
2664 ULONG W = iMaxX + 1;
2665 ULONG H = iMaxY + 1;
2666
2667 /* Always include the hotspot point. */
2668 W = RT_MAX(XHot, W);
2669 H = RT_MAX(YHot, H);
2670
2671 /* Align to 8 pixels, because the XOR/AND pointers are aligned like that.
2672 * The AND mask has one bit per pixel with 8 bits per byte.
2673 * In case the host can't deal with unaligned data.
2674 */
2675 W = RT_ALIGN_T(W, 8, ULONG);
2676 H = RT_ALIGN_T(H, 8, ULONG);
2677
2678 /* Do not send bitmaps with zero dimensions. Actually make the min size 32x32. */
2679 W = RT_MAX(32, W);
2680 H = RT_MAX(32, H);
2681
2682 /* Make it square. Some hosts are known to require square pointers. */
2683 W = RT_MAX(W, H);
2684 H = W;
2685
2686 /* Do not exceed the supported size.
2687 * Actually this should not be necessary because Windows never creates such pointers.
2688 */
2689 W = RT_MIN(W, VBOXWDDM_C_POINTER_MAX_WIDTH);
2690 H = RT_MIN(H, VBOXWDDM_C_POINTER_MAX_HEIGHT);
2691
2692 *pWidth = W;
2693 *pHeight = H;
2694}
2695
2696BOOL vboxWddmPointerCopyColorData(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVIDEO_POINTER_ATTRIBUTES pPointerAttributes,
2697 bool fDwordAlignScanlines)
2698{
2699 ULONG srcMaskW, srcMaskH;
2700 ULONG dstBytesPerLine;
2701 ULONG x, y;
2702 BYTE *pSrc, *pDst, bit;
2703
2704 /* Windows always uses the maximum pointer size VBOXWDDM_C_POINTER_MAX_*
2705 * Exclude zero pixels (which are transparent anyway) from the right and the bottom of the bitmap.
2706 */
2707 LONG iMaxFilledPixel;
2708 LONG iMaxFilledScanline;
2709 vboxWddmPointerFindDimensionsColor(pSetPointerShape->pPixels, pSetPointerShape->Pitch,
2710 pSetPointerShape->Width, pSetPointerShape->Height,
2711 &iMaxFilledPixel, &iMaxFilledScanline);
2712
2713 vboxWddmPointerAdjustDimensions(iMaxFilledPixel, iMaxFilledScanline,
2714 pSetPointerShape->XHot, pSetPointerShape->YHot,
2715 &srcMaskW, &srcMaskH);
2716
2717 pPointerAttributes->Width = srcMaskW;
2718 pPointerAttributes->Height = srcMaskH;
2719 pPointerAttributes->WidthInBytes = pPointerAttributes->Width * 4;
2720
2721 /* cnstruct and mask from alpha color channel */
2722 pSrc = (PBYTE)pSetPointerShape->pPixels;
2723 pDst = pPointerAttributes->Pixels;
2724 dstBytesPerLine = (pPointerAttributes->Width+7)/8;
2725 if (fDwordAlignScanlines)
2726 dstBytesPerLine = RT_ALIGN_T(dstBytesPerLine, 4, ULONG);
2727
2728 /* sanity check */
2729 uint32_t cbData = RT_ALIGN_T(dstBytesPerLine*pPointerAttributes->Height, 4, ULONG)+
2730 pPointerAttributes->Height*pPointerAttributes->WidthInBytes;
2731 uint32_t cbPointerAttributes = RT_UOFFSETOF_DYN(VIDEO_POINTER_ATTRIBUTES, Pixels[cbData]);
2732 Assert(VBOXWDDM_POINTER_ATTRIBUTES_SIZE >= cbPointerAttributes);
2733 if (VBOXWDDM_POINTER_ATTRIBUTES_SIZE < cbPointerAttributes)
2734 {
2735 LOGREL(("VBOXWDDM_POINTER_ATTRIBUTES_SIZE(%d) < cbPointerAttributes(%d)", VBOXWDDM_POINTER_ATTRIBUTES_SIZE, cbPointerAttributes));
2736 return FALSE;
2737 }
2738
2739 memset(pDst, 0xFF, dstBytesPerLine*pPointerAttributes->Height);
2740 for (y=0; y<pPointerAttributes->Height; ++y)
2741 {
2742 for (x=0, bit=7; x<pPointerAttributes->Width; ++x, --bit)
2743 {
2744 if (0xFF==bit) bit=7;
2745
2746 if (pSrc[y*pSetPointerShape->Pitch + x*4 + 3] > 0x7F)
2747 {
2748 pDst[y*dstBytesPerLine + x/8] &= ~RT_BIT(bit);
2749 }
2750 }
2751 }
2752
2753 /* copy 32bpp to XOR DIB, it start in pPointerAttributes->Pixels should be 4bytes aligned */
2754 pSrc = (BYTE*)pSetPointerShape->pPixels;
2755 pDst = pPointerAttributes->Pixels + RT_ALIGN_T(dstBytesPerLine*pPointerAttributes->Height, 4, ULONG);
2756 dstBytesPerLine = pPointerAttributes->Width * 4;
2757
2758 for (y=0; y<pPointerAttributes->Height; ++y)
2759 {
2760 memcpy(pDst+y*dstBytesPerLine, pSrc+y*pSetPointerShape->Pitch, dstBytesPerLine);
2761 }
2762
2763 return TRUE;
2764}
2765
2766BOOL vboxWddmPointerCopyMonoData(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVIDEO_POINTER_ATTRIBUTES pPointerAttributes,
2767 bool fDwordAlignScanlines)
2768{
2769 ULONG srcMaskW, srcMaskH;
2770 ULONG dstBytesPerLine;
2771 ULONG x, y;
2772 BYTE *pSrc, *pDst, bit;
2773
2774 /* Windows always uses the maximum pointer size VBOXWDDM_C_POINTER_MAX_*
2775 * Exclude unused pixels (which are transparent anyway) from the right and the bottom of the bitmap.
2776 */
2777 LONG iMaxFilledPixelAND;
2778 LONG iMaxFilledScanlineAND;
2779 vboxWddmPointerFindDimensionsMono(pSetPointerShape->pPixels, pSetPointerShape->Pitch,
2780 pSetPointerShape->Width, pSetPointerShape->Height, 0xff,
2781 &iMaxFilledPixelAND, &iMaxFilledScanlineAND);
2782
2783 LONG iMaxFilledPixelXOR;
2784 LONG iMaxFilledScanlineXOR;
2785 vboxWddmPointerFindDimensionsMono((BYTE *)pSetPointerShape->pPixels + pSetPointerShape->Height * pSetPointerShape->Pitch,
2786 pSetPointerShape->Pitch,
2787 pSetPointerShape->Width, pSetPointerShape->Height, 0x00,
2788 &iMaxFilledPixelXOR, &iMaxFilledScanlineXOR);
2789
2790 LONG iMaxFilledPixel = RT_MAX(iMaxFilledPixelAND, iMaxFilledPixelXOR);
2791 LONG iMaxFilledScanline = RT_MAX(iMaxFilledScanlineAND, iMaxFilledScanlineXOR);
2792
2793 vboxWddmPointerAdjustDimensions(iMaxFilledPixel, iMaxFilledScanline,
2794 pSetPointerShape->XHot, pSetPointerShape->YHot,
2795 &srcMaskW, &srcMaskH);
2796
2797 pPointerAttributes->Width = srcMaskW;
2798 pPointerAttributes->Height = srcMaskH;
2799 pPointerAttributes->WidthInBytes = pPointerAttributes->Width * 4;
2800
2801 /* copy AND mask */
2802 pSrc = (PBYTE)pSetPointerShape->pPixels;
2803 pDst = pPointerAttributes->Pixels;
2804 dstBytesPerLine = (pPointerAttributes->Width+7)/8;
2805 if (fDwordAlignScanlines)
2806 dstBytesPerLine = RT_ALIGN_T(dstBytesPerLine, 4, ULONG);
2807
2808 for (y=0; y<pPointerAttributes->Height; ++y)
2809 {
2810 memcpy(pDst+y*dstBytesPerLine, pSrc+y*pSetPointerShape->Pitch, dstBytesPerLine);
2811 }
2812
2813 /* convert XOR mask to RGB0 DIB, it start in pPointerAttributes->Pixels should be 4bytes aligned */
2814 pSrc = (BYTE*)pSetPointerShape->pPixels + pSetPointerShape->Height*pSetPointerShape->Pitch;
2815 pDst = pPointerAttributes->Pixels + RT_ALIGN_T(dstBytesPerLine*pPointerAttributes->Height, 4, ULONG);
2816 dstBytesPerLine = pPointerAttributes->Width * 4;
2817
2818 for (y=0; y<pPointerAttributes->Height; ++y)
2819 {
2820 for (x=0, bit=7; x<pPointerAttributes->Width; ++x, --bit)
2821 {
2822 if (0xFF==bit) bit=7;
2823
2824 *(ULONG*)&pDst[y*dstBytesPerLine+x*4] = (pSrc[y*pSetPointerShape->Pitch+x/8] & RT_BIT(bit)) ? 0x00FFFFFF : 0;
2825 }
2826 }
2827
2828 return TRUE;
2829}
2830
2831static BOOLEAN vboxVddmPointerShapeToAttributes(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVBOXWDDM_POINTER_INFO pPointerInfo,
2832 bool fDwordAlignScanlines)
2833{
2834 PVIDEO_POINTER_ATTRIBUTES pPointerAttributes = &pPointerInfo->Attributes.data;
2835 /* pPointerAttributes maintains the visibility state, clear all except visibility */
2836 pPointerAttributes->Enable &= VBOX_MOUSE_POINTER_VISIBLE;
2837
2838 Assert(pSetPointerShape->Flags.Value == 1 || pSetPointerShape->Flags.Value == 2);
2839 if (pSetPointerShape->Flags.Color)
2840 {
2841 if (vboxWddmPointerCopyColorData(pSetPointerShape, pPointerAttributes, fDwordAlignScanlines))
2842 {
2843 pPointerAttributes->Flags = VIDEO_MODE_COLOR_POINTER;
2844 pPointerAttributes->Enable |= VBOX_MOUSE_POINTER_ALPHA;
2845 }
2846 else
2847 {
2848 LOGREL(("vboxWddmPointerCopyColorData failed"));
2849 AssertBreakpoint();
2850 return FALSE;
2851 }
2852
2853 }
2854 else if (pSetPointerShape->Flags.Monochrome)
2855 {
2856 if (vboxWddmPointerCopyMonoData(pSetPointerShape, pPointerAttributes, fDwordAlignScanlines))
2857 {
2858 pPointerAttributes->Flags = VIDEO_MODE_MONO_POINTER;
2859 }
2860 else
2861 {
2862 LOGREL(("vboxWddmPointerCopyMonoData failed"));
2863 AssertBreakpoint();
2864 return FALSE;
2865 }
2866 }
2867 else
2868 {
2869 LOGREL(("unsupported pointer type Flags.Value(0x%x)", pSetPointerShape->Flags.Value));
2870 AssertBreakpoint();
2871 return FALSE;
2872 }
2873
2874 pPointerAttributes->Enable |= VBOX_MOUSE_POINTER_SHAPE;
2875
2876 /*
2877 * The hot spot coordinates and alpha flag will be encoded in the pPointerAttributes::Enable field.
2878 * High word will contain hot spot info and low word - flags.
2879 */
2880 pPointerAttributes->Enable |= (pSetPointerShape->YHot & 0xFF) << 24;
2881 pPointerAttributes->Enable |= (pSetPointerShape->XHot & 0xFF) << 16;
2882
2883 return TRUE;
2884}
2885
2886bool vboxWddmUpdatePointerShape(PVBOXMP_DEVEXT pDevExt, PVIDEO_POINTER_ATTRIBUTES pAttrs, uint32_t cbLength)
2887{
2888#ifdef VBOX_WITH_MESA3D
2889 if (pDevExt->enmHwType != VBOXVIDEO_HWTYPE_VBOX)
2890 {
2891 NTSTATUS Status = STATUS_SUCCESS;
2892
2893 /** @todo Get rid of the unnecesary en-/decode procedure (XPDM legacy). */
2894 uint32_t fFlags = pAttrs->Enable & 0x0000FFFF;
2895 uint32_t xHot = (pAttrs->Enable >> 16) & 0xFF;
2896 uint32_t yHot = (pAttrs->Enable >> 24) & 0xFF;
2897 uint32_t cWidth = pAttrs->Width;
2898 uint32_t cHeight = pAttrs->Height;
2899 uint32_t cbAndMask = 0;
2900 uint32_t cbXorMask = 0;
2901
2902 if (fFlags & VBOX_MOUSE_POINTER_SHAPE)
2903 {
2904 /* Size of the pointer data: sizeof(AND mask) + sizeof(XOR mask) */
2905 /* "Each scanline is padded to a 32-bit boundary." */
2906 cbAndMask = ((((cWidth + 7) / 8) + 3) & ~3) * cHeight;
2907 cbXorMask = cWidth * 4 * cHeight;
2908
2909 /* Send the shape to the host. */
2910 if (fFlags & VBOX_MOUSE_POINTER_ALPHA)
2911 {
2912 void const *pvImage = &pAttrs->Pixels[cbAndMask];
2913 Status = GaDefineAlphaCursor(pDevExt->pGa,
2914 xHot,
2915 yHot,
2916 cWidth,
2917 cHeight,
2918 pvImage,
2919 cbXorMask);
2920 }
2921 else
2922 {
2923 uint32_t u32AndMaskDepth = 1;
2924 uint32_t u32XorMaskDepth = 32;
2925
2926 void const *pvAndMask = &pAttrs->Pixels[0];
2927 void const *pvXorMask = &pAttrs->Pixels[cbAndMask];
2928 Status = GaDefineCursor(pDevExt->pGa,
2929 xHot,
2930 yHot,
2931 cWidth,
2932 cHeight,
2933 u32AndMaskDepth,
2934 u32XorMaskDepth,
2935 pvAndMask,
2936 cbAndMask,
2937 pvXorMask,
2938 cbXorMask);
2939 }
2940 }
2941
2942 /** @todo Hack: Use the legacy interface to handle visibility.
2943 * Eventually the VMSVGA WDDM driver should use the SVGA_FIFO_CURSOR_* interface.
2944 */
2945 VIDEO_POINTER_ATTRIBUTES attrs;
2946 RT_ZERO(attrs);
2947 attrs.Enable = pAttrs->Enable & VBOX_MOUSE_POINTER_VISIBLE;
2948 if (!VBoxMPCmnUpdatePointerShape(VBoxCommonFromDeviceExt(pDevExt), &attrs, sizeof(attrs)))
2949 {
2950 Status = STATUS_INVALID_PARAMETER;
2951 }
2952
2953 return Status == STATUS_SUCCESS;
2954 }
2955#endif
2956
2957 /* VBOXVIDEO_HWTYPE_VBOX */
2958 return VBoxMPCmnUpdatePointerShape(VBoxCommonFromDeviceExt(pDevExt), pAttrs, cbLength);
2959}
2960
2961static void vboxWddmHostPointerEnable(PVBOXMP_DEVEXT pDevExt, BOOLEAN fEnable)
2962{
2963 VIDEO_POINTER_ATTRIBUTES PointerAttributes;
2964 RT_ZERO(PointerAttributes);
2965 if (fEnable)
2966 {
2967 PointerAttributes.Enable = VBOX_MOUSE_POINTER_VISIBLE;
2968 }
2969 vboxWddmUpdatePointerShape(pDevExt, &PointerAttributes, sizeof(PointerAttributes));
2970}
2971
2972NTSTATUS
2973APIENTRY
2974DxgkDdiSetPointerPosition(
2975 CONST HANDLE hAdapter,
2976 CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition)
2977{
2978// LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
2979
2980 vboxVDbgBreakFv();
2981
2982 /* mouse integration is ON */
2983 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
2984 PVBOXWDDM_POINTER_INFO pPointerInfo = &pDevExt->aSources[pSetPointerPosition->VidPnSourceId].PointerInfo;
2985 PVBOXWDDM_GLOBAL_POINTER_INFO pGlobalPointerInfo = &pDevExt->PointerInfo;
2986 PVIDEO_POINTER_ATTRIBUTES pPointerAttributes = &pPointerInfo->Attributes.data;
2987 BOOLEAN fScreenVisState = !!(pPointerAttributes->Enable & VBOX_MOUSE_POINTER_VISIBLE);
2988 BOOLEAN fVisStateChanged = FALSE;
2989 BOOLEAN fScreenChanged = pGlobalPointerInfo->iLastReportedScreen != pSetPointerPosition->VidPnSourceId;
2990
2991 if (pSetPointerPosition->Flags.Visible)
2992 {
2993 pPointerAttributes->Enable |= VBOX_MOUSE_POINTER_VISIBLE;
2994 if (!fScreenVisState)
2995 {
2996 fVisStateChanged = TRUE;
2997 }
2998 }
2999 else
3000 {
3001 pPointerAttributes->Enable &= ~VBOX_MOUSE_POINTER_VISIBLE;
3002 if (fScreenVisState)
3003 {
3004 fVisStateChanged = TRUE;
3005 }
3006 }
3007
3008 pGlobalPointerInfo->iLastReportedScreen = pSetPointerPosition->VidPnSourceId;
3009
3010 if ((fVisStateChanged || fScreenChanged) && VBoxQueryHostWantsAbsolute())
3011 {
3012 if (fScreenChanged)
3013 {
3014 BOOLEAN bResult = vboxWddmUpdatePointerShape(pDevExt, &pPointerInfo->Attributes.data, VBOXWDDM_POINTER_ATTRIBUTES_SIZE);
3015 if (!bResult)
3016 {
3017 vboxWddmHostPointerEnable(pDevExt, FALSE);
3018 }
3019 }
3020
3021 // Always update the visibility as requested. Tell the host to use the guest's pointer.
3022 vboxWddmHostPointerEnable(pDevExt, pSetPointerPosition->Flags.Visible);
3023 }
3024
3025// LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3026
3027 return STATUS_SUCCESS;
3028}
3029
3030NTSTATUS
3031APIENTRY
3032DxgkDdiSetPointerShape(
3033 CONST HANDLE hAdapter,
3034 CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape)
3035{
3036// LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3037
3038 vboxVDbgBreakFv();
3039
3040 NTSTATUS Status = STATUS_NOT_SUPPORTED;
3041
3042 if (VBoxQueryHostWantsAbsolute())
3043 {
3044 /* mouse integration is ON */
3045 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3046 PVBOXWDDM_POINTER_INFO pPointerInfo = &pDevExt->aSources[pSetPointerShape->VidPnSourceId].PointerInfo;
3047 bool const fDwordAlignScanlines = pDevExt->enmHwType != VBOXVIDEO_HWTYPE_VBOX;
3048 /** @todo to avoid extra data copy and extra heap allocation,
3049 * need to maintain the pre-allocated HGSMI buffer and convert the data directly to it */
3050 if (vboxVddmPointerShapeToAttributes(pSetPointerShape, pPointerInfo, fDwordAlignScanlines))
3051 {
3052 pDevExt->PointerInfo.iLastReportedScreen = pSetPointerShape->VidPnSourceId;
3053 if (vboxWddmUpdatePointerShape(pDevExt, &pPointerInfo->Attributes.data, VBOXWDDM_POINTER_ATTRIBUTES_SIZE))
3054 Status = STATUS_SUCCESS;
3055 else
3056 {
3057 // tell the host to use the guest's pointer
3058 vboxWddmHostPointerEnable(pDevExt, FALSE);
3059 }
3060 }
3061 }
3062
3063// LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3064
3065 return Status;
3066}
3067
3068NTSTATUS
3069APIENTRY CALLBACK
3070DxgkDdiResetFromTimeout(
3071 CONST HANDLE hAdapter)
3072{
3073 RT_NOREF(hAdapter);
3074 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3075
3076 AssertBreakpoint();
3077 /** @todo fixme: implement */
3078
3079 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3080
3081 return STATUS_SUCCESS;
3082}
3083
3084
3085/* the lpRgnData->Buffer comes to us as RECT
3086 * to avoid extra memcpy we cast it to PRTRECT assuming
3087 * they are identical */
3088AssertCompile(sizeof(RECT) == sizeof(RTRECT));
3089AssertCompile(RT_OFFSETOF(RECT, left) == RT_OFFSETOF(RTRECT, xLeft));
3090AssertCompile(RT_OFFSETOF(RECT, bottom) == RT_OFFSETOF(RTRECT, yBottom));
3091AssertCompile(RT_OFFSETOF(RECT, right) == RT_OFFSETOF(RTRECT, xRight));
3092AssertCompile(RT_OFFSETOF(RECT, top) == RT_OFFSETOF(RTRECT, yTop));
3093
3094NTSTATUS
3095APIENTRY
3096DxgkDdiEscape(
3097 CONST HANDLE hAdapter,
3098 CONST DXGKARG_ESCAPE* pEscape)
3099{
3100 PAGED_CODE();
3101
3102// LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3103
3104 NTSTATUS Status = STATUS_NOT_SUPPORTED;
3105 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3106 Assert(pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE));
3107 if (pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE))
3108 {
3109 PVBOXDISPIFESCAPE pEscapeHdr = (PVBOXDISPIFESCAPE)pEscape->pPrivateDriverData;
3110 switch (pEscapeHdr->escapeCode)
3111 {
3112 case VBOXESC_SETVISIBLEREGION:
3113 {
3114#ifdef VBOX_DISPIF_WITH_OPCONTEXT
3115 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
3116 if (!pContext)
3117 {
3118 WARN(("VBOXESC_SETVISIBLEREGION no context supplied!"));
3119 Status = STATUS_INVALID_PARAMETER;
3120 break;
3121 }
3122
3123 if (pContext->enmType != VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_SEAMLESS)
3124 {
3125 WARN(("VBOXESC_SETVISIBLEREGION invalid context supplied %d!", pContext->enmType));
3126 Status = STATUS_INVALID_PARAMETER;
3127 break;
3128 }
3129#endif
3130 /* visible regions for seamless */
3131 LPRGNDATA lpRgnData = VBOXDISPIFESCAPE_DATA(pEscapeHdr, RGNDATA);
3132 uint32_t cbData = VBOXDISPIFESCAPE_DATA_SIZE(pEscape->PrivateDriverDataSize);
3133 uint32_t cbRects = cbData - RT_UOFFSETOF(RGNDATA, Buffer);
3134 /* the lpRgnData->Buffer comes to us as RECT
3135 * to avoid extra memcpy we cast it to PRTRECT assuming
3136 * they are identical
3137 * see AssertCompile's above */
3138
3139 RTRECT *pRect = (RTRECT *)&lpRgnData->Buffer;
3140
3141 uint32_t cRects = cbRects/sizeof(RTRECT);
3142 int rc;
3143
3144 LOG(("IOCTL_VIDEO_VBOX_SETVISIBLEREGION cRects=%d", cRects));
3145 Assert(cbRects >= sizeof(RTRECT)
3146 && cbRects == cRects*sizeof(RTRECT)
3147 && cRects == lpRgnData->rdh.nCount);
3148 if ( cbRects >= sizeof(RTRECT)
3149 && cbRects == cRects*sizeof(RTRECT)
3150 && cRects == lpRgnData->rdh.nCount)
3151 {
3152 /*
3153 * Inform the host about the visible region
3154 */
3155 VMMDevVideoSetVisibleRegion *req = NULL;
3156
3157 rc = VbglR0GRAlloc ((VMMDevRequestHeader **)&req,
3158 sizeof (VMMDevVideoSetVisibleRegion) + (cRects-1)*sizeof(RTRECT),
3159 VMMDevReq_VideoSetVisibleRegion);
3160 AssertRC(rc);
3161 if (RT_SUCCESS(rc))
3162 {
3163 req->cRect = cRects;
3164 memcpy(&req->Rect, pRect, cRects*sizeof(RTRECT));
3165
3166 rc = VbglR0GRPerform (&req->header);
3167 AssertRC(rc);
3168 if (RT_SUCCESS(rc))
3169 Status = STATUS_SUCCESS;
3170 else
3171 {
3172 WARN(("VbglR0GRPerform failed rc (%d)", rc));
3173 Status = STATUS_UNSUCCESSFUL;
3174 }
3175 }
3176 else
3177 {
3178 WARN(("VbglR0GRAlloc failed rc (%d)", rc));
3179 Status = STATUS_UNSUCCESSFUL;
3180 }
3181 }
3182 else
3183 {
3184 WARN(("VBOXESC_SETVISIBLEREGION: incorrect buffer size (%d), reported count (%d)", cbRects, lpRgnData->rdh.nCount));
3185 Status = STATUS_INVALID_PARAMETER;
3186 }
3187 break;
3188 }
3189 case VBOXESC_ISVRDPACTIVE:
3190 /** @todo implement */
3191 Status = STATUS_SUCCESS;
3192 break;
3193 case VBOXESC_CONFIGURETARGETS:
3194 {
3195 LOG(("=> VBOXESC_CONFIGURETARGETS"));
3196
3197 if (!pEscape->Flags.HardwareAccess)
3198 {
3199 WARN(("VBOXESC_CONFIGURETARGETS called without HardwareAccess flag set, failing"));
3200 Status = STATUS_INVALID_PARAMETER;
3201 break;
3202 }
3203
3204#ifdef VBOX_DISPIF_WITH_OPCONTEXT
3205 /* win8.1 does not allow context-based escapes for display-only mode */
3206 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
3207 if (!pContext)
3208 {
3209 WARN(("VBOXESC_CONFIGURETARGETS no context supplied!"));
3210 Status = STATUS_INVALID_PARAMETER;
3211 break;
3212 }
3213
3214 if (pContext->enmType != VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_RESIZE)
3215 {
3216 WARN(("VBOXESC_CONFIGURETARGETS invalid context supplied %d!", pContext->enmType));
3217 Status = STATUS_INVALID_PARAMETER;
3218 break;
3219 }
3220#endif
3221
3222 if (pEscape->PrivateDriverDataSize != sizeof (*pEscapeHdr))
3223 {
3224 WARN(("VBOXESC_CONFIGURETARGETS invalid private driver size %d", pEscape->PrivateDriverDataSize));
3225 Status = STATUS_INVALID_PARAMETER;
3226 break;
3227 }
3228
3229 if (pEscapeHdr->u32CmdSpecific)
3230 {
3231 WARN(("VBOXESC_CONFIGURETARGETS invalid command %d", pEscapeHdr->u32CmdSpecific));
3232 Status = STATUS_INVALID_PARAMETER;
3233 break;
3234 }
3235
3236 HANDLE hKey = NULL;
3237 uint32_t cAdjusted = 0;
3238
3239 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
3240 {
3241 VBOXWDDM_TARGET *pTarget = &pDevExt->aTargets[i];
3242 if (pTarget->fConfigured)
3243 continue;
3244
3245 pTarget->fConfigured = true;
3246
3247 if (!pTarget->fConnected)
3248 {
3249 Status = VBoxWddmChildStatusConnect(pDevExt, (uint32_t)i, TRUE);
3250 if (NT_SUCCESS(Status))
3251 ++cAdjusted;
3252 else
3253 WARN(("VBOXESC_CONFIGURETARGETS vboxWddmChildStatusConnectSecondaries failed Status 0x%x\n", Status));
3254 }
3255
3256 if (!hKey)
3257 {
3258 Status = IoOpenDeviceRegistryKey(pDevExt->pPDO, PLUGPLAY_REGKEY_DRIVER, GENERIC_WRITE, &hKey);
3259 if (!NT_SUCCESS(Status))
3260 {
3261 WARN(("VBOXESC_CONFIGURETARGETS IoOpenDeviceRegistryKey failed, Status = 0x%x", Status));
3262 hKey = NULL;
3263 continue;
3264 }
3265 }
3266
3267 Assert(hKey);
3268
3269 WCHAR wszNameBuf[sizeof(VBOXWDDM_REG_DRV_DISPFLAGS_PREFIX) / sizeof(WCHAR) + 32];
3270 RTUtf16Printf(wszNameBuf, RT_ELEMENTS(wszNameBuf), "%ls%d", VBOXWDDM_REG_DRV_DISPFLAGS_PREFIX, i);
3271 Status = vboxWddmRegSetValueDword(hKey, wszNameBuf, VBOXWDDM_CFG_DRVTARGET_CONNECTED);
3272 if (!NT_SUCCESS(Status))
3273 WARN(("VBOXESC_CONFIGURETARGETS vboxWddmRegSetValueDword (%ls) failed Status 0x%x\n", wszNameBuf, Status));
3274
3275 }
3276
3277 if (hKey)
3278 {
3279 NTSTATUS rcNt2 = ZwClose(hKey);
3280 Assert(rcNt2 == STATUS_SUCCESS); NOREF(rcNt2);
3281 }
3282
3283 pEscapeHdr->u32CmdSpecific = cAdjusted;
3284
3285 Status = STATUS_SUCCESS;
3286
3287 LOG(("<= VBOXESC_CONFIGURETARGETS"));
3288 break;
3289 }
3290 case VBOXESC_SETALLOCHOSTID:
3291 {
3292 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)pEscape->hDevice;
3293 if (!pDevice)
3294 {
3295 WARN(("VBOXESC_SETALLOCHOSTID called without no device specified, failing"));
3296 Status = STATUS_INVALID_PARAMETER;
3297 break;
3298 }
3299
3300 if (pEscape->PrivateDriverDataSize != sizeof (VBOXDISPIFESCAPE_SETALLOCHOSTID))
3301 {
3302 WARN(("invalid buffer size for VBOXDISPIFESCAPE_SETALLOCHOSTID, was(%d), but expected (%d)",
3303 pEscape->PrivateDriverDataSize, sizeof (VBOXDISPIFESCAPE_SETALLOCHOSTID)));
3304 Status = STATUS_INVALID_PARAMETER;
3305 break;
3306 }
3307
3308 if (!pEscape->Flags.HardwareAccess)
3309 {
3310 WARN(("VBOXESC_SETALLOCHOSTID not HardwareAccess"));
3311 Status = STATUS_INVALID_PARAMETER;
3312 break;
3313 }
3314
3315 PVBOXDISPIFESCAPE_SETALLOCHOSTID pSetHostID = (PVBOXDISPIFESCAPE_SETALLOCHOSTID)pEscapeHdr;
3316 PVBOXWDDM_ALLOCATION pAlloc = vboxWddmGetAllocationFromHandle(pDevExt, (D3DKMT_HANDLE)pSetHostID->hAlloc);
3317 if (!pAlloc)
3318 {
3319 WARN(("failed to get allocation from handle"));
3320 Status = STATUS_INVALID_PARAMETER;
3321 break;
3322 }
3323
3324 if (pAlloc->enmType != VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE)
3325 {
3326 WARN(("setHostID: invalid allocation type: %d", pAlloc->enmType));
3327 Status = STATUS_INVALID_PARAMETER;
3328 break;
3329 }
3330
3331 pSetHostID->rc = VBoxWddmOaSetHostID(pDevice, pAlloc, pSetHostID->hostID, &pSetHostID->EscapeHdr.u32CmdSpecific);
3332
3333 if (pAlloc->bAssigned)
3334 {
3335 PVBOXMP_DEVEXT pDevExt2 = pDevice->pAdapter;
3336 Assert(pAlloc->AllocData.SurfDesc.VidPnSourceId < (D3DDDI_VIDEO_PRESENT_SOURCE_ID)VBoxCommonFromDeviceExt(pDevExt2)->cDisplays);
3337 PVBOXWDDM_SOURCE pSource = &pDevExt2->aSources[pAlloc->AllocData.SurfDesc.VidPnSourceId];
3338 if (pSource->AllocData.hostID != pAlloc->AllocData.hostID)
3339 {
3340 pSource->AllocData.hostID = pAlloc->AllocData.hostID;
3341 pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_LOCATION;
3342
3343 vboxWddmGhDisplayCheckSetInfo(pDevExt2);
3344 }
3345 }
3346
3347 Status = STATUS_SUCCESS;
3348 break;
3349 }
3350 case VBOXESC_ISANYX:
3351 {
3352 if (pEscape->PrivateDriverDataSize != sizeof (VBOXDISPIFESCAPE_ISANYX))
3353 {
3354 WARN(("invalid private driver size %d", pEscape->PrivateDriverDataSize));
3355 Status = STATUS_INVALID_PARAMETER;
3356 break;
3357 }
3358
3359 PVBOXDISPIFESCAPE_ISANYX pIsAnyX = (PVBOXDISPIFESCAPE_ISANYX)pEscapeHdr;
3360 pIsAnyX->u32IsAnyX = VBoxCommonFromDeviceExt(pDevExt)->fAnyX;
3361 Status = STATUS_SUCCESS;
3362 break;
3363 }
3364 case VBOXESC_UPDATEMODES:
3365 {
3366 LOG(("=> VBOXESC_UPDATEMODES"));
3367
3368 if (!pEscape->Flags.HardwareAccess)
3369 {
3370 WARN(("VBOXESC_UPDATEMODES called without HardwareAccess flag set, failing"));
3371 Status = STATUS_INVALID_PARAMETER;
3372 break;
3373 }
3374
3375#ifdef VBOX_DISPIF_WITH_OPCONTEXT
3376 /* win8.1 does not allow context-based escapes for display-only mode */
3377 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
3378 if (!pContext)
3379 {
3380 WARN(("VBOXESC_UPDATEMODES no context supplied!"));
3381 Status = STATUS_INVALID_PARAMETER;
3382 break;
3383 }
3384
3385 if (pContext->enmType != VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_RESIZE)
3386 {
3387 WARN(("VBOXESC_UPDATEMODES invalid context supplied %d!", pContext->enmType));
3388 Status = STATUS_INVALID_PARAMETER;
3389 break;
3390 }
3391#endif
3392
3393 if (pEscape->PrivateDriverDataSize != sizeof (VBOXDISPIFESCAPE_UPDATEMODES))
3394 {
3395 WARN(("VBOXESC_UPDATEMODES invalid private driver size %d", pEscape->PrivateDriverDataSize));
3396 Status = STATUS_INVALID_PARAMETER;
3397 break;
3398 }
3399
3400 VBOXDISPIFESCAPE_UPDATEMODES *pData = (VBOXDISPIFESCAPE_UPDATEMODES*)pEscapeHdr;
3401 Status = VBoxVidPnUpdateModes(pDevExt, pData->u32TargetId, &pData->Size);
3402 if (!NT_SUCCESS(Status))
3403 {
3404 WARN(("VBoxVidPnUpdateModes failed Status(%#x)\n", Status));
3405 return Status;
3406 }
3407
3408 Status = STATUS_SUCCESS;
3409 break;
3410 }
3411 case VBOXESC_TARGET_CONNECTIVITY:
3412 {
3413 if (!pEscape->Flags.HardwareAccess)
3414 {
3415 WARN(("VBOXESC_TARGET_CONNECTIVITY called without HardwareAccess flag set, failing"));
3416 Status = STATUS_INVALID_PARAMETER;
3417 break;
3418 }
3419
3420 if (pEscape->PrivateDriverDataSize != sizeof(VBOXDISPIFESCAPE_TARGETCONNECTIVITY))
3421 {
3422 WARN(("VBOXESC_TARGET_CONNECTIVITY invalid private driver size %d", pEscape->PrivateDriverDataSize));
3423 Status = STATUS_INVALID_PARAMETER;
3424 break;
3425 }
3426
3427 VBOXDISPIFESCAPE_TARGETCONNECTIVITY *pData = (VBOXDISPIFESCAPE_TARGETCONNECTIVITY *)pEscapeHdr;
3428 LOG(("=> VBOXESC_TARGET_CONNECTIVITY[%d] 0x%08X", pData->u32TargetId, pData->fu32Connect));
3429
3430 if (pData->u32TargetId >= (uint32_t)VBoxCommonFromDeviceExt(pDevExt)->cDisplays)
3431 {
3432 WARN(("VBOXESC_TARGET_CONNECTIVITY invalid screen index 0x%x", pData->u32TargetId));
3433 Status = STATUS_INVALID_PARAMETER;
3434 break;
3435 }
3436
3437 PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[pData->u32TargetId];
3438 pTarget->fDisabled = !RT_BOOL(pData->fu32Connect & 1);
3439 pTarget->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_TOPOLOGY;
3440
3441 Status = STATUS_SUCCESS;
3442 break;
3443 }
3444 case VBOXESC_DBGPRINT:
3445 {
3446 /* use RT_OFFSETOF instead of sizeof since sizeof will give an aligned size that might
3447 * be bigger than the VBOXDISPIFESCAPE_DBGPRINT with a data containing just a few chars */
3448 Assert(pEscape->PrivateDriverDataSize >= RT_UOFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1]));
3449 /* only do DbgPrint when pEscape->PrivateDriverDataSize > RT_OFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1])
3450 * since == RT_OFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1]) means the buffer contains just \0,
3451 * i.e. no need to print it */
3452 if (pEscape->PrivateDriverDataSize > RT_UOFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1]))
3453 {
3454 PVBOXDISPIFESCAPE_DBGPRINT pDbgPrint = (PVBOXDISPIFESCAPE_DBGPRINT)pEscapeHdr;
3455 /* ensure the last char is \0*/
3456 if (*((uint8_t*)pDbgPrint + pEscape->PrivateDriverDataSize - 1) == '\0')
3457 {
3458 if (g_VBoxLogUm & VBOXWDDM_CFG_LOG_UM_DBGPRINT)
3459 DbgPrint("%s\n", pDbgPrint->aStringBuf);
3460 if (g_VBoxLogUm & VBOXWDDM_CFG_LOG_UM_BACKDOOR)
3461 LOGREL_EXACT(("%s\n", pDbgPrint->aStringBuf));
3462 }
3463 }
3464 Status = STATUS_SUCCESS;
3465 break;
3466 }
3467 case VBOXESC_DBGDUMPBUF:
3468 {
3469 Status = vboxUmdDumpBuf((PVBOXDISPIFESCAPE_DBGDUMPBUF)pEscapeHdr, pEscape->PrivateDriverDataSize);
3470 break;
3471 }
3472 case VBOXESC_GUEST_DISPLAYCHANGED:
3473 {
3474 LOG(("=> VBOXESC_GUEST_DISPLAYCHANGED"));
3475
3476 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
3477 {
3478#ifdef VBOX_WITH_MESA3D
3479 if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VMSVGA)
3480 {
3481 GaVidPnSourceCheckPos(pDevExt, i);
3482 continue;
3483 }
3484#endif
3485
3486 vboxWddmDisplaySettingsCheckPos(pDevExt, i);
3487 }
3488 Status = STATUS_SUCCESS;
3489 break;
3490 }
3491 default:
3492#ifdef VBOX_WITH_MESA3D
3493 Status = GaDxgkDdiEscape(hAdapter, pEscape);
3494 if (NT_SUCCESS(Status) || Status != STATUS_NOT_SUPPORTED)
3495 break;
3496#endif
3497 WARN(("unsupported escape code (0x%x)", pEscapeHdr->escapeCode));
3498 break;
3499 }
3500 }
3501 else
3502 {
3503 WARN(("pEscape->PrivateDriverDataSize(%d) < (%d)", pEscape->PrivateDriverDataSize, sizeof (VBOXDISPIFESCAPE)));
3504 Status = STATUS_BUFFER_TOO_SMALL;
3505 }
3506
3507// LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3508
3509 return Status;
3510}
3511
3512NTSTATUS
3513APIENTRY
3514DxgkDdiCollectDbgInfo(
3515 CONST HANDLE hAdapter,
3516 CONST DXGKARG_COLLECTDBGINFO* pCollectDbgInfo
3517 )
3518{
3519 RT_NOREF(hAdapter, pCollectDbgInfo);
3520 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3521
3522 AssertBreakpoint();
3523
3524 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3525
3526 return STATUS_SUCCESS;
3527}
3528
3529NTSTATUS
3530APIENTRY
3531DxgkDdiIsSupportedVidPn(
3532 CONST HANDLE hAdapter,
3533 OUT DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPnArg
3534 )
3535{
3536 /* The DxgkDdiIsSupportedVidPn should be made pageable. */
3537 PAGED_CODE();
3538
3539 LOGF(("ENTER, context(0x%x)", hAdapter));
3540
3541 vboxVDbgBreakFv();
3542
3543 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3544 NTSTATUS Status = VBoxVidPnIsSupported(pDevExt, pIsSupportedVidPnArg->hDesiredVidPn, &pIsSupportedVidPnArg->IsVidPnSupported);
3545 if (!NT_SUCCESS(Status))
3546 {
3547 WARN(("VBoxVidPnIsSupported failed Status(%#x)\n", Status));
3548 return Status;
3549 }
3550
3551 LOGF(("LEAVE, isSupported(%d), context(0x%x)", pIsSupportedVidPnArg->IsVidPnSupported, hAdapter));
3552
3553 return STATUS_SUCCESS;
3554}
3555
3556NTSTATUS
3557APIENTRY
3558DxgkDdiRecommendFunctionalVidPn(
3559 CONST HANDLE hAdapter,
3560 CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPnArg
3561 )
3562{
3563 /* The DxgkDdiRecommendFunctionalVidPn should be made pageable. */
3564 PAGED_CODE();
3565
3566 LOGF(("ENTER, context(0x%x)", hAdapter));
3567
3568 vboxVDbgBreakFv();
3569
3570 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3571
3572 if (pRecommendFunctionalVidPnArg->PrivateDriverDataSize != sizeof (VBOXWDDM_RECOMMENDVIDPN))
3573 {
3574 WARN(("invalid size"));
3575 return STATUS_INVALID_PARAMETER;
3576 }
3577
3578 VBOXWDDM_RECOMMENDVIDPN *pData = (VBOXWDDM_RECOMMENDVIDPN*)pRecommendFunctionalVidPnArg->pPrivateDriverData;
3579 Assert(pData);
3580
3581 NTSTATUS Status = VBoxVidPnRecommendFunctional(pDevExt, pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, pData);
3582 if (!NT_SUCCESS(Status))
3583 {
3584 WARN(("VBoxVidPnRecommendFunctional failed %#x", Status));
3585 return Status;
3586 }
3587
3588 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
3589
3590 return STATUS_SUCCESS;
3591}
3592
3593NTSTATUS
3594APIENTRY
3595DxgkDdiEnumVidPnCofuncModality(
3596 CONST HANDLE hAdapter,
3597 CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModalityArg
3598 )
3599{
3600 /* The DxgkDdiEnumVidPnCofuncModality function should be made pageable. */
3601 PAGED_CODE();
3602
3603 LOGF(("ENTER, context(0x%x)", hAdapter));
3604
3605 vboxVDbgBreakFv();
3606
3607 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3608
3609 NTSTATUS Status = VBoxVidPnCofuncModality(pDevExt, pEnumCofuncModalityArg->hConstrainingVidPn, pEnumCofuncModalityArg->EnumPivotType, &pEnumCofuncModalityArg->EnumPivot);
3610 if (!NT_SUCCESS(Status))
3611 {
3612 WARN(("VBoxVidPnCofuncModality failed Status(%#x)\n", Status));
3613 return Status;
3614 }
3615
3616 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
3617
3618 return STATUS_SUCCESS;
3619}
3620
3621NTSTATUS
3622APIENTRY
3623DxgkDdiSetVidPnSourceAddress(
3624 CONST HANDLE hAdapter,
3625 CONST DXGKARG_SETVIDPNSOURCEADDRESS* pSetVidPnSourceAddress
3626 )
3627{
3628 /* The DxgkDdiSetVidPnSourceAddress function should be made pageable. */
3629 PAGED_CODE();
3630
3631 vboxVDbgBreakFv();
3632
3633 LOGF(("ENTER, context(0x%x)", hAdapter));
3634 LOG(("id %d, seg %d, addr 0x%RX64, hAllocation %p, ctx cnt %d, f 0x%x",
3635 pSetVidPnSourceAddress->VidPnSourceId,
3636 pSetVidPnSourceAddress->PrimarySegment,
3637 pSetVidPnSourceAddress->PrimaryAddress.QuadPart,
3638 pSetVidPnSourceAddress->hAllocation,
3639 pSetVidPnSourceAddress->ContextCount,
3640 pSetVidPnSourceAddress->Flags.Value));
3641
3642 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3643 if ((UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays <= pSetVidPnSourceAddress->VidPnSourceId)
3644 {
3645 WARN(("invalid VidPnSourceId (%d), for displays(%d)", pSetVidPnSourceAddress->VidPnSourceId, VBoxCommonFromDeviceExt(pDevExt)->cDisplays));
3646 return STATUS_INVALID_PARAMETER;
3647 }
3648
3649#ifdef VBOX_WITH_MESA3D
3650 if (pDevExt->enmHwType != VBOXVIDEO_HWTYPE_VMSVGA)
3651#endif
3652 vboxWddmDisplaySettingsCheckPos(pDevExt, pSetVidPnSourceAddress->VidPnSourceId);
3653
3654 NTSTATUS Status = STATUS_SUCCESS;
3655 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pSetVidPnSourceAddress->VidPnSourceId];
3656
3657 /*
3658 * Update the source VRAM address.
3659 */
3660 PVBOXWDDM_ALLOCATION pAllocation;
3661 Assert(pSetVidPnSourceAddress->hAllocation);
3662 Assert(pSetVidPnSourceAddress->hAllocation || pSource->pPrimaryAllocation);
3663 Assert (pSetVidPnSourceAddress->Flags.Value < 2); /* i.e. 0 or 1 (ModeChange) */
3664
3665 if (pSetVidPnSourceAddress->hAllocation)
3666 {
3667 pAllocation = (PVBOXWDDM_ALLOCATION)pSetVidPnSourceAddress->hAllocation;
3668 vboxWddmAssignPrimary(pSource, pAllocation, pSetVidPnSourceAddress->VidPnSourceId);
3669 }
3670 else
3671 pAllocation = pSource->pPrimaryAllocation;
3672
3673 if (pAllocation)
3674 {
3675 vboxWddmAddrSetVram(&pAllocation->AllocData.Addr, pSetVidPnSourceAddress->PrimarySegment, (VBOXVIDEOOFFSET)pSetVidPnSourceAddress->PrimaryAddress.QuadPart);
3676 }
3677
3678 if (g_VBoxDisplayOnly && !pAllocation)
3679 {
3680 /* the VRAM here is an absolute address, nto an offset!
3681 * convert to offset since all internal VBox functionality is offset-based */
3682 vboxWddmAddrSetVram(&pSource->AllocData.Addr, pSetVidPnSourceAddress->PrimarySegment,
3683 vboxWddmVramAddrToOffset(pDevExt, pSetVidPnSourceAddress->PrimaryAddress));
3684 }
3685 else
3686 {
3687 Assert(!g_VBoxDisplayOnly);
3688 vboxWddmAddrSetVram(&pSource->AllocData.Addr, pSetVidPnSourceAddress->PrimarySegment,
3689 pSetVidPnSourceAddress->PrimaryAddress.QuadPart);
3690 }
3691
3692 pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_LOCATION;
3693
3694 /*
3695 * Report the source.
3696 */
3697#ifdef VBOX_WITH_MESA3D
3698 if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VMSVGA)
3699 {
3700 /* Query the position of the screen to make sure it is up to date. */
3701 vboxWddmDisplaySettingsQueryPos(pDevExt, pSetVidPnSourceAddress->VidPnSourceId, &pSource->VScreenPos);
3702
3703 GaVidPnSourceReport(pDevExt, pSource);
3704 return STATUS_SUCCESS;
3705 }
3706#endif
3707
3708 vboxWddmGhDisplayCheckSetInfoFromSource(pDevExt, pSource);
3709
3710 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
3711
3712 return Status;
3713}
3714
3715NTSTATUS
3716APIENTRY
3717DxgkDdiSetVidPnSourceVisibility(
3718 CONST HANDLE hAdapter,
3719 CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility
3720 )
3721{
3722 /* DxgkDdiSetVidPnSourceVisibility should be made pageable. */
3723 PAGED_CODE();
3724
3725 vboxVDbgBreakFv();
3726
3727 LOGF(("ENTER, context(0x%x)", hAdapter));
3728
3729 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3730
3731 if ((UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays <= pSetVidPnSourceVisibility->VidPnSourceId)
3732 {
3733 WARN(("invalid VidPnSourceId (%d), for displays(%d)", pSetVidPnSourceVisibility->VidPnSourceId, VBoxCommonFromDeviceExt(pDevExt)->cDisplays));
3734 return STATUS_INVALID_PARAMETER;
3735 }
3736
3737#ifdef VBOX_WITH_MESA3D
3738 if (pDevExt->enmHwType != VBOXVIDEO_HWTYPE_VMSVGA)
3739#endif
3740 vboxWddmDisplaySettingsCheckPos(pDevExt, pSetVidPnSourceVisibility->VidPnSourceId);
3741
3742 NTSTATUS Status = STATUS_SUCCESS;
3743 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pSetVidPnSourceVisibility->VidPnSourceId];
3744 PVBOXWDDM_ALLOCATION pAllocation = pSource->pPrimaryAllocation;
3745 if (pAllocation)
3746 {
3747 Assert(pAllocation->bVisible == pSource->bVisible);
3748 pAllocation->bVisible = pSetVidPnSourceVisibility->Visible;
3749 }
3750
3751 if (pSource->bVisible != pSetVidPnSourceVisibility->Visible)
3752 {
3753 pSource->bVisible = pSetVidPnSourceVisibility->Visible;
3754// pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_VISIBILITY;
3755// if (pDevExt->fCmdVbvaEnabled || pSource->bVisible)
3756// {
3757// vboxWddmGhDisplayCheckSetInfoFromSource(pDevExt, pSource);
3758// }
3759 }
3760
3761#ifdef VBOX_WITH_MESA3D
3762 if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VMSVGA)
3763 {
3764 GaVidPnSourceCheckPos(pDevExt, pSetVidPnSourceVisibility->VidPnSourceId);
3765 }
3766#endif
3767
3768 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
3769
3770 return Status;
3771}
3772
3773NTSTATUS
3774APIENTRY
3775DxgkDdiCommitVidPn(
3776 CONST HANDLE hAdapter,
3777 CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPnArg
3778 )
3779{
3780 LOG(("ENTER AffectedVidPnSourceId(%d) hAdapter(0x%x)", pCommitVidPnArg->AffectedVidPnSourceId, hAdapter));
3781
3782 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3783 NTSTATUS Status;
3784
3785 vboxVDbgBreakFv();
3786
3787 VBOXWDDM_SOURCE *paSources = (VBOXWDDM_SOURCE*)RTMemAlloc(sizeof (VBOXWDDM_SOURCE) * VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
3788 if (!paSources)
3789 {
3790 WARN(("RTMemAlloc failed"));
3791 return STATUS_NO_MEMORY;
3792 }
3793
3794 VBOXWDDM_TARGET *paTargets = (VBOXWDDM_TARGET*)RTMemAlloc(sizeof (VBOXWDDM_TARGET) * VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
3795 if (!paTargets)
3796 {
3797 WARN(("RTMemAlloc failed"));
3798 RTMemFree(paSources);
3799 return STATUS_NO_MEMORY;
3800 }
3801
3802 VBoxVidPnSourcesInit(paSources, VBoxCommonFromDeviceExt(pDevExt)->cDisplays, VBOXWDDM_HGSYNC_F_SYNCED_ALL);
3803
3804 VBoxVidPnTargetsInit(paTargets, VBoxCommonFromDeviceExt(pDevExt)->cDisplays, VBOXWDDM_HGSYNC_F_SYNCED_ALL);
3805
3806 VBoxVidPnSourcesCopy(paSources, pDevExt->aSources, VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
3807 VBoxVidPnTargetsCopy(paTargets, pDevExt->aTargets, VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
3808
3809 do {
3810 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
3811 Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pCommitVidPnArg->hFunctionalVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
3812 if (!NT_SUCCESS(Status))
3813 {
3814 WARN(("DxgkCbQueryVidPnInterface failed Status 0x%x", Status));
3815 break;
3816 }
3817
3818#ifdef VBOXWDDM_DEBUG_VIDPN
3819 vboxVidPnDumpVidPn("\n>>>>COMMIT VidPN: >>>>", pDevExt, pCommitVidPnArg->hFunctionalVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<\n");
3820#endif
3821
3822 if (pCommitVidPnArg->AffectedVidPnSourceId != D3DDDI_ID_ALL)
3823 {
3824 Status = VBoxVidPnCommitSourceModeForSrcId(
3825 pDevExt,
3826 pCommitVidPnArg->hFunctionalVidPn, pVidPnInterface,
3827 (PVBOXWDDM_ALLOCATION)pCommitVidPnArg->hPrimaryAllocation,
3828 pCommitVidPnArg->AffectedVidPnSourceId, paSources, paTargets, pCommitVidPnArg->Flags.PathPowerTransition);
3829 if (!NT_SUCCESS(Status))
3830 {
3831 WARN(("VBoxVidPnCommitSourceModeForSrcId for current VidPn failed Status 0x%x", Status));
3832 break;
3833 }
3834 }
3835 else
3836 {
3837 Status = VBoxVidPnCommitAll(pDevExt, pCommitVidPnArg->hFunctionalVidPn, pVidPnInterface,
3838 (PVBOXWDDM_ALLOCATION)pCommitVidPnArg->hPrimaryAllocation,
3839 paSources, paTargets);
3840 if (!NT_SUCCESS(Status))
3841 {
3842 WARN(("VBoxVidPnCommitAll for current VidPn failed Status 0x%x", Status));
3843 break;
3844 }
3845 }
3846
3847 Assert(NT_SUCCESS(Status));
3848 pDevExt->u.primary.hCommittedVidPn = pCommitVidPnArg->hFunctionalVidPn;
3849 VBoxVidPnSourcesCopy(pDevExt->aSources, paSources, VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
3850 VBoxVidPnTargetsCopy(pDevExt->aTargets, paTargets, VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
3851
3852 VBoxDumpSourceTargetArrays(paSources, paTargets, VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
3853
3854#ifdef VBOX_WITH_MESA3D
3855 if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VMSVGA)
3856 {
3857 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
3858 {
3859 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[i];
3860
3861 LOG(("Source [%d]: visible %d, blanked %d", i, pSource->bVisible, pSource->bBlankedByPowerOff));
3862
3863 /* Update positions of all screens. */
3864 vboxWddmDisplaySettingsQueryPos(pDevExt, i, &pSource->VScreenPos);
3865
3866 GaVidPnSourceReport(pDevExt, pSource);
3867 }
3868
3869 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
3870 {
3871 VBOXWDDM_TARGET *pTarget = &pDevExt->aTargets[i];
3872 Assert(pTarget->u32Id == (unsigned)i);
3873 if (pTarget->VidPnSourceId != D3DDDI_ID_UNINITIALIZED)
3874 {
3875 continue;
3876 }
3877
3878 LOG(("Target [%d]: blanked %d", i, pTarget->fBlankedByPowerOff));
3879
3880 if (pTarget->fBlankedByPowerOff)
3881 {
3882 GaScreenDefine(pDevExt->pGa, 0, pTarget->u32Id, 0, 0, 0, 0, true);
3883 }
3884 else
3885 {
3886 GaScreenDestroy(pDevExt->pGa, pTarget->u32Id);
3887 }
3888 }
3889
3890 break;
3891 }
3892#endif
3893 vboxWddmGhDisplayCheckSetInfo(pDevExt);
3894 } while (0);
3895
3896 RTMemFree(paSources);
3897 RTMemFree(paTargets);
3898
3899 LOG(("LEAVE, status(0x%x), hAdapter(0x%x)", Status, hAdapter));
3900
3901 return Status;
3902}
3903
3904NTSTATUS
3905APIENTRY
3906DxgkDdiUpdateActiveVidPnPresentPath(
3907 CONST HANDLE hAdapter,
3908 CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPathArg
3909 )
3910{
3911 RT_NOREF(hAdapter, pUpdateActiveVidPnPresentPathArg);
3912 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3913
3914 AssertBreakpoint();
3915
3916 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3917
3918 return STATUS_SUCCESS;
3919}
3920
3921NTSTATUS
3922APIENTRY
3923DxgkDdiRecommendMonitorModes(
3924 CONST HANDLE hAdapter,
3925 CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModesArg
3926 )
3927{
3928 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3929
3930 vboxVDbgBreakFv();
3931
3932 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3933
3934 NTSTATUS Status = VBoxVidPnRecommendMonitorModes(pDevExt, pRecommendMonitorModesArg->VideoPresentTargetId,
3935 pRecommendMonitorModesArg->hMonitorSourceModeSet, pRecommendMonitorModesArg->pMonitorSourceModeSetInterface);
3936 if (!NT_SUCCESS(Status))
3937 {
3938 WARN(("VBoxVidPnRecommendMonitorModes failed %#x", Status));
3939 return Status;
3940 }
3941
3942 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3943
3944 return STATUS_SUCCESS;
3945}
3946
3947NTSTATUS
3948APIENTRY
3949DxgkDdiRecommendVidPnTopology(
3950 CONST HANDLE hAdapter,
3951 CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopologyArg
3952 )
3953{
3954 RT_NOREF(hAdapter, pRecommendVidPnTopologyArg);
3955 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3956
3957 vboxVDbgBreakFv();
3958
3959 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3960
3961 return STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY;
3962}
3963
3964NTSTATUS
3965APIENTRY
3966DxgkDdiGetScanLine(
3967 CONST HANDLE hAdapter,
3968 DXGKARG_GETSCANLINE* pGetScanLine)
3969{
3970 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3971
3972 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3973
3974#ifdef DEBUG_misha
3975// RT_BREAKPOINT();
3976#endif
3977
3978 NTSTATUS Status = VBoxWddmSlGetScanLine(pDevExt, pGetScanLine);
3979
3980 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3981
3982 return Status;
3983}
3984
3985NTSTATUS
3986APIENTRY
3987DxgkDdiStopCapture(
3988 CONST HANDLE hAdapter,
3989 CONST DXGKARG_STOPCAPTURE* pStopCapture)
3990{
3991 RT_NOREF(hAdapter, pStopCapture);
3992 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3993
3994 AssertBreakpoint();
3995
3996 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3997
3998 return STATUS_SUCCESS;
3999}
4000
4001NTSTATUS
4002APIENTRY
4003DxgkDdiControlInterrupt(
4004 CONST HANDLE hAdapter,
4005 CONST DXGK_INTERRUPT_TYPE InterruptType,
4006 BOOLEAN Enable
4007 )
4008{
4009 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
4010
4011 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
4012 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
4013
4014 switch (InterruptType)
4015 {
4016 case DXGK_INTERRUPT_DISPLAYONLY_VSYNC:
4017 case DXGK_INTERRUPT_CRTC_VSYNC:
4018 {
4019 Status = VBoxWddmSlEnableVSyncNotification(pDevExt, Enable);
4020 if (NT_SUCCESS(Status))
4021 Status = STATUS_SUCCESS; /* <- sanity */
4022 else
4023 WARN(("VSYNC Interrupt control failed Enable(%d), Status(0x%x)", Enable, Status));
4024 break;
4025 }
4026 case DXGK_INTERRUPT_DMA_COMPLETED:
4027 case DXGK_INTERRUPT_DMA_PREEMPTED:
4028 case DXGK_INTERRUPT_DMA_FAULTED:
4029 WARN(("Unexpected interrupt type! %d", InterruptType));
4030 break;
4031 default:
4032 WARN(("UNSUPPORTED interrupt type! %d", InterruptType));
4033 break;
4034 }
4035
4036 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
4037
4038 return Status;
4039}
4040
4041NTSTATUS
4042APIENTRY
4043DxgkDdiCreateOverlay(
4044 CONST HANDLE hAdapter,
4045 DXGKARG_CREATEOVERLAY *pCreateOverlay)
4046{
4047 LOGF(("ENTER, hAdapter(0x%p)", hAdapter));
4048
4049 NTSTATUS Status = STATUS_SUCCESS;
4050
4051#ifdef VBOX_WITH_VIDEOHWACCEL
4052 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
4053 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)vboxWddmMemAllocZero(sizeof (VBOXWDDM_OVERLAY));
4054 Assert(pOverlay);
4055 if (pOverlay)
4056 {
4057 int rc = vboxVhwaHlpOverlayCreate(pDevExt, pCreateOverlay->VidPnSourceId, &pCreateOverlay->OverlayInfo, pOverlay);
4058 AssertRC(rc);
4059 if (RT_SUCCESS(rc))
4060 {
4061 pCreateOverlay->hOverlay = pOverlay;
4062 }
4063 else
4064 {
4065 vboxWddmMemFree(pOverlay);
4066 Status = STATUS_UNSUCCESSFUL;
4067 }
4068 }
4069 else
4070 Status = STATUS_NO_MEMORY;
4071#else
4072 RT_NOREF(hAdapter, pCreateOverlay);
4073#endif
4074
4075 LOGF(("LEAVE, hAdapter(0x%p)", hAdapter));
4076
4077 return Status;
4078}
4079
4080NTSTATUS
4081APIENTRY
4082DxgkDdiDestroyDevice(
4083 CONST HANDLE hDevice)
4084{
4085 /* DxgkDdiDestroyDevice should be made pageable. */
4086 PAGED_CODE();
4087
4088 LOGF(("ENTER, hDevice(0x%x)", hDevice));
4089
4090 vboxVDbgBreakFv();
4091
4092#ifdef VBOX_WITH_MESA3D
4093 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)hDevice;
4094 PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
4095 if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VMSVGA)
4096 {
4097 GaDeviceDestroy(pDevExt->pGa, pDevice);
4098 }
4099#endif
4100
4101 vboxWddmMemFree(hDevice);
4102
4103 LOGF(("LEAVE, "));
4104
4105 return STATUS_SUCCESS;
4106}
4107
4108
4109
4110/*
4111 * DxgkDdiOpenAllocation
4112 */
4113NTSTATUS
4114APIENTRY
4115DxgkDdiOpenAllocation(
4116 CONST HANDLE hDevice,
4117 CONST DXGKARG_OPENALLOCATION *pOpenAllocation)
4118{
4119 /* DxgkDdiOpenAllocation should be made pageable. */
4120 PAGED_CODE();
4121
4122 LOGF(("ENTER, hDevice(0x%x)", hDevice));
4123
4124 vboxVDbgBreakFv();
4125
4126 NTSTATUS Status = STATUS_SUCCESS;
4127 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)hDevice;
4128 PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
4129 PVBOXWDDM_RCINFO pRcInfo = NULL;
4130 if (pOpenAllocation->PrivateDriverSize)
4131 {
4132 Assert(pOpenAllocation->pPrivateDriverData);
4133 if (pOpenAllocation->PrivateDriverSize == sizeof (VBOXWDDM_RCINFO))
4134 {
4135 pRcInfo = (PVBOXWDDM_RCINFO)pOpenAllocation->pPrivateDriverData;
4136 Assert(pRcInfo->cAllocInfos == pOpenAllocation->NumAllocations);
4137 }
4138 else
4139 {
4140 WARN(("Invalid PrivateDriverSize %d", pOpenAllocation->PrivateDriverSize));
4141 Status = STATUS_INVALID_PARAMETER;
4142 }
4143 }
4144
4145 if (Status == STATUS_SUCCESS)
4146 {
4147 UINT i = 0;
4148 for (; i < pOpenAllocation->NumAllocations; ++i)
4149 {
4150 DXGK_OPENALLOCATIONINFO* pInfo = &pOpenAllocation->pOpenAllocation[i];
4151 Assert(pInfo->PrivateDriverDataSize == sizeof (VBOXWDDM_ALLOCINFO));
4152 Assert(pInfo->pPrivateDriverData);
4153 PVBOXWDDM_ALLOCATION pAllocation = vboxWddmGetAllocationFromHandle(pDevExt, pInfo->hAllocation);
4154 if (!pAllocation)
4155 {
4156 WARN(("invalid handle"));
4157 Status = STATUS_INVALID_PARAMETER;
4158 break;
4159 }
4160
4161#ifdef DEBUG
4162 Assert(!pAllocation->fAssumedDeletion);
4163#endif
4164 if (pRcInfo)
4165 {
4166 Assert(pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC);
4167
4168 if (pInfo->PrivateDriverDataSize != sizeof (VBOXWDDM_ALLOCINFO)
4169 || !pInfo->pPrivateDriverData)
4170 {
4171 WARN(("invalid data size"));
4172 Status = STATUS_INVALID_PARAMETER;
4173 break;
4174 }
4175
4176#ifdef VBOX_WITH_VIDEOHWACCEL
4177 PVBOXWDDM_ALLOCINFO pAllocInfo = (PVBOXWDDM_ALLOCINFO)pInfo->pPrivateDriverData;
4178
4179 if (pRcInfo->RcDesc.fFlags.Overlay)
4180 {
4181 /* we have queried host for some surface info, like pitch & size,
4182 * need to return it back to the UMD (User Mode Drive) */
4183 pAllocInfo->SurfDesc = pAllocation->AllocData.SurfDesc;
4184 /* success, just continue */
4185 }
4186#endif
4187 }
4188
4189 KIRQL OldIrql;
4190 PVBOXWDDM_OPENALLOCATION pOa;
4191 KeAcquireSpinLock(&pAllocation->OpenLock, &OldIrql);
4192 pOa = VBoxWddmOaSearchLocked(pDevice, pAllocation);
4193 if (pOa)
4194 {
4195 ++pOa->cOpens;
4196 ++pAllocation->cOpens;
4197 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
4198 }
4199 else
4200 {
4201 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
4202 pOa = (PVBOXWDDM_OPENALLOCATION)vboxWddmMemAllocZero(sizeof (VBOXWDDM_OPENALLOCATION));
4203 if (!pOa)
4204 {
4205 WARN(("failed to allocation alloc info"));
4206 Status = STATUS_INSUFFICIENT_RESOURCES;
4207 break;
4208 }
4209
4210 pOa->hAllocation = pInfo->hAllocation;
4211 pOa->pAllocation = pAllocation;
4212 pOa->pDevice = pDevice;
4213 pOa->cOpens = 1;
4214
4215 PVBOXWDDM_OPENALLOCATION pConcurrentOa;
4216 KeAcquireSpinLock(&pAllocation->OpenLock, &OldIrql);
4217 pConcurrentOa = VBoxWddmOaSearchLocked(pDevice, pAllocation);
4218 if (!pConcurrentOa)
4219 InsertHeadList(&pAllocation->OpenList, &pOa->ListEntry);
4220 else
4221 ++pConcurrentOa->cOpens;
4222 ++pAllocation->cOpens;
4223 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
4224 if (pConcurrentOa)
4225 {
4226 vboxWddmMemFree(pOa);
4227 pOa = pConcurrentOa;
4228 }
4229 }
4230
4231 pInfo->hDeviceSpecificAllocation = pOa;
4232 }
4233
4234 if (Status != STATUS_SUCCESS)
4235 {
4236 for (UINT j = 0; j < i; ++j)
4237 {
4238 DXGK_OPENALLOCATIONINFO* pInfo2Free = &pOpenAllocation->pOpenAllocation[j];
4239 PVBOXWDDM_OPENALLOCATION pOa2Free = (PVBOXWDDM_OPENALLOCATION)pInfo2Free->hDeviceSpecificAllocation;
4240 VBoxWddmOaRelease(pOa2Free);
4241 }
4242 }
4243 }
4244 LOGF(("LEAVE, hDevice(0x%x)", hDevice));
4245
4246 return Status;
4247}
4248
4249NTSTATUS
4250APIENTRY
4251DxgkDdiCloseAllocation(
4252 CONST HANDLE hDevice,
4253 CONST DXGKARG_CLOSEALLOCATION* pCloseAllocation)
4254{
4255 RT_NOREF(hDevice);
4256 /* DxgkDdiCloseAllocation should be made pageable. */
4257 PAGED_CODE();
4258
4259 LOGF(("ENTER, hDevice(0x%x)", hDevice));
4260
4261 vboxVDbgBreakFv();
4262
4263 for (UINT i = 0; i < pCloseAllocation->NumAllocations; ++i)
4264 {
4265 PVBOXWDDM_OPENALLOCATION pOa2Free = (PVBOXWDDM_OPENALLOCATION)pCloseAllocation->pOpenHandleList[i];
4266 PVBOXWDDM_ALLOCATION pAllocation = pOa2Free->pAllocation;
4267 Assert(pAllocation->cShRcRefs >= pOa2Free->cShRcRefs);
4268 pAllocation->cShRcRefs -= pOa2Free->cShRcRefs;
4269 VBoxWddmOaRelease(pOa2Free);
4270 }
4271
4272 LOGF(("LEAVE, hDevice(0x%x)", hDevice));
4273
4274 return STATUS_SUCCESS;
4275}
4276
4277#define VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE() (VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_PRESENT_BLT))
4278#define VBOXVDMACMD_DMA_PRESENT_BLT_SIZE(_c) (VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects[_c]))
4279
4280DECLINLINE(BOOLEAN) vboxWddmPixFormatConversionSupported(D3DDDIFORMAT From, D3DDDIFORMAT To)
4281{
4282 Assert(From != D3DDDIFMT_UNKNOWN);
4283 Assert(To != D3DDDIFMT_UNKNOWN);
4284 Assert(From == To);
4285 return From == To;
4286}
4287
4288NTSTATUS
4289APIENTRY
4290DxgkDdiUpdateOverlay(
4291 CONST HANDLE hOverlay,
4292 CONST DXGKARG_UPDATEOVERLAY *pUpdateOverlay)
4293{
4294 LOGF(("ENTER, hOverlay(0x%p)", hOverlay));
4295
4296 NTSTATUS Status = STATUS_SUCCESS;
4297
4298#ifdef VBOX_WITH_VIDEOHWACCEL
4299 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)hOverlay;
4300 AssertPtr(pOverlay);
4301 int rc = vboxVhwaHlpOverlayUpdate(pOverlay, &pUpdateOverlay->OverlayInfo);
4302 AssertRC(rc);
4303 if (RT_FAILURE(rc))
4304 Status = STATUS_UNSUCCESSFUL;
4305#else
4306 RT_NOREF(hOverlay, pUpdateOverlay);
4307#endif
4308
4309 LOGF(("LEAVE, hOverlay(0x%p)", hOverlay));
4310 return Status;
4311}
4312
4313NTSTATUS
4314APIENTRY
4315DxgkDdiFlipOverlay(
4316 CONST HANDLE hOverlay,
4317 CONST DXGKARG_FLIPOVERLAY *pFlipOverlay)
4318{
4319 LOGF(("ENTER, hOverlay(0x%p)", hOverlay));
4320
4321 NTSTATUS Status = STATUS_SUCCESS;
4322
4323#ifdef VBOX_WITH_VIDEOHWACCEL
4324 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)hOverlay;
4325 AssertPtr(pOverlay);
4326 int rc = vboxVhwaHlpOverlayFlip(pOverlay, pFlipOverlay);
4327 AssertRC(rc);
4328 if (RT_FAILURE(rc))
4329 Status = STATUS_UNSUCCESSFUL;
4330#else
4331 RT_NOREF(hOverlay, pFlipOverlay);
4332#endif
4333
4334 LOGF(("LEAVE, hOverlay(0x%p)", hOverlay));
4335
4336 return Status;
4337}
4338
4339NTSTATUS
4340APIENTRY
4341DxgkDdiDestroyOverlay(
4342 CONST HANDLE hOverlay)
4343{
4344 LOGF(("ENTER, hOverlay(0x%p)", hOverlay));
4345
4346 NTSTATUS Status = STATUS_SUCCESS;
4347
4348#ifdef VBOX_WITH_VIDEOHWACCEL
4349 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)hOverlay;
4350 AssertPtr(pOverlay);
4351 int rc = vboxVhwaHlpOverlayDestroy(pOverlay);
4352 AssertRC(rc);
4353 if (RT_SUCCESS(rc))
4354 vboxWddmMemFree(pOverlay);
4355 else
4356 Status = STATUS_UNSUCCESSFUL;
4357#else
4358 RT_NOREF(hOverlay);
4359#endif
4360
4361 LOGF(("LEAVE, hOverlay(0x%p)", hOverlay));
4362
4363 return Status;
4364}
4365
4366/**
4367 * DxgkDdiCreateContext
4368 */
4369NTSTATUS
4370APIENTRY
4371DxgkDdiCreateContext(
4372 CONST HANDLE hDevice,
4373 DXGKARG_CREATECONTEXT *pCreateContext)
4374{
4375 /* DxgkDdiCreateContext should be made pageable */
4376 PAGED_CODE();
4377
4378 LOGF(("ENTER, hDevice(0x%x)", hDevice));
4379
4380 vboxVDbgBreakFv();
4381
4382 if (pCreateContext->NodeOrdinal >= VBOXWDDM_NUM_NODES)
4383 {
4384 WARN(("Invalid NodeOrdinal (%d), expected to be less that (%d)\n", pCreateContext->NodeOrdinal, VBOXWDDM_NUM_NODES));
4385 return STATUS_INVALID_PARAMETER;
4386 }
4387
4388 NTSTATUS Status = STATUS_SUCCESS;
4389 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)hDevice;
4390 PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
4391 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)vboxWddmMemAllocZero(sizeof (VBOXWDDM_CONTEXT));
4392 Assert(pContext);
4393 if (pContext)
4394 {
4395 pContext->pDevice = pDevice;
4396 pContext->hContext = pCreateContext->hContext;
4397 pContext->EngineAffinity = pCreateContext->EngineAffinity;
4398 pContext->NodeOrdinal = pCreateContext->NodeOrdinal;
4399 vboxVideoCmCtxInitEmpty(&pContext->CmContext);
4400 if (pCreateContext->Flags.SystemContext || pCreateContext->PrivateDriverDataSize == 0)
4401 {
4402 Assert(pCreateContext->PrivateDriverDataSize == 0);
4403 Assert(!pCreateContext->pPrivateDriverData);
4404 Assert(pCreateContext->Flags.Value <= 2); /* 2 is a GDI context in Win7 */
4405 pContext->enmType = VBOXWDDM_CONTEXT_TYPE_SYSTEM;
4406
4407 if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VBOX)
4408 {
4409 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
4410 {
4411 vboxWddmDisplaySettingsCheckPos(pDevExt, i);
4412 }
4413 }
4414 Status = STATUS_SUCCESS;
4415 }
4416 else
4417 {
4418 Assert(pCreateContext->Flags.Value == 0);
4419 Assert(pCreateContext->PrivateDriverDataSize == sizeof (VBOXWDDM_CREATECONTEXT_INFO));
4420 Assert(pCreateContext->pPrivateDriverData);
4421 if (pCreateContext->PrivateDriverDataSize == sizeof (VBOXWDDM_CREATECONTEXT_INFO))
4422 {
4423 PVBOXWDDM_CREATECONTEXT_INFO pInfo = (PVBOXWDDM_CREATECONTEXT_INFO)pCreateContext->pPrivateDriverData;
4424 switch (pInfo->enmType)
4425 {
4426 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_RESIZE:
4427 {
4428 pContext->enmType = pInfo->enmType;
4429 ASMAtomicIncU32(&pDevExt->cContextsDispIfResize);
4430 break;
4431 }
4432 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_SEAMLESS:
4433 {
4434 pContext->enmType = pInfo->enmType;
4435 Status = vboxVideoCmCtxAdd(&pDevice->pAdapter->SeamlessCtxMgr, &pContext->CmContext, (HANDLE)pInfo->u.vbox.hUmEvent, pInfo->u.vbox.u64UmInfo);
4436 if (!NT_SUCCESS(Status))
4437 {
4438 WARN(("vboxVideoCmCtxAdd failed, Status 0x%x", Status));
4439 }
4440 break;
4441 }
4442#ifdef VBOX_WITH_MESA3D
4443 case VBOXWDDM_CONTEXT_TYPE_GA_3D:
4444 {
4445 pContext->enmType = VBOXWDDM_CONTEXT_TYPE_GA_3D;
4446 Status = GaContextCreate(pDevExt->pGa, pInfo, pContext);
4447 break;
4448 }
4449#endif
4450 default:
4451 {
4452 WARN(("unsupported context type %d", pInfo->enmType));
4453 Status = STATUS_INVALID_PARAMETER;
4454 break;
4455 }
4456 }
4457 }
4458 }
4459
4460 if (Status == STATUS_SUCCESS)
4461 {
4462 pCreateContext->hContext = pContext;
4463 pCreateContext->ContextInfo.DmaBufferSize = VBOXWDDM_C_DMA_BUFFER_SIZE;
4464 pCreateContext->ContextInfo.DmaBufferSegmentSet = 0;
4465 pCreateContext->ContextInfo.DmaBufferPrivateDataSize = VBOXWDDM_C_DMA_PRIVATEDATA_SIZE;
4466 pCreateContext->ContextInfo.AllocationListSize = VBOXWDDM_C_ALLOC_LIST_SIZE;
4467 pCreateContext->ContextInfo.PatchLocationListSize = VBOXWDDM_C_PATH_LOCATION_LIST_SIZE;
4468 //#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
4469 //# error port to Win7 DDI
4470 // //pCreateContext->ContextInfo.DmaBufferAllocationGroup = ???;
4471 //#endif // DXGKDDI_INTERFACE_VERSION
4472 }
4473 else
4474 vboxWddmMemFree(pContext);
4475 }
4476 else
4477 Status = STATUS_NO_MEMORY;
4478
4479 LOGF(("LEAVE, hDevice(0x%x)", hDevice));
4480
4481 return Status;
4482}
4483
4484NTSTATUS
4485APIENTRY
4486DxgkDdiDestroyContext(
4487 CONST HANDLE hContext)
4488{
4489 LOGF(("ENTER, hContext(0x%x)", hContext));
4490 vboxVDbgBreakFv();
4491 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
4492 PVBOXMP_DEVEXT pDevExt = pContext->pDevice->pAdapter;
4493 NTSTATUS Status = STATUS_SUCCESS;
4494
4495 switch(pContext->enmType)
4496 {
4497 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_RESIZE:
4498 {
4499 uint32_t cContexts = ASMAtomicDecU32(&pDevExt->cContextsDispIfResize);
4500 Assert(cContexts < UINT32_MAX/2);
4501 if (!cContexts)
4502 {
4503 if (pDevExt->fDisableTargetUpdate)
4504 {
4505 pDevExt->fDisableTargetUpdate = FALSE;
4506 vboxWddmGhDisplayCheckSetInfoEx(pDevExt, true);
4507 }
4508 }
4509 break;
4510 }
4511 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_SEAMLESS:
4512 {
4513 Status = vboxVideoCmCtxRemove(&pContext->pDevice->pAdapter->SeamlessCtxMgr, &pContext->CmContext);
4514 if (!NT_SUCCESS(Status))
4515 WARN(("vboxVideoCmCtxRemove failed, Status 0x%x", Status));
4516
4517 Assert(pContext->CmContext.pSession == NULL);
4518 break;
4519 }
4520#ifdef VBOX_WITH_MESA3D
4521 case VBOXWDDM_CONTEXT_TYPE_GA_3D:
4522 {
4523 Status = GaContextDestroy(pDevExt->pGa, pContext);
4524 break;
4525 }
4526#endif
4527 default:
4528 break;
4529 }
4530
4531 Status = vboxVideoAMgrCtxDestroy(&pContext->AllocContext);
4532 if (NT_SUCCESS(Status))
4533 {
4534 Status = vboxVideoCmCtxRemove(&pContext->pDevice->pAdapter->CmMgr, &pContext->CmContext);
4535 if (NT_SUCCESS(Status))
4536 vboxWddmMemFree(pContext);
4537 else
4538 WARN(("vboxVideoCmCtxRemove failed, Status 0x%x", Status));
4539 }
4540 else
4541 WARN(("vboxVideoAMgrCtxDestroy failed, Status 0x%x", Status));
4542
4543 LOGF(("LEAVE, hContext(0x%x)", hContext));
4544
4545 return Status;
4546}
4547
4548NTSTATUS
4549APIENTRY
4550DxgkDdiLinkDevice(
4551 __in CONST PDEVICE_OBJECT PhysicalDeviceObject,
4552 __in CONST PVOID MiniportDeviceContext,
4553 __inout PLINKED_DEVICE LinkedDevice
4554 )
4555{
4556 RT_NOREF(PhysicalDeviceObject, MiniportDeviceContext, LinkedDevice);
4557 LOGF(("ENTER, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
4558 vboxVDbgBreakFv();
4559 AssertBreakpoint();
4560 LOGF(("LEAVE, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
4561 return STATUS_NOT_IMPLEMENTED;
4562}
4563
4564NTSTATUS
4565APIENTRY
4566DxgkDdiSetDisplayPrivateDriverFormat(
4567 CONST HANDLE hAdapter,
4568 /*CONST*/ DXGKARG_SETDISPLAYPRIVATEDRIVERFORMAT* pSetDisplayPrivateDriverFormat
4569 )
4570{
4571 RT_NOREF(hAdapter, pSetDisplayPrivateDriverFormat);
4572 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
4573 vboxVDbgBreakFv();
4574 AssertBreakpoint();
4575 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
4576 return STATUS_SUCCESS;
4577}
4578
4579NTSTATUS APIENTRY CALLBACK DxgkDdiRestartFromTimeout(IN_CONST_HANDLE hAdapter)
4580{
4581 RT_NOREF(hAdapter);
4582 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
4583 vboxVDbgBreakFv();
4584 AssertBreakpoint();
4585 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
4586 return STATUS_SUCCESS;
4587}
4588
4589static NTSTATUS APIENTRY DxgkDdiQueryVidPnHWCapability(
4590 __in const HANDLE hAdapter,
4591 __inout DXGKARG_QUERYVIDPNHWCAPABILITY *pVidPnHWCaps
4592 )
4593{
4594 RT_NOREF(hAdapter);
4595 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
4596 vboxVDbgBreakF();
4597 pVidPnHWCaps->VidPnHWCaps.DriverRotation = 0;
4598 pVidPnHWCaps->VidPnHWCaps.DriverScaling = 0;
4599 pVidPnHWCaps->VidPnHWCaps.DriverCloning = 0;
4600 pVidPnHWCaps->VidPnHWCaps.DriverColorConvert = 0;
4601 pVidPnHWCaps->VidPnHWCaps.DriverLinkedAdapaterOutput = 0;
4602 pVidPnHWCaps->VidPnHWCaps.DriverRemoteDisplay = 0;
4603 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
4604 return STATUS_SUCCESS;
4605}
4606
4607static NTSTATUS APIENTRY DxgkDdiPresentDisplayOnly(
4608 _In_ const HANDLE hAdapter,
4609 _In_ const DXGKARG_PRESENT_DISPLAYONLY *pPresentDisplayOnly
4610 )
4611{
4612 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
4613 vboxVDbgBreakFv();
4614
4615 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
4616#ifdef VBOX_WITH_MESA3D
4617 if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VMSVGA)
4618 {
4619 return GaDxgkDdiPresentDisplayOnly(hAdapter, pPresentDisplayOnly);
4620 }
4621#endif
4622 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pPresentDisplayOnly->VidPnSourceId];
4623 Assert(pSource->AllocData.Addr.SegmentId == 1);
4624 VBOXWDDM_ALLOC_DATA SrcAllocData;
4625 SrcAllocData.SurfDesc.width = pPresentDisplayOnly->Pitch * pPresentDisplayOnly->BytesPerPixel;
4626 SrcAllocData.SurfDesc.height = ~0UL;
4627 switch (pPresentDisplayOnly->BytesPerPixel)
4628 {
4629 case 4:
4630 SrcAllocData.SurfDesc.format = D3DDDIFMT_A8R8G8B8;
4631 break;
4632 case 3:
4633 SrcAllocData.SurfDesc.format = D3DDDIFMT_R8G8B8;
4634 break;
4635 case 2:
4636 SrcAllocData.SurfDesc.format = D3DDDIFMT_R5G6B5;
4637 break;
4638 case 1:
4639 SrcAllocData.SurfDesc.format = D3DDDIFMT_P8;
4640 break;
4641 default:
4642 WARN(("Unknown format"));
4643 SrcAllocData.SurfDesc.format = D3DDDIFMT_UNKNOWN;
4644 break;
4645 }
4646 SrcAllocData.SurfDesc.bpp = pPresentDisplayOnly->BytesPerPixel >> 3;
4647 SrcAllocData.SurfDesc.pitch = pPresentDisplayOnly->Pitch;
4648 SrcAllocData.SurfDesc.depth = 1;
4649 SrcAllocData.SurfDesc.slicePitch = pPresentDisplayOnly->Pitch;
4650 SrcAllocData.SurfDesc.cbSize = ~0UL;
4651 SrcAllocData.Addr.SegmentId = 0;
4652 SrcAllocData.Addr.pvMem = pPresentDisplayOnly->pSource;
4653 SrcAllocData.hostID = 0;
4654
4655 RECT UpdateRect;
4656 RT_ZERO(UpdateRect);
4657 BOOLEAN bUpdateRectInited = FALSE;
4658
4659 for (UINT i = 0; i < pPresentDisplayOnly->NumMoves; ++i)
4660 {
4661 if (!bUpdateRectInited)
4662 {
4663 UpdateRect = pPresentDisplayOnly->pMoves[i].DestRect;
4664 bUpdateRectInited = TRUE;
4665 }
4666 else
4667 vboxWddmRectUnite(&UpdateRect, &pPresentDisplayOnly->pMoves[i].DestRect);
4668 vboxVdmaGgDmaBltPerform(pDevExt, &SrcAllocData, &pPresentDisplayOnly->pMoves[i].DestRect, &pSource->AllocData, &pPresentDisplayOnly->pMoves[i].DestRect);
4669 }
4670
4671 for (UINT i = 0; i < pPresentDisplayOnly->NumDirtyRects; ++i)
4672 {
4673 RECT *pDirtyRect = &pPresentDisplayOnly->pDirtyRect[i];
4674
4675 if (pDirtyRect->left >= pDirtyRect->right || pDirtyRect->top >= pDirtyRect->bottom)
4676 {
4677 WARN(("Wrong dirty rect (%d, %d)-(%d, %d)",
4678 pDirtyRect->left, pDirtyRect->top, pDirtyRect->right, pDirtyRect->bottom));
4679 continue;
4680 }
4681
4682 vboxVdmaGgDmaBltPerform(pDevExt, &SrcAllocData, pDirtyRect, &pSource->AllocData, pDirtyRect);
4683
4684 if (!bUpdateRectInited)
4685 {
4686 UpdateRect = *pDirtyRect;
4687 bUpdateRectInited = TRUE;
4688 }
4689 else
4690 vboxWddmRectUnite(&UpdateRect, pDirtyRect);
4691 }
4692
4693 if (bUpdateRectInited && pSource->bVisible)
4694 {
4695 VBOXVBVA_OP_WITHLOCK(ReportDirtyRect, pDevExt, pSource, &UpdateRect);
4696 }
4697
4698 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
4699 return STATUS_SUCCESS;
4700}
4701
4702static NTSTATUS DxgkDdiStopDeviceAndReleasePostDisplayOwnership(
4703 _In_ PVOID MiniportDeviceContext,
4704 _In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
4705 _Out_ PDXGK_DISPLAY_INFORMATION DisplayInfo
4706)
4707{
4708 RT_NOREF(MiniportDeviceContext, TargetId, DisplayInfo);
4709 LOGF(("ENTER, hAdapter(0x%x)", MiniportDeviceContext));
4710 vboxVDbgBreakFv();
4711 AssertBreakpoint();
4712 LOGF(("LEAVE, hAdapter(0x%x)", MiniportDeviceContext));
4713 return STATUS_NOT_SUPPORTED;
4714}
4715
4716static NTSTATUS DxgkDdiSystemDisplayEnable(
4717 _In_ PVOID MiniportDeviceContext,
4718 _In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
4719 _In_ PDXGKARG_SYSTEM_DISPLAY_ENABLE_FLAGS Flags,
4720 _Out_ UINT *Width,
4721 _Out_ UINT *Height,
4722 _Out_ D3DDDIFORMAT *ColorFormat
4723 )
4724{
4725 RT_NOREF(MiniportDeviceContext, TargetId, Flags, Width, Height, ColorFormat);
4726 LOGF(("ENTER, hAdapter(0x%x)", MiniportDeviceContext));
4727 vboxVDbgBreakFv();
4728 AssertBreakpoint();
4729 LOGF(("LEAVE, hAdapter(0x%x)", MiniportDeviceContext));
4730 return STATUS_NOT_SUPPORTED;
4731}
4732
4733static VOID DxgkDdiSystemDisplayWrite(
4734 _In_ PVOID MiniportDeviceContext,
4735 _In_ PVOID Source,
4736 _In_ UINT SourceWidth,
4737 _In_ UINT SourceHeight,
4738 _In_ UINT SourceStride,
4739 _In_ UINT PositionX,
4740 _In_ UINT PositionY
4741)
4742{
4743 RT_NOREF(MiniportDeviceContext, Source, SourceWidth, SourceHeight, SourceStride, PositionX, PositionY);
4744 LOGF(("ENTER, hAdapter(0x%x)", MiniportDeviceContext));
4745 vboxVDbgBreakFv();
4746 AssertBreakpoint();
4747 LOGF(("LEAVE, hAdapter(0x%x)", MiniportDeviceContext));
4748}
4749
4750static NTSTATUS DxgkDdiGetChildContainerId(
4751 _In_ PVOID MiniportDeviceContext,
4752 _In_ ULONG ChildUid,
4753 _Inout_ PDXGK_CHILD_CONTAINER_ID ContainerId
4754)
4755{
4756 RT_NOREF(MiniportDeviceContext, ChildUid, ContainerId);
4757 LOGF(("ENTER, hAdapter(0x%x)", MiniportDeviceContext));
4758 vboxVDbgBreakFv();
4759 AssertBreakpoint();
4760 LOGF(("LEAVE, hAdapter(0x%x)", MiniportDeviceContext));
4761 return STATUS_SUCCESS;
4762}
4763
4764static NTSTATUS APIENTRY DxgkDdiSetPowerComponentFState(
4765 _In_ const HANDLE DriverContext,
4766 UINT ComponentIndex,
4767 UINT FState
4768)
4769{
4770 RT_NOREF(DriverContext, ComponentIndex, FState);
4771 LOGF(("ENTER, DriverContext(0x%x)", DriverContext));
4772 vboxVDbgBreakFv();
4773 AssertBreakpoint();
4774 LOGF(("LEAVE, DriverContext(0x%x)", DriverContext));
4775 return STATUS_SUCCESS;
4776}
4777
4778static NTSTATUS APIENTRY DxgkDdiPowerRuntimeControlRequest(
4779 _In_ const HANDLE DriverContext,
4780 _In_ LPCGUID PowerControlCode,
4781 _In_opt_ PVOID InBuffer,
4782 _In_ SIZE_T InBufferSize,
4783 _Out_opt_ PVOID OutBuffer,
4784 _In_ SIZE_T OutBufferSize,
4785 _Out_opt_ PSIZE_T BytesReturned
4786)
4787{
4788 RT_NOREF(DriverContext, PowerControlCode, InBuffer, InBufferSize, OutBuffer, OutBufferSize, BytesReturned);
4789 LOGF(("ENTER, DriverContext(0x%x)", DriverContext));
4790 vboxVDbgBreakFv();
4791 AssertBreakpoint();
4792 LOGF(("LEAVE, DriverContext(0x%x)", DriverContext));
4793 return STATUS_SUCCESS;
4794}
4795
4796static NTSTATUS DxgkDdiNotifySurpriseRemoval(
4797 _In_ PVOID MiniportDeviceContext,
4798 _In_ DXGK_SURPRISE_REMOVAL_TYPE RemovalType
4799 )
4800{
4801 RT_NOREF(MiniportDeviceContext, RemovalType);
4802 LOGF(("ENTER, hAdapter(0x%x)", MiniportDeviceContext));
4803 vboxVDbgBreakFv();
4804 AssertBreakpoint();
4805 LOGF(("LEAVE, hAdapter(0x%x)", MiniportDeviceContext));
4806 return STATUS_SUCCESS;
4807}
4808
4809static BOOLEAN DxgkDdiInterruptRoutine(const PVOID MiniportDeviceContext,
4810 ULONG MessageNumber)
4811{
4812#ifdef VBOX_WITH_MESA3D
4813 BOOLEAN const fVMSVGA = GaDxgkDdiInterruptRoutine(MiniportDeviceContext, MessageNumber);
4814#else
4815 BOOLEAN const fVMSVGA = FALSE;
4816#endif
4817
4818 BOOLEAN const fHGSMI = DxgkDdiInterruptRoutineLegacy(MiniportDeviceContext, MessageNumber);
4819 return fVMSVGA || fHGSMI;
4820}
4821
4822static VOID DxgkDdiDpcRoutine(const PVOID MiniportDeviceContext)
4823{
4824 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
4825
4826#ifdef VBOX_WITH_MESA3D
4827 GaDxgkDdiDpcRoutine(MiniportDeviceContext);
4828#endif
4829 DxgkDdiDpcRoutineLegacy(MiniportDeviceContext);
4830
4831 pDevExt->u.primary.DxgkInterface.DxgkCbNotifyDpc(pDevExt->u.primary.DxgkInterface.DeviceHandle);
4832}
4833
4834static NTSTATUS vboxWddmInitDisplayOnlyDriver(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)
4835{
4836 KMDDOD_INITIALIZATION_DATA DriverInitializationData = {'\0'};
4837
4838 DriverInitializationData.Version = DXGKDDI_INTERFACE_VERSION_WIN8;
4839
4840 DriverInitializationData.DxgkDdiAddDevice = DxgkDdiAddDevice;
4841 DriverInitializationData.DxgkDdiStartDevice = DxgkDdiStartDevice;
4842 DriverInitializationData.DxgkDdiStopDevice = DxgkDdiStopDevice;
4843 DriverInitializationData.DxgkDdiRemoveDevice = DxgkDdiRemoveDevice;
4844 DriverInitializationData.DxgkDdiDispatchIoRequest = DxgkDdiDispatchIoRequest;
4845 DriverInitializationData.DxgkDdiInterruptRoutine = DxgkDdiInterruptRoutine;
4846 DriverInitializationData.DxgkDdiDpcRoutine = DxgkDdiDpcRoutine;
4847 DriverInitializationData.DxgkDdiQueryChildRelations = DxgkDdiQueryChildRelations;
4848 DriverInitializationData.DxgkDdiQueryChildStatus = DxgkDdiQueryChildStatus;
4849 DriverInitializationData.DxgkDdiQueryDeviceDescriptor = DxgkDdiQueryDeviceDescriptor;
4850 DriverInitializationData.DxgkDdiSetPowerState = DxgkDdiSetPowerState;
4851 DriverInitializationData.DxgkDdiNotifyAcpiEvent = DxgkDdiNotifyAcpiEvent;
4852 DriverInitializationData.DxgkDdiResetDevice = DxgkDdiResetDevice;
4853 DriverInitializationData.DxgkDdiUnload = DxgkDdiUnload;
4854 DriverInitializationData.DxgkDdiQueryInterface = DxgkDdiQueryInterface;
4855 DriverInitializationData.DxgkDdiControlEtwLogging = DxgkDdiControlEtwLogging;
4856 DriverInitializationData.DxgkDdiQueryAdapterInfo = DxgkDdiQueryAdapterInfo;
4857 DriverInitializationData.DxgkDdiSetPalette = DxgkDdiSetPalette;
4858 DriverInitializationData.DxgkDdiSetPointerPosition = DxgkDdiSetPointerPosition;
4859 DriverInitializationData.DxgkDdiSetPointerShape = DxgkDdiSetPointerShape;
4860 DriverInitializationData.DxgkDdiEscape = DxgkDdiEscape;
4861 DriverInitializationData.DxgkDdiCollectDbgInfo = DxgkDdiCollectDbgInfo;
4862 DriverInitializationData.DxgkDdiIsSupportedVidPn = DxgkDdiIsSupportedVidPn;
4863 DriverInitializationData.DxgkDdiRecommendFunctionalVidPn = DxgkDdiRecommendFunctionalVidPn;
4864 DriverInitializationData.DxgkDdiEnumVidPnCofuncModality = DxgkDdiEnumVidPnCofuncModality;
4865 DriverInitializationData.DxgkDdiSetVidPnSourceVisibility = DxgkDdiSetVidPnSourceVisibility;
4866 DriverInitializationData.DxgkDdiCommitVidPn = DxgkDdiCommitVidPn;
4867 DriverInitializationData.DxgkDdiUpdateActiveVidPnPresentPath = DxgkDdiUpdateActiveVidPnPresentPath;
4868 DriverInitializationData.DxgkDdiRecommendMonitorModes = DxgkDdiRecommendMonitorModes;
4869 DriverInitializationData.DxgkDdiQueryVidPnHWCapability = DxgkDdiQueryVidPnHWCapability;
4870 DriverInitializationData.DxgkDdiPresentDisplayOnly = DxgkDdiPresentDisplayOnly;
4871 DriverInitializationData.DxgkDdiStopDeviceAndReleasePostDisplayOwnership = DxgkDdiStopDeviceAndReleasePostDisplayOwnership;
4872 DriverInitializationData.DxgkDdiSystemDisplayEnable = DxgkDdiSystemDisplayEnable;
4873 DriverInitializationData.DxgkDdiSystemDisplayWrite = DxgkDdiSystemDisplayWrite;
4874// DriverInitializationData.DxgkDdiGetChildContainerId = DxgkDdiGetChildContainerId;
4875// DriverInitializationData.DxgkDdiSetPowerComponentFState = DxgkDdiSetPowerComponentFState;
4876// DriverInitializationData.DxgkDdiPowerRuntimeControlRequest = DxgkDdiPowerRuntimeControlRequest;
4877// DriverInitializationData.DxgkDdiNotifySurpriseRemoval = DxgkDdiNotifySurpriseRemoval;
4878
4879 /* Display-only driver is not required to report VSYNC.
4880 * The Microsoft KMDOD driver sample does not implement DxgkDdiControlInterrupt and DxgkDdiGetScanLine.
4881 * The functions must be either both implemented or none implemented.
4882 * Windows 10 10586 guests had problems with VSYNC in display-only driver (#8228).
4883 * Therefore the driver does not implement DxgkDdiControlInterrupt and DxgkDdiGetScanLine.
4884 */
4885
4886 NTSTATUS Status = DxgkInitializeDisplayOnlyDriver(pDriverObject,
4887 pRegistryPath,
4888 &DriverInitializationData);
4889 if (!NT_SUCCESS(Status))
4890 {
4891 WARN(("DxgkInitializeDisplayOnlyDriver failed! Status 0x%x", Status));
4892 }
4893 return Status;
4894}
4895
4896static NTSTATUS vboxWddmInitFullGraphicsDriver(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath, VBOXVIDEO_HWTYPE enmHwType)
4897{
4898 DRIVER_INITIALIZATION_DATA DriverInitializationData = {'\0'};
4899
4900 // Fill in the DriverInitializationData structure and call DxgkInitialize()
4901 if (VBoxQueryWinVersion(NULL) >= WINVERSION_8)
4902 DriverInitializationData.Version = DXGKDDI_INTERFACE_VERSION_WIN8;
4903 else
4904 DriverInitializationData.Version = DXGKDDI_INTERFACE_VERSION_VISTA_SP1;
4905
4906 DriverInitializationData.DxgkDdiAddDevice = DxgkDdiAddDevice;
4907 DriverInitializationData.DxgkDdiStartDevice = DxgkDdiStartDevice;
4908 DriverInitializationData.DxgkDdiStopDevice = DxgkDdiStopDevice;
4909 DriverInitializationData.DxgkDdiRemoveDevice = DxgkDdiRemoveDevice;
4910 DriverInitializationData.DxgkDdiDispatchIoRequest = DxgkDdiDispatchIoRequest;
4911 DriverInitializationData.DxgkDdiInterruptRoutine = DxgkDdiInterruptRoutine;
4912 DriverInitializationData.DxgkDdiDpcRoutine = DxgkDdiDpcRoutine;
4913
4914#ifdef VBOX_WITH_MESA3D
4915 if (enmHwType == VBOXVIDEO_HWTYPE_VMSVGA)
4916 {
4917 DriverInitializationData.DxgkDdiPatch = GaDxgkDdiPatch;
4918 DriverInitializationData.DxgkDdiSubmitCommand = GaDxgkDdiSubmitCommand;
4919 DriverInitializationData.DxgkDdiPreemptCommand = GaDxgkDdiPreemptCommand;
4920 DriverInitializationData.DxgkDdiBuildPagingBuffer = GaDxgkDdiBuildPagingBuffer;
4921 DriverInitializationData.DxgkDdiQueryCurrentFence = GaDxgkDdiQueryCurrentFence;
4922 DriverInitializationData.DxgkDdiRender = GaDxgkDdiRender;
4923 DriverInitializationData.DxgkDdiPresent = GaDxgkDdiPresent;
4924 }
4925 else
4926#endif
4927 {
4928 RT_NOREF(enmHwType);
4929
4930 DriverInitializationData.DxgkDdiPatch = DxgkDdiPatchLegacy;
4931 DriverInitializationData.DxgkDdiSubmitCommand = DxgkDdiSubmitCommandLegacy;
4932 DriverInitializationData.DxgkDdiPreemptCommand = DxgkDdiPreemptCommandLegacy;
4933 DriverInitializationData.DxgkDdiBuildPagingBuffer = DxgkDdiBuildPagingBufferLegacy;
4934 DriverInitializationData.DxgkDdiQueryCurrentFence = DxgkDdiQueryCurrentFenceLegacy;
4935 DriverInitializationData.DxgkDdiRender = DxgkDdiRenderLegacy;
4936 DriverInitializationData.DxgkDdiPresent = DxgkDdiPresentLegacy;
4937 }
4938
4939 DriverInitializationData.DxgkDdiQueryChildRelations = DxgkDdiQueryChildRelations;
4940 DriverInitializationData.DxgkDdiQueryChildStatus = DxgkDdiQueryChildStatus;
4941 DriverInitializationData.DxgkDdiQueryDeviceDescriptor = DxgkDdiQueryDeviceDescriptor;
4942 DriverInitializationData.DxgkDdiSetPowerState = DxgkDdiSetPowerState;
4943 DriverInitializationData.DxgkDdiNotifyAcpiEvent = DxgkDdiNotifyAcpiEvent;
4944 DriverInitializationData.DxgkDdiResetDevice = DxgkDdiResetDevice;
4945 DriverInitializationData.DxgkDdiUnload = DxgkDdiUnload;
4946 DriverInitializationData.DxgkDdiQueryInterface = DxgkDdiQueryInterface;
4947 DriverInitializationData.DxgkDdiControlEtwLogging = DxgkDdiControlEtwLogging;
4948
4949 DriverInitializationData.DxgkDdiQueryAdapterInfo = DxgkDdiQueryAdapterInfo;
4950 DriverInitializationData.DxgkDdiCreateDevice = DxgkDdiCreateDevice;
4951 DriverInitializationData.DxgkDdiCreateAllocation = DxgkDdiCreateAllocation;
4952 DriverInitializationData.DxgkDdiDestroyAllocation = DxgkDdiDestroyAllocation;
4953 DriverInitializationData.DxgkDdiDescribeAllocation = DxgkDdiDescribeAllocation;
4954 DriverInitializationData.DxgkDdiGetStandardAllocationDriverData = DxgkDdiGetStandardAllocationDriverData;
4955 DriverInitializationData.DxgkDdiAcquireSwizzlingRange = DxgkDdiAcquireSwizzlingRange;
4956 DriverInitializationData.DxgkDdiReleaseSwizzlingRange = DxgkDdiReleaseSwizzlingRange;
4957
4958 DriverInitializationData.DxgkDdiSetPalette = DxgkDdiSetPalette;
4959 DriverInitializationData.DxgkDdiSetPointerPosition = DxgkDdiSetPointerPosition;
4960 DriverInitializationData.DxgkDdiSetPointerShape = DxgkDdiSetPointerShape;
4961 DriverInitializationData.DxgkDdiResetFromTimeout = DxgkDdiResetFromTimeout;
4962 DriverInitializationData.DxgkDdiRestartFromTimeout = DxgkDdiRestartFromTimeout;
4963 DriverInitializationData.DxgkDdiEscape = DxgkDdiEscape;
4964 DriverInitializationData.DxgkDdiCollectDbgInfo = DxgkDdiCollectDbgInfo;
4965 DriverInitializationData.DxgkDdiIsSupportedVidPn = DxgkDdiIsSupportedVidPn;
4966 DriverInitializationData.DxgkDdiRecommendFunctionalVidPn = DxgkDdiRecommendFunctionalVidPn;
4967 DriverInitializationData.DxgkDdiEnumVidPnCofuncModality = DxgkDdiEnumVidPnCofuncModality;
4968 DriverInitializationData.DxgkDdiSetVidPnSourceAddress = DxgkDdiSetVidPnSourceAddress;
4969 DriverInitializationData.DxgkDdiSetVidPnSourceVisibility = DxgkDdiSetVidPnSourceVisibility;
4970 DriverInitializationData.DxgkDdiCommitVidPn = DxgkDdiCommitVidPn;
4971 DriverInitializationData.DxgkDdiUpdateActiveVidPnPresentPath = DxgkDdiUpdateActiveVidPnPresentPath;
4972 DriverInitializationData.DxgkDdiRecommendMonitorModes = DxgkDdiRecommendMonitorModes;
4973 DriverInitializationData.DxgkDdiRecommendVidPnTopology = DxgkDdiRecommendVidPnTopology;
4974 DriverInitializationData.DxgkDdiGetScanLine = DxgkDdiGetScanLine;
4975 DriverInitializationData.DxgkDdiStopCapture = DxgkDdiStopCapture;
4976 DriverInitializationData.DxgkDdiControlInterrupt = DxgkDdiControlInterrupt;
4977 DriverInitializationData.DxgkDdiCreateOverlay = DxgkDdiCreateOverlay;
4978
4979 DriverInitializationData.DxgkDdiDestroyDevice = DxgkDdiDestroyDevice;
4980 DriverInitializationData.DxgkDdiOpenAllocation = DxgkDdiOpenAllocation;
4981 DriverInitializationData.DxgkDdiCloseAllocation = DxgkDdiCloseAllocation;
4982
4983 DriverInitializationData.DxgkDdiUpdateOverlay = DxgkDdiUpdateOverlay;
4984 DriverInitializationData.DxgkDdiFlipOverlay = DxgkDdiFlipOverlay;
4985 DriverInitializationData.DxgkDdiDestroyOverlay = DxgkDdiDestroyOverlay;
4986
4987 DriverInitializationData.DxgkDdiCreateContext = DxgkDdiCreateContext;
4988 DriverInitializationData.DxgkDdiDestroyContext = DxgkDdiDestroyContext;
4989
4990 DriverInitializationData.DxgkDdiLinkDevice = NULL; //DxgkDdiLinkDevice;
4991 DriverInitializationData.DxgkDdiSetDisplayPrivateDriverFormat = DxgkDdiSetDisplayPrivateDriverFormat;
4992
4993 if (DriverInitializationData.Version >= DXGKDDI_INTERFACE_VERSION_WIN7)
4994 {
4995 DriverInitializationData.DxgkDdiQueryVidPnHWCapability = DxgkDdiQueryVidPnHWCapability;
4996 }
4997
4998 NTSTATUS Status = DxgkInitialize(pDriverObject,
4999 pRegistryPath,
5000 &DriverInitializationData);
5001 if (!NT_SUCCESS(Status))
5002 {
5003 WARN(("DxgkInitialize failed! Status 0x%x", Status));
5004 }
5005 return Status;
5006}
5007
5008NTSTATUS
5009DriverEntry(
5010 IN PDRIVER_OBJECT DriverObject,
5011 IN PUNICODE_STRING RegistryPath
5012 )
5013{
5014 PAGED_CODE();
5015
5016 vboxVDbgBreakFv();
5017
5018 int irc = RTR0Init(0);
5019 if (RT_FAILURE(irc))
5020 {
5021 RTLogBackdoorPrintf("VBoxWddm: RTR0Init failed: %Rrc!\n", irc);
5022 return STATUS_UNSUCCESSFUL;
5023 }
5024
5025#if 0//def DEBUG_misha
5026 RTLogGroupSettings(0, "+default.e.l.f.l2.l3");
5027#endif
5028
5029#ifdef DEBUG
5030#define VBOXWDDM_BUILD_TYPE "dbg"
5031#else
5032#define VBOXWDDM_BUILD_TYPE "rel"
5033#endif
5034
5035 LOGREL(("VBox WDDM Driver for Windows %s version %d.%d.%dr%d %s, %d bit; Built %s %s",
5036 VBoxQueryWinVersion(NULL) >= WINVERSION_8 ? "8+" : "Vista and 7",
5037 VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV,
5038 VBOXWDDM_BUILD_TYPE,
5039 (sizeof (void*) << 3), __DATE__, __TIME__));
5040
5041 if ( !ARGUMENT_PRESENT(DriverObject)
5042 || !ARGUMENT_PRESENT(RegistryPath))
5043 return STATUS_INVALID_PARAMETER;
5044
5045 vboxWddmDrvCfgInit(RegistryPath);
5046
5047 ULONG major, minor, build;
5048 BOOLEAN fCheckedBuild = PsGetVersion(&major, &minor, &build, NULL); NOREF(fCheckedBuild);
5049 BOOLEAN f3DRequired = FALSE;
5050
5051 LOGREL(("OsVersion(%d, %d, %d)", major, minor, build));
5052
5053 NTSTATUS Status = STATUS_SUCCESS;
5054 /* Initialize VBoxGuest library, which is used for requests which go through VMMDev. */
5055 int rc = VbglR0InitClient();
5056 if (RT_SUCCESS(rc))
5057 {
5058 /* Check whether 3D is required by the guest. */
5059 if (major > 6)
5060 {
5061 /* Windows 10 and newer. */
5062 f3DRequired = TRUE;
5063 }
5064 else if (major == 6)
5065 {
5066 if (minor >= 2)
5067 {
5068 /* Windows 8, 8.1 and 10 preview. */
5069 f3DRequired = TRUE;
5070 }
5071 else
5072 {
5073 f3DRequired = FALSE;
5074 }
5075 }
5076 else
5077 {
5078 WARN(("Unsupported OLDER win version, ignore and assume 3D is NOT required"));
5079 f3DRequired = FALSE;
5080 }
5081
5082 LOG(("3D is %srequired!", f3DRequired? "": "NOT "));
5083
5084 /* Check whether 3D is provided by the host. */
5085 VBOXVIDEO_HWTYPE enmHwType = VBOXVIDEO_HWTYPE_VBOX;
5086 BOOL f3DSupported = FALSE;
5087
5088 if (VBoxVGACfgAvailable())
5089 {
5090 /* New configuration query interface is available. */
5091 uint32_t u32;
5092 if (VBoxVGACfgQuery(VBE_DISPI_CFG_ID_VERSION, &u32, 0))
5093 {
5094 LOGREL(("WDDM: VGA configuration version %d", u32));
5095 }
5096
5097 VBoxVGACfgQuery(VBE_DISPI_CFG_ID_3D, &u32, 0);
5098 f3DSupported = RT_BOOL(u32);
5099
5100 VBoxVGACfgQuery(VBE_DISPI_CFG_ID_VMSVGA, &u32, 0);
5101 if (u32)
5102 {
5103 enmHwType = VBOXVIDEO_HWTYPE_VMSVGA;
5104 }
5105 LOGREL(("WDDM: VGA configuration: 3D %d, hardware type %d", f3DSupported, enmHwType));
5106 }
5107
5108 if (enmHwType == VBOXVIDEO_HWTYPE_VBOX)
5109 {
5110 /* No 3D for legacy adapter. */
5111 f3DSupported = FALSE;
5112 }
5113 else if (enmHwType == VBOXVIDEO_HWTYPE_VMSVGA)
5114 {
5115 /* Nothing. */
5116 }
5117 else
5118 {
5119 /* No supported hardware, fallback to VBox 2D only. */
5120 enmHwType = VBOXVIDEO_HWTYPE_VBOX;
5121 f3DSupported = FALSE;
5122 }
5123
5124 LOGREL(("WDDM: 3D is %ssupported, hardware type %d", f3DSupported? "": "not ", enmHwType));
5125
5126 if (NT_SUCCESS(Status))
5127 {
5128 if (!f3DSupported)
5129 {
5130 /* No 3D support by the host. */
5131 if (VBoxQueryWinVersion(NULL) >= WINVERSION_8)
5132 {
5133 /* Use display only driver for Win8+. */
5134 g_VBoxDisplayOnly = 1;
5135
5136 /* Black list some builds. */
5137 if (major == 6 && minor == 4 && build == 9841)
5138 {
5139 /* W10 Technical preview crashes with display-only driver. */
5140 LOGREL(("3D is NOT supported by the host, fallback to the system video driver."));
5141 Status = STATUS_UNSUCCESSFUL;
5142 }
5143 else
5144 {
5145 LOGREL(("3D is NOT supported by the host, falling back to display-only mode.."));
5146 }
5147 }
5148 else
5149 {
5150 if (f3DRequired)
5151 {
5152 LOGREL(("3D is NOT supported by the host, but is required for the current guest version using this driver.."));
5153 Status = STATUS_UNSUCCESSFUL;
5154 }
5155 else
5156 LOGREL(("3D is NOT supported by the host, but is NOT required for the current guest version using this driver, continuing with Disabled 3D.."));
5157 }
5158 }
5159 }
5160
5161 if (NT_SUCCESS(Status))
5162 {
5163 if (g_VBoxDisplayOnly)
5164 {
5165 Status = vboxWddmInitDisplayOnlyDriver(DriverObject, RegistryPath);
5166 }
5167 else
5168 {
5169 Status = vboxWddmInitFullGraphicsDriver(DriverObject, RegistryPath, enmHwType);
5170 }
5171
5172 if (NT_SUCCESS(Status))
5173 {
5174 /*
5175 * Successfully initialized the driver.
5176 */
5177 return Status;
5178 }
5179
5180 /*
5181 * Cleanup on failure.
5182 */
5183 }
5184 else
5185 LOGREL(("Aborting the video driver load due to 3D support missing"));
5186
5187 VbglR0TerminateClient();
5188 }
5189 else
5190 {
5191 WARN(("VbglR0InitClient failed, rc(%d)", rc));
5192 Status = STATUS_UNSUCCESSFUL;
5193 }
5194
5195 AssertRelease(!NT_SUCCESS(Status));
5196
5197 PRTLOGGER pLogger = RTLogRelSetDefaultInstance(NULL);
5198 if (pLogger)
5199 {
5200 RTLogDestroy(pLogger);
5201 }
5202 pLogger = RTLogSetDefaultInstance(NULL);
5203 if (pLogger)
5204 {
5205 RTLogDestroy(pLogger);
5206 }
5207
5208 return Status;
5209}
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