VirtualBox

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

Last change on this file since 74671 was 74671, checked in by vboxsync, 6 years ago

WDDM: enable R3 logging in debug builds

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 291.4 KB
Line 
1/* $Id: VBoxMPWddm.cpp 74671 2018-10-08 11:38:27Z vboxsync $ */
2/** @file
3 * VBox WDDM Miniport driver
4 */
5
6/*
7 * Copyright (C) 2011-2017 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#include "VBoxMPVhwa.h"
22#include "VBoxMPVidPn.h"
23
24#include <iprt/asm.h>
25#include <iprt/param.h>
26
27#include <VBox/VBoxGuestLib.h>
28#include <VBox/VMMDev.h> /* for VMMDevVideoSetVisibleRegion */
29#include <VBoxVideo.h>
30#include <wingdi.h> /* needed for RGNDATA definition */
31#include <VBoxDisplay.h> /* this is from Additions/WINNT/include/ to include escape codes */
32#include <VBoxVideoVBE.h>
33#include <VBox/Version.h>
34
35#include <stdio.h>
36
37/* Uncomment this in order to enable dumping regions guest wants to display on DxgkDdiPresentNew(). */
38//#define VBOX_WDDM_DUMP_REGIONS_ON_PRESENT
39
40#define VBOXWDDM_DUMMY_DMABUFFER_SIZE (sizeof(VBOXCMDVBVA_HDR) / 2)
41
42#ifdef DEBUG
43DWORD g_VBoxLogUm = VBOXWDDM_CFG_LOG_UM_BACKDOOR;
44#else
45DWORD g_VBoxLogUm = 0;
46#endif
47
48/* Whether the driver is display-only (no 3D) for Windows 8 or newer guests. */
49DWORD g_VBoxDisplayOnly = 0;
50
51#define VBOXWDDM_MEMTAG 'MDBV'
52PVOID vboxWddmMemAlloc(IN SIZE_T cbSize)
53{
54 POOL_TYPE enmPoolType = (VBoxQueryWinVersion() >= WINVERSION_8) ? NonPagedPoolNx : NonPagedPool;
55 return ExAllocatePoolWithTag(enmPoolType, cbSize, VBOXWDDM_MEMTAG);
56}
57
58PVOID vboxWddmMemAllocZero(IN SIZE_T cbSize)
59{
60 PVOID pvMem = vboxWddmMemAlloc(cbSize);
61 if (pvMem)
62 memset(pvMem, 0, cbSize);
63 return pvMem;
64}
65
66
67VOID vboxWddmMemFree(PVOID pvMem)
68{
69 ExFreePool(pvMem);
70}
71
72DECLINLINE(void) VBoxWddmOaHostIDReleaseLocked(PVBOXWDDM_OPENALLOCATION pOa)
73{
74 Assert(pOa->cHostIDRefs);
75 PVBOXWDDM_ALLOCATION pAllocation = pOa->pAllocation;
76 Assert(pAllocation->AllocData.cHostIDRefs >= pOa->cHostIDRefs);
77 Assert(pAllocation->AllocData.hostID);
78 --pOa->cHostIDRefs;
79 --pAllocation->AllocData.cHostIDRefs;
80 if (!pAllocation->AllocData.cHostIDRefs)
81 pAllocation->AllocData.hostID = 0;
82}
83
84DECLINLINE(void) VBoxWddmOaHostIDCheckReleaseLocked(PVBOXWDDM_OPENALLOCATION pOa)
85{
86 if (pOa->cHostIDRefs)
87 VBoxWddmOaHostIDReleaseLocked(pOa);
88}
89
90DECLINLINE(void) VBoxWddmOaRelease(PVBOXWDDM_OPENALLOCATION pOa)
91{
92 PVBOXWDDM_ALLOCATION pAllocation = pOa->pAllocation;
93 KIRQL OldIrql;
94 KeAcquireSpinLock(&pAllocation->OpenLock, &OldIrql);
95 Assert(pAllocation->cOpens);
96 VBoxWddmOaHostIDCheckReleaseLocked(pOa);
97 --pAllocation->cOpens;
98 uint32_t cOpens = --pOa->cOpens;
99 Assert(cOpens < UINT32_MAX/2);
100 if (!cOpens)
101 {
102 RemoveEntryList(&pOa->ListEntry);
103 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
104 vboxWddmMemFree(pOa);
105 }
106 else
107 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
108}
109
110DECLINLINE(PVBOXWDDM_OPENALLOCATION) VBoxWddmOaSearchLocked(PVBOXWDDM_DEVICE pDevice, PVBOXWDDM_ALLOCATION pAllocation)
111{
112 for (PLIST_ENTRY pCur = pAllocation->OpenList.Flink; pCur != &pAllocation->OpenList; pCur = pCur->Flink)
113 {
114 PVBOXWDDM_OPENALLOCATION pCurOa = CONTAINING_RECORD(pCur, VBOXWDDM_OPENALLOCATION, ListEntry);
115 if (pCurOa->pDevice == pDevice)
116 {
117 return pCurOa;
118 }
119 }
120 return NULL;
121}
122
123DECLINLINE(PVBOXWDDM_OPENALLOCATION) VBoxWddmOaSearch(PVBOXWDDM_DEVICE pDevice, PVBOXWDDM_ALLOCATION pAllocation)
124{
125 PVBOXWDDM_OPENALLOCATION pOa;
126 KIRQL OldIrql;
127 KeAcquireSpinLock(&pAllocation->OpenLock, &OldIrql);
128 pOa = VBoxWddmOaSearchLocked(pDevice, pAllocation);
129 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
130 return pOa;
131}
132
133DECLINLINE(int) VBoxWddmOaSetHostID(PVBOXWDDM_DEVICE pDevice, PVBOXWDDM_ALLOCATION pAllocation, uint32_t hostID, uint32_t *pHostID)
134{
135 PVBOXWDDM_OPENALLOCATION pOa;
136 KIRQL OldIrql;
137 int rc = VINF_SUCCESS;
138 KeAcquireSpinLock(&pAllocation->OpenLock, &OldIrql);
139 pOa = VBoxWddmOaSearchLocked(pDevice, pAllocation);
140 if (!pOa)
141 {
142 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);;
143 WARN(("no open allocation!"));
144 return VERR_INVALID_STATE;
145 }
146
147 if (hostID)
148 {
149 if (pAllocation->AllocData.hostID == 0)
150 {
151 pAllocation->AllocData.hostID = hostID;
152 }
153 else if (pAllocation->AllocData.hostID != hostID)
154 {
155 WARN(("hostID differ: alloc(%d), trying to assign(%d)", pAllocation->AllocData.hostID, hostID));
156 hostID = pAllocation->AllocData.hostID;
157 rc = VERR_NOT_EQUAL;
158 }
159
160 ++pAllocation->AllocData.cHostIDRefs;
161 ++pOa->cHostIDRefs;
162 }
163 else
164 VBoxWddmOaHostIDCheckReleaseLocked(pOa);
165
166 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
167
168 if (pHostID)
169 *pHostID = hostID;
170
171 return rc;
172}
173
174DECLINLINE(PVBOXWDDM_ALLOCATION) vboxWddmGetAllocationFromHandle(PVBOXMP_DEVEXT pDevExt, D3DKMT_HANDLE hAllocation)
175{
176 DXGKARGCB_GETHANDLEDATA GhData;
177 GhData.hObject = hAllocation;
178 GhData.Type = DXGK_HANDLE_ALLOCATION;
179 GhData.Flags.Value = 0;
180 return (PVBOXWDDM_ALLOCATION)pDevExt->u.primary.DxgkInterface.DxgkCbGetHandleData(&GhData);
181}
182
183DECLINLINE(PVBOXWDDM_ALLOCATION) vboxWddmGetAllocationFromAllocList(DXGK_ALLOCATIONLIST *pAllocList)
184{
185 PVBOXWDDM_OPENALLOCATION pOa = (PVBOXWDDM_OPENALLOCATION)pAllocList->hDeviceSpecificAllocation;
186 return pOa->pAllocation;
187}
188
189static void vboxWddmPopulateDmaAllocInfo(PVBOXWDDM_DMA_ALLOCINFO pInfo, PVBOXWDDM_ALLOCATION pAlloc, DXGK_ALLOCATIONLIST *pDmaAlloc)
190{
191 pInfo->pAlloc = pAlloc;
192 if (pDmaAlloc->SegmentId)
193 {
194 pInfo->offAlloc = (VBOXVIDEOOFFSET)pDmaAlloc->PhysicalAddress.QuadPart;
195 pInfo->segmentIdAlloc = pDmaAlloc->SegmentId;
196 }
197 else
198 pInfo->segmentIdAlloc = 0;
199 pInfo->srcId = pAlloc->AllocData.SurfDesc.VidPnSourceId;
200}
201
202static void vboxWddmPopulateDmaAllocInfoWithOffset(PVBOXWDDM_DMA_ALLOCINFO pInfo, PVBOXWDDM_ALLOCATION pAlloc, DXGK_ALLOCATIONLIST *pDmaAlloc, uint32_t offStart)
203{
204 pInfo->pAlloc = pAlloc;
205 if (pDmaAlloc->SegmentId)
206 {
207 pInfo->offAlloc = (VBOXVIDEOOFFSET)pDmaAlloc->PhysicalAddress.QuadPart + offStart;
208 pInfo->segmentIdAlloc = pDmaAlloc->SegmentId;
209 }
210 else
211 pInfo->segmentIdAlloc = 0;
212 pInfo->srcId = pAlloc->AllocData.SurfDesc.VidPnSourceId;
213}
214
215int vboxWddmGhDisplayPostInfoScreen(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData, const POINT * pVScreenPos, uint16_t fFlags)
216{
217 VBVAINFOSCREEN RT_UNTRUSTED_VOLATILE_HOST *pScreen =
218 (VBVAINFOSCREEN RT_UNTRUSTED_VOLATILE_HOST *)VBoxHGSMIBufferAlloc(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx,
219 sizeof(VBVAINFOSCREEN),
220 HGSMI_CH_VBVA,
221 VBVA_INFO_SCREEN);
222 if (!pScreen != NULL)
223 {
224 WARN(("VBoxHGSMIBufferAlloc failed"));
225 return VERR_OUT_OF_RESOURCES;
226 }
227
228 int rc = vboxWddmScreenInfoInit(pScreen, pAllocData, pVScreenPos, fFlags);
229 if (RT_SUCCESS(rc))
230 {
231 pScreen->u32StartOffset = 0; //(uint32_t)offVram; /* we pretend the view is located at the start of each framebuffer */
232
233 rc = VBoxHGSMIBufferSubmit(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, pScreen);
234 if (RT_FAILURE(rc))
235 WARN(("VBoxHGSMIBufferSubmit failed %d", rc));
236 }
237 else
238 WARN(("VBoxHGSMIBufferSubmit failed %d", rc));
239
240 VBoxHGSMIBufferFree(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, pScreen);
241
242 return rc;
243}
244
245int vboxWddmGhDisplayPostInfoView(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData)
246{
247 VBOXVIDEOOFFSET offVram = vboxWddmAddrFramOffset(&pAllocData->Addr);
248 if (offVram == VBOXVIDEOOFFSET_VOID)
249 {
250 WARN(("offVram == VBOXVIDEOOFFSET_VOID"));
251 return VERR_INVALID_PARAMETER;
252 }
253
254 /* Issue the screen info command. */
255 VBVAINFOVIEW RT_UNTRUSTED_VOLATILE_HOST *pView =
256 (VBVAINFOVIEW RT_UNTRUSTED_VOLATILE_HOST *)VBoxHGSMIBufferAlloc(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx,
257 sizeof(VBVAINFOVIEW), HGSMI_CH_VBVA, VBVA_INFO_VIEW);
258 if (!pView)
259 {
260 WARN(("VBoxHGSMIBufferAlloc failed"));
261 return VERR_OUT_OF_RESOURCES;
262 }
263 pView->u32ViewIndex = pAllocData->SurfDesc.VidPnSourceId;
264 pView->u32ViewOffset = (uint32_t)offVram; /* we pretend the view is located at the start of each framebuffer */
265 pView->u32ViewSize = vboxWddmVramCpuVisibleSegmentSize(pDevExt)/VBoxCommonFromDeviceExt(pDevExt)->cDisplays;
266 pView->u32MaxScreenSize = pView->u32ViewSize;
267
268 int rc = VBoxHGSMIBufferSubmit (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, pView);
269 if (RT_FAILURE(rc))
270 WARN(("VBoxHGSMIBufferSubmit failed %d", rc));
271
272 VBoxHGSMIBufferFree(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, pView);
273 return rc;
274}
275
276NTSTATUS vboxWddmGhDisplayPostResizeLegacy(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData, const POINT * pVScreenPos, uint16_t fFlags)
277{
278 int rc;
279
280 if (!(fFlags & (VBVA_SCREEN_F_DISABLED | VBVA_SCREEN_F_BLANK2)))
281 {
282 rc = vboxWddmGhDisplayPostInfoView(pDevExt, pAllocData);
283 if (RT_FAILURE(rc))
284 {
285 WARN(("vboxWddmGhDisplayPostInfoView failed %d", rc));
286 return STATUS_UNSUCCESSFUL;
287 }
288 }
289
290 rc = vboxWddmGhDisplayPostInfoScreen(pDevExt, pAllocData, pVScreenPos, fFlags);
291 if (RT_FAILURE(rc))
292 {
293 WARN(("vboxWddmGhDisplayPostInfoScreen failed %d", rc));
294 return STATUS_UNSUCCESSFUL;
295 }
296
297 return STATUS_SUCCESS;
298}
299
300NTSTATUS vboxWddmGhDisplayPostResizeNew(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData, const uint32_t *pTargetMap, const POINT * pVScreenPos, uint16_t fFlags)
301{
302 int rc = VBoxCmdVbvaConCmdResize(pDevExt, pAllocData, pTargetMap, pVScreenPos, fFlags);
303 if (RT_SUCCESS(rc))
304 return STATUS_SUCCESS;
305
306 WARN(("VBoxCmdVbvaConCmdResize failed %d", rc));
307 return STATUS_UNSUCCESSFUL;
308}
309
310NTSTATUS vboxWddmGhDisplaySetMode(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData)
311{
312 RT_NOREF(pDevExt);
313 VBOXVIDEOOFFSET offVram = vboxWddmAddrFramOffset(&pAllocData->Addr);;
314 if (offVram == VBOXVIDEOOFFSET_VOID)
315 {
316 WARN(("offVram == VBOXVIDEOOFFSET_VOID"));
317 return STATUS_UNSUCCESSFUL;
318 }
319
320 USHORT width = pAllocData->SurfDesc.width;
321 USHORT height = pAllocData->SurfDesc.height;
322 USHORT bpp = pAllocData->SurfDesc.bpp;
323 ULONG cbLine = VBOXWDDM_ROUNDBOUND(((width * bpp) + 7) / 8, 4);
324 ULONG yOffset = (ULONG)offVram / cbLine;
325 ULONG xOffset = (ULONG)offVram % cbLine;
326
327 if (bpp == 4)
328 {
329 xOffset <<= 1;
330 }
331 else
332 {
333 Assert(!(xOffset%((bpp + 7) >> 3)));
334 xOffset /= ((bpp + 7) >> 3);
335 }
336 Assert(xOffset <= 0xffff);
337 Assert(yOffset <= 0xffff);
338
339 VBoxVideoSetModeRegisters(width, height, width, bpp, 0, (uint16_t)xOffset, (uint16_t)yOffset);
340 /** @todo read back from port to check if mode switch was successful */
341
342 return STATUS_SUCCESS;
343}
344
345static uint16_t vboxWddmCalcScreenFlags(PVBOXMP_DEVEXT pDevExt, bool fValidAlloc, bool fPowerOff, bool fDisabled)
346{
347 uint16_t u16Flags;
348
349 if (fValidAlloc)
350 {
351 u16Flags = VBVA_SCREEN_F_ACTIVE;
352 }
353 else
354 {
355 if ( !fDisabled
356 && fPowerOff
357 && RT_BOOL(VBoxCommonFromDeviceExt(pDevExt)->u16SupportedScreenFlags & VBVA_SCREEN_F_BLANK2))
358 {
359 u16Flags = VBVA_SCREEN_F_ACTIVE | VBVA_SCREEN_F_BLANK2;
360 }
361 else
362 {
363 u16Flags = VBVA_SCREEN_F_DISABLED;
364 }
365 }
366
367 return u16Flags;
368}
369
370NTSTATUS vboxWddmGhDisplaySetInfoLegacy(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData, const POINT * pVScreenPos, uint8_t u8CurCyncState, bool fPowerOff, bool fDisabled)
371{
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#ifdef VBOX_WITH_CROGL
379 if ((u8CurCyncState & VBOXWDDM_HGSYNC_F_CHANGED_LOCATION_ONLY) == VBOXWDDM_HGSYNC_F_CHANGED_LOCATION_ONLY
380 && pAllocData->hostID)
381 {
382 Status = vboxVdmaTexPresentSetAlloc(pDevExt, pAllocData);
383 if (!NT_SUCCESS(Status))
384 WARN(("vboxVdmaTexPresentSetAlloc failed, Status 0x%x", Status));
385 return Status;
386 }
387#endif
388
389 if (pAllocData->SurfDesc.VidPnSourceId == 0)
390 Status = vboxWddmGhDisplaySetMode(pDevExt, pAllocData);
391 }
392
393 if (NT_SUCCESS(Status))
394 {
395 Status = vboxWddmGhDisplayPostResizeLegacy(pDevExt, pAllocData, pVScreenPos,
396 fu16Flags);
397 if (NT_SUCCESS(Status))
398 {
399#ifdef VBOX_WITH_CROGL
400 if (fValidAlloc && pDevExt->f3DEnabled)
401 {
402 Status = vboxVdmaTexPresentSetAlloc(pDevExt, pAllocData);
403 if (NT_SUCCESS(Status))
404 return STATUS_SUCCESS;
405 else
406 WARN(("vboxVdmaTexPresentSetAlloc failed, Status 0x%x", Status));
407 }
408#else
409 return STATUS_SUCCESS;
410#endif
411 }
412 else
413 WARN(("vboxWddmGhDisplayPostResize failed, Status 0x%x", Status));
414 }
415 else
416 WARN(("vboxWddmGhDisplaySetMode failed, Status 0x%x", Status));
417
418 return Status;
419}
420
421NTSTATUS vboxWddmGhDisplaySetInfoNew(PVBOXMP_DEVEXT pDevExt, const VBOXWDDM_ALLOC_DATA *pAllocData, const uint32_t *pTargetMap, const POINT * pVScreenPos, uint8_t u8CurCyncState, bool fPowerOff, bool fDisabled)
422{
423 NTSTATUS Status = STATUS_SUCCESS;
424 bool fValidAlloc = pAllocData->SurfDesc.width > 0 && pAllocData->SurfDesc.height > 0;
425 uint16_t fu16Flags = vboxWddmCalcScreenFlags(pDevExt, fValidAlloc, fPowerOff, fDisabled);
426
427 if (fValidAlloc)
428 {
429#ifdef VBOX_WITH_CROGL
430 if ((u8CurCyncState & VBOXWDDM_HGSYNC_F_CHANGED_LOCATION_ONLY) == VBOXWDDM_HGSYNC_F_CHANGED_LOCATION_ONLY
431 && pAllocData->hostID)
432 {
433 Status = vboxVdmaTexPresentSetAlloc(pDevExt, pAllocData);
434 if (!NT_SUCCESS(Status))
435 WARN(("vboxVdmaTexPresentSetAlloc failed, Status 0x%x", Status));
436 return Status;
437 }
438#endif
439
440 if (ASMBitTest(pTargetMap, 0))
441 Status = vboxWddmGhDisplaySetMode(pDevExt, pAllocData);
442 }
443
444 if (NT_SUCCESS(Status))
445 {
446 Status = vboxWddmGhDisplayPostResizeNew(pDevExt, pAllocData, pTargetMap, pVScreenPos, fu16Flags);
447 if (NT_SUCCESS(Status))
448 {
449#ifdef VBOX_WITH_CROGL
450 if (fValidAlloc && pDevExt->f3DEnabled)
451 {
452 Status = vboxVdmaTexPresentSetAlloc(pDevExt, pAllocData);
453 if (NT_SUCCESS(Status))
454 return STATUS_SUCCESS;
455 else
456 WARN(("vboxVdmaTexPresentSetAlloc failed, Status 0x%x", Status));
457 }
458#else
459 return STATUS_SUCCESS;
460#endif
461 }
462 else
463 WARN(("vboxWddmGhDisplayPostResizeNew failed, Status 0x%x", Status));
464 }
465 else
466 WARN(("vboxWddmGhDisplaySetMode failed, Status 0x%x", Status));
467
468 return Status;
469}
470
471bool vboxWddmGhDisplayCheckSetInfoFromSourceNew(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource, bool fReportTargets)
472{
473 if (pSource->u8SyncState == VBOXWDDM_HGSYNC_F_SYNCED_ALL)
474 {
475 if (!pSource->fTargetsReported && fReportTargets)
476 pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_TOPOLOGY;
477 else
478 return false;
479 }
480
481 if (!pSource->AllocData.Addr.SegmentId && pSource->AllocData.SurfDesc.width)
482 return false;
483
484 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aTargetMap);
485 uint32_t *pTargetMap;
486 if (fReportTargets)
487 pTargetMap = pSource->aTargetMap;
488 else
489 {
490 memset(aTargetMap, 0, sizeof (aTargetMap));
491 pTargetMap = aTargetMap;
492 }
493
494 NTSTATUS Status = vboxWddmGhDisplaySetInfoNew(pDevExt, &pSource->AllocData, pTargetMap, &pSource->VScreenPos, pSource->u8SyncState, RT_BOOL(pSource->bBlankedByPowerOff), false);
495 if (NT_SUCCESS(Status))
496 {
497 if (fReportTargets && (pSource->u8SyncState & VBOXWDDM_HGSYNC_F_CHANGED_LOCATION_ONLY) != VBOXWDDM_HGSYNC_F_CHANGED_LOCATION_ONLY)
498 {
499 VBOXWDDM_TARGET_ITER Iter;
500 VBoxVidPnStTIterInit(pSource, pDevExt->aTargets, VBoxCommonFromDeviceExt(pDevExt)->cDisplays, &Iter);
501
502 for (PVBOXWDDM_TARGET pTarget = VBoxVidPnStTIterNext(&Iter);
503 pTarget;
504 pTarget = VBoxVidPnStTIterNext(&Iter))
505 {
506 pTarget->u8SyncState = VBOXWDDM_HGSYNC_F_SYNCED_ALL;
507 }
508 }
509
510 pSource->u8SyncState = VBOXWDDM_HGSYNC_F_SYNCED_ALL;
511 pSource->fTargetsReported = !!fReportTargets;
512 return true;
513 }
514
515 WARN(("vboxWddmGhDisplaySetInfoNew failed, Status (0x%x)", Status));
516 return false;
517}
518
519bool vboxWddmGhDisplayCheckSetInfoFromSourceLegacy(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource, bool fReportTargets)
520{
521 if (!fReportTargets)
522 return false;
523
524 if (pSource->u8SyncState == VBOXWDDM_HGSYNC_F_SYNCED_ALL)
525 return false;
526
527 if (!pSource->AllocData.Addr.SegmentId)
528 return false;
529
530 VBOXWDDM_TARGET_ITER Iter;
531 VBoxVidPnStTIterInit(pSource, pDevExt->aTargets, VBoxCommonFromDeviceExt(pDevExt)->cDisplays, &Iter);
532 uint8_t u8SyncState = VBOXWDDM_HGSYNC_F_SYNCED_ALL;
533 VBOXWDDM_ALLOC_DATA AllocData = pSource->AllocData;
534
535 for (PVBOXWDDM_TARGET pTarget = VBoxVidPnStTIterNext(&Iter);
536 pTarget;
537 pTarget = VBoxVidPnStTIterNext(&Iter))
538 {
539 AllocData.SurfDesc.VidPnSourceId = pTarget->u32Id;
540 NTSTATUS Status = vboxWddmGhDisplaySetInfoLegacy(pDevExt, &AllocData, &pSource->VScreenPos, pSource->u8SyncState | pTarget->u8SyncState, pTarget->fBlankedByPowerOff, pTarget->fDisabled);
541 if (NT_SUCCESS(Status))
542 pTarget->u8SyncState = VBOXWDDM_HGSYNC_F_SYNCED_ALL;
543 else
544 {
545 WARN(("vboxWddmGhDisplaySetInfoLegacy failed, Status (0x%x)", Status));
546 u8SyncState = 0;
547 }
548 }
549
550 pSource->u8SyncState |= u8SyncState;
551
552 return true;
553}
554
555bool vboxWddmGhDisplayCheckSetInfoFromSourceEx(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource, bool fReportTargets)
556{
557 if (pDevExt->fCmdVbvaEnabled)
558 return vboxWddmGhDisplayCheckSetInfoFromSourceNew(pDevExt, pSource, fReportTargets);
559 return vboxWddmGhDisplayCheckSetInfoFromSourceLegacy(pDevExt, pSource, fReportTargets);
560}
561
562bool vboxWddmGhDisplayCheckSetInfoFromSource(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource)
563{
564 bool fReportTargets = !pDevExt->fDisableTargetUpdate;
565 return vboxWddmGhDisplayCheckSetInfoFromSourceEx(pDevExt, pSource, fReportTargets);
566}
567
568bool vboxWddmGhDisplayCheckSetInfoForDisabledTargetsNew(PVBOXMP_DEVEXT pDevExt)
569{
570 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aTargetMap);
571
572 memset(aTargetMap, 0, sizeof (aTargetMap));
573
574 bool fFound = false;
575 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
576 {
577 VBOXWDDM_TARGET *pTarget = &pDevExt->aTargets[i];
578 Assert(pTarget->u32Id == i);
579 if (pTarget->VidPnSourceId != D3DDDI_ID_UNINITIALIZED)
580 {
581 Assert(pTarget->VidPnSourceId < (D3DDDI_VIDEO_PRESENT_SOURCE_ID)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
582 continue;
583 }
584
585 /* Explicitely disabled targets must not be skipped. */
586 if (pTarget->fBlankedByPowerOff && !pTarget->fDisabled)
587 {
588 LOG(("Skip doing DISABLED request for PowerOff tgt %d", pTarget->u32Id));
589 continue;
590 }
591
592 if (pTarget->u8SyncState != VBOXWDDM_HGSYNC_F_SYNCED_ALL)
593 {
594 ASMBitSet(aTargetMap, i);
595 fFound = true;
596 }
597 }
598
599 if (!fFound)
600 return false;
601
602 POINT VScreenPos = {0};
603 VBOXWDDM_ALLOC_DATA AllocData;
604 VBoxVidPnAllocDataInit(&AllocData, D3DDDI_ID_UNINITIALIZED);
605 NTSTATUS Status = vboxWddmGhDisplaySetInfoNew(pDevExt, &AllocData, aTargetMap, &VScreenPos, 0, false, true);
606 if (!NT_SUCCESS(Status))
607 {
608 WARN(("vboxWddmGhDisplaySetInfoNew failed %#x", Status));
609 return false;
610 }
611
612 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
613 {
614 VBOXWDDM_TARGET *pTarget = &pDevExt->aTargets[i];
615 if (pTarget->VidPnSourceId != D3DDDI_ID_UNINITIALIZED)
616 {
617 Assert(pTarget->VidPnSourceId < (D3DDDI_VIDEO_PRESENT_SOURCE_ID)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
618 continue;
619 }
620
621 pTarget->u8SyncState = VBOXWDDM_HGSYNC_F_SYNCED_ALL;
622 }
623
624 return true;
625}
626
627bool vboxWddmGhDisplayCheckSetInfoForDisabledTargetsLegacy(PVBOXMP_DEVEXT pDevExt)
628{
629 POINT VScreenPos = {0};
630 bool fFound = false;
631 VBOXWDDM_ALLOC_DATA AllocData;
632 VBoxVidPnAllocDataInit(&AllocData, D3DDDI_ID_UNINITIALIZED);
633
634 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
635 {
636 VBOXWDDM_TARGET *pTarget = &pDevExt->aTargets[i];
637 Assert(pTarget->u32Id == i);
638 if (pTarget->VidPnSourceId != D3DDDI_ID_UNINITIALIZED)
639 {
640 Assert(pTarget->VidPnSourceId < (D3DDDI_VIDEO_PRESENT_SOURCE_ID)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
641 continue;
642 }
643
644 if (pTarget->u8SyncState == VBOXWDDM_HGSYNC_F_SYNCED_ALL)
645 continue;
646
647 fFound = true;
648 AllocData.SurfDesc.VidPnSourceId = i;
649 NTSTATUS Status = vboxWddmGhDisplaySetInfoLegacy(pDevExt, &AllocData, &VScreenPos, 0, pTarget->fBlankedByPowerOff, pTarget->fDisabled);
650 if (NT_SUCCESS(Status))
651 pTarget->u8SyncState = VBOXWDDM_HGSYNC_F_SYNCED_ALL;
652 else
653 WARN(("vboxWddmGhDisplaySetInfoLegacy failed, Status (0x%x)", Status));
654 }
655
656 return fFound;
657}
658
659void vboxWddmGhDisplayCheckSetInfoForDisabledTargets(PVBOXMP_DEVEXT pDevExt)
660{
661 if (pDevExt->fCmdVbvaEnabled)
662 vboxWddmGhDisplayCheckSetInfoForDisabledTargetsNew(pDevExt);
663 else
664 vboxWddmGhDisplayCheckSetInfoForDisabledTargetsLegacy(pDevExt);
665}
666
667void vboxWddmGhDisplayCheckSetInfoForDisabledTargetsCheck(PVBOXMP_DEVEXT pDevExt)
668{
669 bool fReportTargets = !pDevExt->fDisableTargetUpdate;
670
671 if (fReportTargets)
672 vboxWddmGhDisplayCheckSetInfoForDisabledTargets(pDevExt);
673}
674
675void vboxWddmGhDisplayCheckSetInfoEx(PVBOXMP_DEVEXT pDevExt, bool fReportTargets)
676{
677 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
678 {
679 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[i];
680 vboxWddmGhDisplayCheckSetInfoFromSourceEx(pDevExt, pSource, fReportTargets);
681 }
682
683 if (fReportTargets)
684 vboxWddmGhDisplayCheckSetInfoForDisabledTargets(pDevExt);
685}
686
687void vboxWddmGhDisplayCheckSetInfo(PVBOXMP_DEVEXT pDevExt)
688{
689 bool fReportTargets = !pDevExt->fDisableTargetUpdate;
690 vboxWddmGhDisplayCheckSetInfoEx(pDevExt, fReportTargets);
691}
692
693PVBOXSHGSMI vboxWddmHgsmiGetHeapFromCmdOffset(PVBOXMP_DEVEXT pDevExt, HGSMIOFFSET offCmd)
694{
695#ifdef VBOX_WITH_VDMA
696 if(HGSMIAreaContainsOffset(&pDevExt->u.primary.Vdma.CmdHeap.Heap.area, offCmd))
697 return &pDevExt->u.primary.Vdma.CmdHeap;
698#endif
699 if (HGSMIAreaContainsOffset(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx.Heap.area, offCmd))
700 return &VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx;
701 return NULL;
702}
703
704typedef enum
705{
706 VBOXWDDM_HGSMICMD_TYPE_UNDEFINED = 0,
707 VBOXWDDM_HGSMICMD_TYPE_CTL = 1,
708#ifdef VBOX_WITH_VDMA
709 VBOXWDDM_HGSMICMD_TYPE_DMACMD = 2
710#endif
711} VBOXWDDM_HGSMICMD_TYPE;
712
713VBOXWDDM_HGSMICMD_TYPE vboxWddmHgsmiGetCmdTypeFromOffset(PVBOXMP_DEVEXT pDevExt, HGSMIOFFSET offCmd)
714{
715#ifdef VBOX_WITH_VDMA
716 if(HGSMIAreaContainsOffset(&pDevExt->u.primary.Vdma.CmdHeap.Heap.area, offCmd))
717 return VBOXWDDM_HGSMICMD_TYPE_DMACMD;
718#endif
719 if (HGSMIAreaContainsOffset(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx.Heap.area, offCmd))
720 return VBOXWDDM_HGSMICMD_TYPE_CTL;
721 return VBOXWDDM_HGSMICMD_TYPE_UNDEFINED;
722}
723
724NTSTATUS vboxWddmPickResources(PVBOXMP_DEVEXT pDevExt, PDXGK_DEVICE_INFO pDeviceInfo, PVBOXWDDM_HWRESOURCES pHwResources)
725{
726 RT_NOREF(pDevExt);
727 NTSTATUS Status = STATUS_SUCCESS;
728 USHORT DispiId;
729 memset(pHwResources, 0, sizeof (*pHwResources));
730 pHwResources->cbVRAM = VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES;
731
732 VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
733 VBVO_PORT_WRITE_U16(VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID2);
734 DispiId = VBVO_PORT_READ_U16(VBE_DISPI_IOPORT_DATA);
735 if (DispiId == VBE_DISPI_ID2)
736 {
737 LOGREL(("found the VBE card"));
738 /*
739 * Write some hardware information to registry, so that
740 * it's visible in Windows property dialog.
741 */
742
743 /*
744 * Query the adapter's memory size. It's a bit of a hack, we just read
745 * an ULONG from the data port without setting an index before.
746 */
747 pHwResources->cbVRAM = VBVO_PORT_READ_U32(VBE_DISPI_IOPORT_DATA);
748 if (VBoxHGSMIIsSupported ())
749 {
750 PCM_RESOURCE_LIST pRcList = pDeviceInfo->TranslatedResourceList;
751 /** @todo verify resources */
752 for (ULONG i = 0; i < pRcList->Count; ++i)
753 {
754 PCM_FULL_RESOURCE_DESCRIPTOR pFRc = &pRcList->List[i];
755 for (ULONG j = 0; j < pFRc->PartialResourceList.Count; ++j)
756 {
757 PCM_PARTIAL_RESOURCE_DESCRIPTOR pPRc = &pFRc->PartialResourceList.PartialDescriptors[j];
758 switch (pPRc->Type)
759 {
760 case CmResourceTypePort:
761 break;
762 case CmResourceTypeInterrupt:
763 break;
764 case CmResourceTypeMemory:
765 /* we assume there is one memory segment */
766 AssertBreak(pHwResources->phVRAM.QuadPart == 0);
767 pHwResources->phVRAM = pPRc->u.Memory.Start;
768 Assert(pHwResources->phVRAM.QuadPart != 0);
769 pHwResources->ulApertureSize = pPRc->u.Memory.Length;
770 Assert(pHwResources->cbVRAM <= pHwResources->ulApertureSize);
771 break;
772 case CmResourceTypeDma:
773 break;
774 case CmResourceTypeDeviceSpecific:
775 break;
776 case CmResourceTypeBusNumber:
777 break;
778 default:
779 break;
780 }
781 }
782 }
783 }
784 else
785 {
786 LOGREL(("HGSMI unsupported, returning err"));
787 /** @todo report a better status */
788 Status = STATUS_UNSUCCESSFUL;
789 }
790 }
791 else
792 {
793 LOGREL(("VBE card not found, returning err"));
794 Status = STATUS_UNSUCCESSFUL;
795 }
796
797
798 return Status;
799}
800
801static void vboxWddmDevExtZeroinit(PVBOXMP_DEVEXT pDevExt, CONST PDEVICE_OBJECT pPDO)
802{
803 memset(pDevExt, 0, sizeof (VBOXMP_DEVEXT));
804 pDevExt->pPDO = pPDO;
805 PWCHAR pName = (PWCHAR)(((uint8_t*)pDevExt) + VBOXWDDM_ROUNDBOUND(sizeof(VBOXMP_DEVEXT), 8));
806 RtlInitUnicodeString(&pDevExt->RegKeyName, pName);
807
808 VBoxVidPnSourcesInit(pDevExt->aSources, RT_ELEMENTS(pDevExt->aSources), 0);
809
810 VBoxVidPnTargetsInit(pDevExt->aTargets, RT_ELEMENTS(pDevExt->aTargets), 0);
811
812 BOOLEAN f3DSupported = FALSE;
813 uint32_t u32 = 0;
814 if (VBoxVGACfgAvailable())
815 {
816 VBoxVGACfgQuery(VBE_DISPI_CFG_ID_3D, &u32, 0);
817 f3DSupported = RT_BOOL(u32);
818
819 VBoxVGACfgQuery(VBE_DISPI_CFG_ID_VMSVGA, &u32, 0);
820 }
821
822 pDevExt->enmHwType = u32 ? VBOXVIDEO_HWTYPE_VMSVGA : VBOXVIDEO_HWTYPE_VBOX;
823
824 if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VBOX)
825 {
826 pDevExt->f3DEnabled = VBoxMpCrCtlConIs3DSupported();
827 }
828 else
829 {
830 /* No supported 3D hardware, Fallback to VBox 2D only. */
831 pDevExt->enmHwType = VBOXVIDEO_HWTYPE_VBOX;
832 pDevExt->f3DEnabled = FALSE;
833 }
834}
835
836static void vboxWddmSetupDisplaysLegacy(PVBOXMP_DEVEXT pDevExt)
837{
838 /* For WDDM, we simply store the number of monitors as we will deal with
839 * VidPN stuff later */
840 int rc = STATUS_SUCCESS;
841
842 if (VBoxCommonFromDeviceExt(pDevExt)->bHGSMI)
843 {
844 ULONG ulAvailable = VBoxCommonFromDeviceExt(pDevExt)->cbVRAM
845 - VBoxCommonFromDeviceExt(pDevExt)->cbMiniportHeap
846 - VBVA_ADAPTER_INFORMATION_SIZE;
847
848 ULONG ulSize;
849 ULONG offset;
850#ifdef VBOX_WITH_VDMA
851 ulSize = ulAvailable / 2;
852 if (ulSize > VBOXWDDM_C_VDMA_BUFFER_SIZE)
853 ulSize = VBOXWDDM_C_VDMA_BUFFER_SIZE;
854
855 /* Align down to 4096 bytes. */
856 ulSize &= ~0xFFF;
857 offset = ulAvailable - ulSize;
858
859 Assert(!(offset & 0xFFF));
860#else
861 offset = ulAvailable;
862#endif
863 rc = vboxVdmaCreate (pDevExt, &pDevExt->u.primary.Vdma
864#ifdef VBOX_WITH_VDMA
865 , offset, ulSize
866#endif
867 );
868 AssertRC(rc);
869 if (RT_SUCCESS(rc))
870 {
871#ifdef VBOX_VDMA_WITH_WATCHDOG
872 vboxWddmWdInit(pDevExt);
873#endif
874 /* can enable it right away since the host does not need any screen/FB info
875 * for basic DMA functionality */
876 rc = vboxVdmaEnable(pDevExt, &pDevExt->u.primary.Vdma);
877 AssertRC(rc);
878 if (RT_FAILURE(rc))
879 vboxVdmaDestroy(pDevExt, &pDevExt->u.primary.Vdma);
880 }
881
882 ulAvailable = offset;
883 ulSize = ulAvailable/2;
884 offset = ulAvailable - ulSize;
885
886 NTSTATUS Status = vboxVideoAMgrCreate(pDevExt, &pDevExt->AllocMgr, offset, ulSize);
887 AssertNtStatusSuccess(Status);
888 if (Status != STATUS_SUCCESS)
889 {
890 offset = ulAvailable;
891 }
892
893#ifdef VBOXWDDM_RENDER_FROM_SHADOW
894 if (RT_SUCCESS(rc))
895 {
896 ulAvailable = offset;
897 ulSize = ulAvailable / 2;
898 ulSize /= VBoxCommonFromDeviceExt(pDevExt)->cDisplays;
899 Assert(ulSize > VBVA_MIN_BUFFER_SIZE);
900 if (ulSize > VBVA_MIN_BUFFER_SIZE)
901 {
902 ULONG ulRatio = ulSize/VBVA_MIN_BUFFER_SIZE;
903 ulRatio >>= 4; /* /= 16; */
904 if (ulRatio)
905 ulSize = VBVA_MIN_BUFFER_SIZE * ulRatio;
906 else
907 ulSize = VBVA_MIN_BUFFER_SIZE;
908 }
909 else
910 {
911 /** @todo ?? */
912 }
913
914 ulSize &= ~0xFFF;
915 Assert(ulSize);
916
917 Assert(ulSize * VBoxCommonFromDeviceExt(pDevExt)->cDisplays < ulAvailable);
918
919 for (int i = VBoxCommonFromDeviceExt(pDevExt)->cDisplays-1; i >= 0; --i)
920 {
921 offset -= ulSize;
922 rc = vboxVbvaCreate(pDevExt, &pDevExt->aSources[i].Vbva, offset, ulSize, i);
923 AssertRC(rc);
924 if (RT_SUCCESS(rc))
925 {
926 rc = vboxVbvaEnable(pDevExt, &pDevExt->aSources[i].Vbva);
927 AssertRC(rc);
928 if (RT_FAILURE(rc))
929 {
930 /** @todo de-initialize */
931 }
932 }
933 }
934 }
935#endif
936
937 rc = VBoxMPCmnMapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt), (void**)&pDevExt->pvVisibleVram,
938 0, vboxWddmVramCpuVisibleSize(pDevExt));
939 Assert(rc == VINF_SUCCESS);
940 if (rc != VINF_SUCCESS)
941 pDevExt->pvVisibleVram = NULL;
942
943 if (RT_FAILURE(rc))
944 VBoxCommonFromDeviceExt(pDevExt)->bHGSMI = FALSE;
945 }
946}
947#ifdef VBOX_WITH_CROGL
948static NTSTATUS vboxWddmSetupDisplaysNew(PVBOXMP_DEVEXT pDevExt)
949{
950 if (!VBoxCommonFromDeviceExt(pDevExt)->bHGSMI)
951 return STATUS_UNSUCCESSFUL;
952
953 ULONG cbAvailable = VBoxCommonFromDeviceExt(pDevExt)->cbVRAM
954 - VBoxCommonFromDeviceExt(pDevExt)->cbMiniportHeap
955 - VBVA_ADAPTER_INFORMATION_SIZE;
956
957 /* Size of the VBVA buffer which is used to pass VBOXCMDVBVA_* commands to the host.
958 * Estimate max 4KB per command.
959 */
960 ULONG cbCmdVbva = VBOXCMDVBVA_BUFFERSIZE(4096);
961
962 if (cbCmdVbva >= cbAvailable)
963 {
964 WARN(("too few VRAM memory fatal, %d, requested for CmdVbva %d", cbAvailable, cbCmdVbva));
965 return STATUS_UNSUCCESSFUL;
966 }
967
968
969 ULONG offCmdVbva = cbAvailable - cbCmdVbva;
970
971 int rc = VBoxCmdVbvaCreate(pDevExt, &pDevExt->CmdVbva, offCmdVbva, cbCmdVbva);
972 if (RT_SUCCESS(rc))
973 {
974 rc = VBoxCmdVbvaEnable(pDevExt, &pDevExt->CmdVbva);
975 if (RT_SUCCESS(rc))
976 {
977 rc = VBoxMPCmnMapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt), (void**)&pDevExt->pvVisibleVram,
978 0, vboxWddmVramCpuVisibleSize(pDevExt));
979 if (RT_SUCCESS(rc))
980 return STATUS_SUCCESS;
981 else
982 WARN(("VBoxMPCmnMapAdapterMemory failed, rc %d", rc));
983
984 VBoxCmdVbvaDisable(pDevExt, &pDevExt->CmdVbva);
985 }
986 else
987 WARN(("VBoxCmdVbvaEnable failed, rc %d", rc));
988
989 VBoxCmdVbvaDestroy(pDevExt, &pDevExt->CmdVbva);
990 }
991 else
992 WARN(("VBoxCmdVbvaCreate failed, rc %d", rc));
993
994 return STATUS_UNSUCCESSFUL;
995}
996#endif
997static NTSTATUS vboxWddmSetupDisplays(PVBOXMP_DEVEXT pDevExt)
998{
999#ifdef VBOX_WITH_CROGL
1000 if (pDevExt->fCmdVbvaEnabled)
1001 {
1002 NTSTATUS Status = vboxWddmSetupDisplaysNew(pDevExt);
1003 if (!NT_SUCCESS(Status))
1004 VBoxCommonFromDeviceExt(pDevExt)->bHGSMI = FALSE;
1005 return Status;
1006 }
1007#endif
1008
1009 vboxWddmSetupDisplaysLegacy(pDevExt);
1010 return VBoxCommonFromDeviceExt(pDevExt)->bHGSMI ? STATUS_SUCCESS : STATUS_UNSUCCESSFUL;
1011}
1012
1013static int vboxWddmFreeDisplays(PVBOXMP_DEVEXT pDevExt)
1014{
1015 int rc = VINF_SUCCESS;
1016
1017 Assert(pDevExt->pvVisibleVram);
1018 if (pDevExt->pvVisibleVram)
1019 VBoxMPCmnUnmapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt), (void**)&pDevExt->pvVisibleVram);
1020
1021 if (pDevExt->fCmdVbvaEnabled)
1022 {
1023 rc = VBoxCmdVbvaDisable(pDevExt, &pDevExt->CmdVbva);
1024 if (RT_SUCCESS(rc))
1025 {
1026 rc = VBoxCmdVbvaDestroy(pDevExt, &pDevExt->CmdVbva);
1027 if (RT_FAILURE(rc))
1028 WARN(("VBoxCmdVbvaDestroy failed %d", rc));
1029 }
1030 else
1031 WARN(("VBoxCmdVbvaDestroy failed %d", rc));
1032
1033 }
1034 else
1035 {
1036 for (int i = VBoxCommonFromDeviceExt(pDevExt)->cDisplays-1; i >= 0; --i)
1037 {
1038 rc = vboxVbvaDisable(pDevExt, &pDevExt->aSources[i].Vbva);
1039 AssertRC(rc);
1040 if (RT_SUCCESS(rc))
1041 {
1042 rc = vboxVbvaDestroy(pDevExt, &pDevExt->aSources[i].Vbva);
1043 AssertRC(rc);
1044 if (RT_FAILURE(rc))
1045 {
1046 /** @todo */
1047 }
1048 }
1049 }
1050
1051 vboxVideoAMgrDestroy(pDevExt, &pDevExt->AllocMgr);
1052
1053 rc = vboxVdmaDisable(pDevExt, &pDevExt->u.primary.Vdma);
1054 AssertRC(rc);
1055 if (RT_SUCCESS(rc))
1056 {
1057#ifdef VBOX_VDMA_WITH_WATCHDOG
1058 vboxWddmWdTerm(pDevExt);
1059#endif
1060 rc = vboxVdmaDestroy(pDevExt, &pDevExt->u.primary.Vdma);
1061 AssertRC(rc);
1062 }
1063 }
1064
1065 return rc;
1066}
1067
1068
1069/* driver callbacks */
1070NTSTATUS DxgkDdiAddDevice(
1071 IN CONST PDEVICE_OBJECT PhysicalDeviceObject,
1072 OUT PVOID *MiniportDeviceContext
1073 )
1074{
1075 /* The DxgkDdiAddDevice function should be made pageable. */
1076 PAGED_CODE();
1077
1078 LOGF(("ENTER, pdo(0x%x)", PhysicalDeviceObject));
1079
1080 vboxVDbgBreakFv();
1081
1082 NTSTATUS Status = STATUS_SUCCESS;
1083 PVBOXMP_DEVEXT pDevExt = NULL;
1084
1085 WCHAR RegKeyBuf[512];
1086 ULONG cbRegKeyBuf = sizeof (RegKeyBuf);
1087
1088 Status = IoGetDeviceProperty (PhysicalDeviceObject,
1089 DevicePropertyDriverKeyName,
1090 cbRegKeyBuf,
1091 RegKeyBuf,
1092 &cbRegKeyBuf);
1093 AssertNtStatusSuccess(Status);
1094 if (Status == STATUS_SUCCESS)
1095 {
1096 pDevExt = (PVBOXMP_DEVEXT)vboxWddmMemAllocZero(VBOXWDDM_ROUNDBOUND(sizeof(VBOXMP_DEVEXT), 8) + cbRegKeyBuf);
1097 if (pDevExt)
1098 {
1099 PWCHAR pName = (PWCHAR)(((uint8_t*)pDevExt) + VBOXWDDM_ROUNDBOUND(sizeof(VBOXMP_DEVEXT), 8));
1100 memcpy(pName, RegKeyBuf, cbRegKeyBuf);
1101 vboxWddmDevExtZeroinit(pDevExt, PhysicalDeviceObject);
1102 *MiniportDeviceContext = pDevExt;
1103 }
1104 else
1105 {
1106 Status = STATUS_NO_MEMORY;
1107 LOGREL(("ERROR, failed to create context"));
1108 }
1109 }
1110
1111 LOGF(("LEAVE, Status(0x%x), pDevExt(0x%x)", Status, pDevExt));
1112
1113 return Status;
1114}
1115
1116NTSTATUS DxgkDdiStartDevice(
1117 IN CONST PVOID MiniportDeviceContext,
1118 IN PDXGK_START_INFO DxgkStartInfo,
1119 IN PDXGKRNL_INTERFACE DxgkInterface,
1120 OUT PULONG NumberOfVideoPresentSources,
1121 OUT PULONG NumberOfChildren
1122 )
1123{
1124 /* The DxgkDdiStartDevice function should be made pageable. */
1125 PAGED_CODE();
1126
1127 NTSTATUS Status;
1128
1129 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
1130
1131 vboxVDbgBreakFv();
1132
1133 if ( ARGUMENT_PRESENT(MiniportDeviceContext) &&
1134 ARGUMENT_PRESENT(DxgkInterface) &&
1135 ARGUMENT_PRESENT(DxgkStartInfo) &&
1136 ARGUMENT_PRESENT(NumberOfVideoPresentSources) &&
1137 ARGUMENT_PRESENT(NumberOfChildren)
1138 )
1139 {
1140 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1141
1142 vboxWddmVGuidGet(pDevExt);
1143
1144 /* Save DeviceHandle and function pointers supplied by the DXGKRNL_INTERFACE structure passed to DxgkInterface. */
1145 memcpy(&pDevExt->u.primary.DxgkInterface, DxgkInterface, sizeof (DXGKRNL_INTERFACE));
1146
1147 /* 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)
1148 * of the DXGK_DEVICE_INFO structure in the context block represented by MiniportDeviceContext. */
1149 DXGK_DEVICE_INFO DeviceInfo;
1150 Status = pDevExt->u.primary.DxgkInterface.DxgkCbGetDeviceInformation (pDevExt->u.primary.DxgkInterface.DeviceHandle, &DeviceInfo);
1151 if (Status == STATUS_SUCCESS)
1152 {
1153 Status = vboxWddmPickResources(pDevExt, &DeviceInfo, &pDevExt->HwResources);
1154 if (Status == STATUS_SUCCESS)
1155 {
1156 /* Figure out the host capabilities. Start with nothing. */
1157 pDevExt->fTexPresentEnabled = FALSE;
1158 pDevExt->fCmdVbvaEnabled = FALSE;
1159 pDevExt->fComplexTopologiesEnabled = FALSE;
1160
1161 if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VBOX)
1162 {
1163#ifdef VBOX_WITH_CROGL
1164 if (pDevExt->f3DEnabled)
1165 {
1166 pDevExt->fTexPresentEnabled = !!(VBoxMpCrGetHostCaps() & CR_VBOX_CAP_TEX_PRESENT);
1167 pDevExt->fCmdVbvaEnabled = !!(VBoxMpCrGetHostCaps() & CR_VBOX_CAP_CMDVBVA);
1168 // Disabled, see xTracker #8244 pDevExt->fComplexTopologiesEnabled = pDevExt->fCmdVbvaEnabled;
1169 }
1170#else
1171 pDevExt->f3DEnabled = FALSE;
1172#endif
1173 }
1174 else
1175 {
1176 pDevExt->f3DEnabled = FALSE;
1177 }
1178
1179 /* Guest supports only HGSMI, the old VBVA via VMMDev is not supported.
1180 * The host will however support both old and new interface to keep compatibility
1181 * with old guest additions.
1182 */
1183 VBoxSetupDisplaysHGSMI(VBoxCommonFromDeviceExt(pDevExt),
1184 pDevExt->HwResources.phVRAM, pDevExt->HwResources.ulApertureSize, pDevExt->HwResources.cbVRAM,
1185 VBVACAPS_COMPLETEGCMD_BY_IOREAD | VBVACAPS_IRQ);
1186 if (VBoxCommonFromDeviceExt(pDevExt)->bHGSMI)
1187 {
1188 vboxWddmSetupDisplays(pDevExt);
1189 if (!VBoxCommonFromDeviceExt(pDevExt)->bHGSMI)
1190 VBoxFreeDisplaysHGSMI(VBoxCommonFromDeviceExt(pDevExt));
1191 }
1192 if (VBoxCommonFromDeviceExt(pDevExt)->bHGSMI)
1193 {
1194 LOGREL(("using HGSMI"));
1195 *NumberOfVideoPresentSources = VBoxCommonFromDeviceExt(pDevExt)->cDisplays;
1196 *NumberOfChildren = VBoxCommonFromDeviceExt(pDevExt)->cDisplays;
1197 LOG(("sources(%d), children(%d)", *NumberOfVideoPresentSources, *NumberOfChildren));
1198
1199 vboxVdmaDdiNodesInit(pDevExt);
1200 vboxVideoCmInit(&pDevExt->CmMgr);
1201 vboxVideoCmInit(&pDevExt->SeamlessCtxMgr);
1202 InitializeListHead(&pDevExt->SwapchainList3D);
1203 pDevExt->cContexts3D = 0;
1204 pDevExt->cContexts2D = 0;
1205 pDevExt->cContextsDispIfResize = 0;
1206 pDevExt->cUnlockedVBVADisabled = 0;
1207 pDevExt->fDisableTargetUpdate = 0;
1208 VBOXWDDM_CTXLOCK_INIT(pDevExt);
1209 KeInitializeSpinLock(&pDevExt->SynchLock);
1210
1211 VBoxCommonFromDeviceExt(pDevExt)->fAnyX = VBoxVideoAnyWidthAllowed();
1212#if 0
1213 vboxShRcTreeInit(pDevExt);
1214#endif
1215
1216#ifdef VBOX_WITH_VIDEOHWACCEL
1217 vboxVhwaInit(pDevExt);
1218#endif
1219 VBoxWddmSlInit(pDevExt);
1220
1221#ifdef VBOX_WITH_CROGL
1222 VBoxMpCrShgsmiTransportCreate(&pDevExt->CrHgsmiTransport, pDevExt);
1223#endif
1224
1225 for (UINT i = 0; i < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
1226 {
1227 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[i];
1228 KeInitializeSpinLock(&pSource->AllocationLock);
1229#ifdef VBOX_WITH_CROGL
1230 VBoxVrListInit(&pSource->VrList);
1231#endif
1232 }
1233
1234 DWORD dwVal = VBOXWDDM_CFG_DRV_DEFAULT;
1235 HANDLE hKey = NULL;
1236 WCHAR aNameBuf[100];
1237
1238 Status = IoOpenDeviceRegistryKey(pDevExt->pPDO, PLUGPLAY_REGKEY_DRIVER, GENERIC_READ, &hKey);
1239 if (!NT_SUCCESS(Status))
1240 {
1241 WARN(("IoOpenDeviceRegistryKey failed, Status = 0x%x", Status));
1242 hKey = NULL;
1243 }
1244
1245
1246 if (hKey)
1247 {
1248 Status = vboxWddmRegQueryValueDword(hKey, VBOXWDDM_REG_DRV_FLAGS_NAME, &dwVal);
1249 if (!NT_SUCCESS(Status))
1250 {
1251 LOG(("vboxWddmRegQueryValueDword failed, Status = 0x%x", Status));
1252 dwVal = VBOXWDDM_CFG_DRV_DEFAULT;
1253 }
1254 }
1255
1256 pDevExt->dwDrvCfgFlags = dwVal;
1257
1258 for (UINT i = 0; i < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
1259 {
1260 PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[i];
1261 if (i == 0 || (pDevExt->dwDrvCfgFlags & VBOXWDDM_CFG_DRV_SECONDARY_TARGETS_CONNECTED) || !hKey)
1262 {
1263 pTarget->fConnected = true;
1264 pTarget->fConfigured = true;
1265 }
1266 else if (hKey)
1267 {
1268 swprintf(aNameBuf, L"%s%d", VBOXWDDM_REG_DRV_DISPFLAGS_PREFIX, i);
1269 Status = vboxWddmRegQueryValueDword(hKey, aNameBuf, &dwVal);
1270 if (NT_SUCCESS(Status))
1271 {
1272 pTarget->fConnected = !!(dwVal & VBOXWDDM_CFG_DRVTARGET_CONNECTED);
1273 pTarget->fConfigured = true;
1274 }
1275 else
1276 {
1277 WARN(("vboxWddmRegQueryValueDword failed, Status = 0x%x", Status));
1278 pTarget->fConnected = false;
1279 pTarget->fConfigured = false;
1280 }
1281 }
1282 }
1283
1284 if (hKey)
1285 {
1286 NTSTATUS rcNt2 = ZwClose(hKey);
1287 Assert(rcNt2 == STATUS_SUCCESS); NOREF(rcNt2);
1288 }
1289
1290 Status = STATUS_SUCCESS;
1291
1292 if (VBoxQueryWinVersion() >= WINVERSION_8)
1293 {
1294 DXGK_DISPLAY_INFORMATION DisplayInfo;
1295 Status = pDevExt->u.primary.DxgkInterface.DxgkCbAcquirePostDisplayOwnership(pDevExt->u.primary.DxgkInterface.DeviceHandle,
1296 &DisplayInfo);
1297 if (NT_SUCCESS(Status))
1298 {
1299 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[0];
1300 PHYSICAL_ADDRESS PhAddr;
1301 /* display info may sometimes not be valid, e.g. on from-full-graphics wddm driver update
1302 * ensure we have something meaningful here */
1303 if (!DisplayInfo.Width)
1304 {
1305 PhAddr = VBoxCommonFromDeviceExt(pDevExt)->phVRAM;
1306 vboxWddmDiInitDefault(&DisplayInfo, PhAddr, 0);
1307 }
1308 else
1309 {
1310 PhAddr = DisplayInfo.PhysicAddress;
1311 DisplayInfo.TargetId = 0;
1312 }
1313
1314 vboxWddmDiToAllocData(pDevExt, &DisplayInfo, &pSource->AllocData);
1315
1316 /* init the rest source infos with some default values */
1317 for (UINT i = 1; i < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
1318 {
1319 PhAddr.QuadPart += pSource->AllocData.SurfDesc.cbSize;
1320 PhAddr.QuadPart = ROUND_TO_PAGES(PhAddr.QuadPart);
1321 vboxWddmDiInitDefault(&DisplayInfo, PhAddr, i);
1322 pSource = &pDevExt->aSources[i];
1323 vboxWddmDiToAllocData(pDevExt, &DisplayInfo, &pSource->AllocData);
1324 }
1325 }
1326 else
1327 {
1328 WARN(("DxgkCbAcquirePostDisplayOwnership failed, Status 0x%x", Status));
1329 }
1330 }
1331
1332 VBoxWddmVModesInit(pDevExt);
1333 }
1334 else
1335 {
1336 LOGREL(("HGSMI failed to initialize, returning err"));
1337
1338 /** @todo report a better status */
1339 Status = STATUS_UNSUCCESSFUL;
1340 }
1341 }
1342 else
1343 {
1344 LOGREL(("vboxWddmPickResources failed Status(0x%x), returning err", Status));
1345 Status = STATUS_UNSUCCESSFUL;
1346 }
1347 }
1348 else
1349 {
1350 LOGREL(("DxgkCbGetDeviceInformation failed Status(0x%x), returning err", Status));
1351 }
1352 }
1353 else
1354 {
1355 LOGREL(("invalid parameter, returning err"));
1356 Status = STATUS_INVALID_PARAMETER;
1357 }
1358
1359 LOGF(("LEAVE, status(0x%x)", Status));
1360
1361 return Status;
1362}
1363
1364NTSTATUS DxgkDdiStopDevice(
1365 IN CONST PVOID MiniportDeviceContext
1366 )
1367{
1368 /* The DxgkDdiStopDevice function should be made pageable. */
1369 PAGED_CODE();
1370
1371 LOGF(("ENTER, context(0x%p)", MiniportDeviceContext));
1372
1373 vboxVDbgBreakFv();
1374
1375 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1376 NTSTATUS Status = STATUS_SUCCESS;
1377
1378#ifdef VBOX_WITH_CROGL
1379 if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VBOX && pDevExt->u32CrConDefaultClientID)
1380 VBoxMpCrCtlConDisconnect(pDevExt, &pDevExt->CrCtlCon, pDevExt->u32CrConDefaultClientID);
1381
1382 VBoxMpCrShgsmiTransportTerm(&pDevExt->CrHgsmiTransport);
1383#endif
1384
1385 VBoxWddmSlTerm(pDevExt);
1386
1387 vboxVideoCmTerm(&pDevExt->CmMgr);
1388
1389 vboxVideoCmTerm(&pDevExt->SeamlessCtxMgr);
1390
1391 /* do everything we did on DxgkDdiStartDevice in the reverse order */
1392#ifdef VBOX_WITH_VIDEOHWACCEL
1393 vboxVhwaFree(pDevExt);
1394#endif
1395#if 0
1396 vboxShRcTreeTerm(pDevExt);
1397#endif
1398
1399 int rc = vboxWddmFreeDisplays(pDevExt);
1400 if (RT_SUCCESS(rc))
1401 VBoxFreeDisplaysHGSMI(VBoxCommonFromDeviceExt(pDevExt));
1402 AssertRC(rc);
1403 if (RT_SUCCESS(rc))
1404 {
1405 vboxWddmVGuidFree(pDevExt);
1406
1407 VBoxWddmVModesCleanup();
1408 /* revert back to the state we were right after the DxgkDdiAddDevice */
1409 vboxWddmDevExtZeroinit(pDevExt, pDevExt->pPDO);
1410 }
1411 else
1412 Status = STATUS_UNSUCCESSFUL;
1413
1414 return Status;
1415}
1416
1417NTSTATUS DxgkDdiRemoveDevice(
1418 IN CONST PVOID MiniportDeviceContext
1419 )
1420{
1421 /* DxgkDdiRemoveDevice should be made pageable. */
1422 PAGED_CODE();
1423
1424 LOGF(("ENTER, context(0x%p)", MiniportDeviceContext));
1425
1426 vboxVDbgBreakFv();
1427
1428 vboxWddmMemFree(MiniportDeviceContext);
1429
1430 LOGF(("LEAVE, context(0x%p)", MiniportDeviceContext));
1431
1432 return STATUS_SUCCESS;
1433}
1434
1435NTSTATUS DxgkDdiDispatchIoRequest(
1436 IN CONST PVOID MiniportDeviceContext,
1437 IN ULONG VidPnSourceId,
1438 IN PVIDEO_REQUEST_PACKET VideoRequestPacket
1439 )
1440{
1441 LOGF(("ENTER, context(0x%p), ctl(0x%x)", MiniportDeviceContext, VideoRequestPacket->IoControlCode));
1442
1443 AssertBreakpoint();
1444#if 0
1445 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1446
1447 switch (VideoRequestPacket->IoControlCode)
1448 {
1449 case IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES:
1450 {
1451 if (VideoRequestPacket->OutputBufferLength < sizeof(VIDEO_COLOR_CAPABILITIES))
1452 {
1453 AssertBreakpoint();
1454 VideoRequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1455 return TRUE;
1456 }
1457 VIDEO_COLOR_CAPABILITIES *pCaps = (VIDEO_COLOR_CAPABILITIES*)VideoRequestPacket->OutputBuffer;
1458
1459 pCaps->Length = sizeof (VIDEO_COLOR_CAPABILITIES);
1460 pCaps->AttributeFlags = VIDEO_DEVICE_COLOR;
1461 pCaps->RedPhosphoreDecay = 0;
1462 pCaps->GreenPhosphoreDecay = 0;
1463 pCaps->BluePhosphoreDecay = 0;
1464 pCaps->WhiteChromaticity_x = 3127;
1465 pCaps->WhiteChromaticity_y = 3290;
1466 pCaps->WhiteChromaticity_Y = 0;
1467 pCaps->RedChromaticity_x = 6700;
1468 pCaps->RedChromaticity_y = 3300;
1469 pCaps->GreenChromaticity_x = 2100;
1470 pCaps->GreenChromaticity_y = 7100;
1471 pCaps->BlueChromaticity_x = 1400;
1472 pCaps->BlueChromaticity_y = 800;
1473 pCaps->WhiteGamma = 0;
1474 pCaps->RedGamma = 20000;
1475 pCaps->GreenGamma = 20000;
1476 pCaps->BlueGamma = 20000;
1477
1478 VideoRequestPacket->StatusBlock->Status = NO_ERROR;
1479 VideoRequestPacket->StatusBlock->Information = sizeof (VIDEO_COLOR_CAPABILITIES);
1480 break;
1481 }
1482#if 0
1483 case IOCTL_VIDEO_HANDLE_VIDEOPARAMETERS:
1484 {
1485 if (VideoRequestPacket->OutputBufferLength < sizeof(VIDEOPARAMETERS)
1486 || VideoRequestPacket->InputBufferLength < sizeof(VIDEOPARAMETERS))
1487 {
1488 AssertBreakpoint();
1489 VideoRequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1490 return TRUE;
1491 }
1492
1493 Result = VBoxVideoResetDevice((PVBOXMP_DEVEXT)HwDeviceExtension,
1494 RequestPacket->StatusBlock);
1495 break;
1496 }
1497#endif
1498 default:
1499 AssertBreakpoint();
1500 VideoRequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1501 VideoRequestPacket->StatusBlock->Information = 0;
1502 }
1503#else
1504 RT_NOREF(MiniportDeviceContext, VidPnSourceId, VideoRequestPacket);
1505#endif
1506 LOGF(("LEAVE, context(0x%p), ctl(0x%x)", MiniportDeviceContext, VideoRequestPacket->IoControlCode));
1507
1508 return STATUS_SUCCESS;
1509}
1510
1511#ifdef VBOX_WITH_CROGL
1512BOOLEAN DxgkDdiInterruptRoutineNew(
1513 IN CONST PVOID MiniportDeviceContext,
1514 IN ULONG MessageNumber
1515 )
1516{
1517 RT_NOREF(MessageNumber);
1518// LOGF(("ENTER, context(0x%p), msg(0x%x)", MiniportDeviceContext, MessageNumber));
1519
1520 vboxVDbgBreakFv();
1521
1522 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1523 BOOLEAN bOur = FALSE;
1524 bool bNeedDpc = FALSE;
1525 if (!VBoxCommonFromDeviceExt(pDevExt)->hostCtx.pfHostFlags) /* If HGSMI is enabled at all. */
1526 {
1527 WARN(("ISR called with hgsmi disabled!"));
1528 return FALSE;
1529 }
1530
1531 VBOXVTLIST CtlList;
1532 vboxVtListInit(&CtlList);
1533#ifdef VBOX_WITH_VIDEOHWACCEL
1534 VBOXVTLIST VhwaCmdList;
1535 vboxVtListInit(&VhwaCmdList);
1536#endif
1537
1538 uint32_t flags = VBoxCommonFromDeviceExt(pDevExt)->hostCtx.pfHostFlags->u32HostFlags;
1539 bOur = (flags & HGSMIHOSTFLAGS_IRQ);
1540
1541 if (bOur)
1542 VBoxHGSMIClearIrq(&VBoxCommonFromDeviceExt(pDevExt)->hostCtx);
1543
1544 bNeedDpc |= VBoxCmdVbvaCheckCompletedIrq(pDevExt, &pDevExt->CmdVbva);
1545
1546 do {
1547 /* re-read flags right here to avoid host-guest racing,
1548 * i.e. the situation:
1549 * 1. guest reads flags ant it is HGSMIHOSTFLAGS_IRQ, i.e. HGSMIHOSTFLAGS_GCOMMAND_COMPLETED no set
1550 * 2. host completes guest command, sets the HGSMIHOSTFLAGS_GCOMMAND_COMPLETED and raises IRQ
1551 * 3. guest clleans IRQ and exits */
1552 flags = VBoxCommonFromDeviceExt(pDevExt)->hostCtx.pfHostFlags->u32HostFlags;
1553
1554 if (flags & HGSMIHOSTFLAGS_GCOMMAND_COMPLETED)
1555 {
1556 /* read the command offset */
1557 HGSMIOFFSET offCmd = VBVO_PORT_READ_U32(VBoxCommonFromDeviceExt(pDevExt)->guestCtx.port);
1558 if (offCmd == HGSMIOFFSET_VOID)
1559 {
1560 WARN(("void command offset!"));
1561 continue;
1562 }
1563
1564 uint16_t chInfo;
1565 uint8_t RT_UNTRUSTED_VOLATILE_HOST *pvCmd =
1566 HGSMIBufferDataAndChInfoFromOffset(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx.Heap.area, offCmd, &chInfo);
1567 if (!pvCmd)
1568 {
1569 WARN(("zero cmd"));
1570 continue;
1571 }
1572
1573 switch (chInfo)
1574 {
1575 case VBVA_CMDVBVA_CTL:
1576 {
1577 int rc = VBoxSHGSMICommandProcessCompletion(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx,
1578 (VBOXSHGSMIHEADER *)pvCmd, TRUE /*bool bIrq*/ , &CtlList);
1579 AssertRC(rc);
1580 break;
1581 }
1582#ifdef VBOX_WITH_VIDEOHWACCEL
1583 case VBVA_VHWA_CMD:
1584 {
1585 vboxVhwaPutList(&VhwaCmdList, (VBOXVHWACMD*)pvCmd);
1586 break;
1587 }
1588#endif /* # ifdef VBOX_WITH_VIDEOHWACCEL */
1589 default:
1590 AssertBreakpoint();
1591 }
1592 }
1593 else if (flags & HGSMIHOSTFLAGS_COMMANDS_PENDING)
1594 {
1595 AssertBreakpoint();
1596 /** @todo FIXME: implement !!! */
1597 }
1598 else
1599 break;
1600 } while (1);
1601
1602 if (!vboxVtListIsEmpty(&CtlList))
1603 {
1604 vboxVtListCat(&pDevExt->CtlList, &CtlList);
1605 bNeedDpc = TRUE;
1606 ASMAtomicWriteU32(&pDevExt->fCompletingCommands, 1);
1607 }
1608
1609 if (!vboxVtListIsEmpty(&VhwaCmdList))
1610 {
1611 vboxVtListCat(&pDevExt->VhwaCmdList, &VhwaCmdList);
1612 bNeedDpc = TRUE;
1613 ASMAtomicWriteU32(&pDevExt->fCompletingCommands, 1);
1614 }
1615
1616 bNeedDpc |= !vboxVdmaDdiCmdIsCompletedListEmptyIsr(pDevExt);
1617
1618 if (bOur)
1619 {
1620#ifdef VBOX_VDMA_WITH_WATCHDOG
1621 if (flags & HGSMIHOSTFLAGS_WATCHDOG)
1622 {
1623 Assert(0);
1624 }
1625#endif
1626 if (flags & HGSMIHOSTFLAGS_VSYNC)
1627 {
1628 Assert(0);
1629 DXGKARGCB_NOTIFY_INTERRUPT_DATA notify;
1630 for (UINT i = 0; i < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
1631 {
1632 PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[i];
1633 if (pTarget->fConnected)
1634 {
1635 memset(&notify, 0, sizeof(DXGKARGCB_NOTIFY_INTERRUPT_DATA));
1636 notify.InterruptType = DXGK_INTERRUPT_CRTC_VSYNC;
1637 notify.CrtcVsync.VidPnTargetId = i;
1638 pDevExt->u.primary.DxgkInterface.DxgkCbNotifyInterrupt(pDevExt->u.primary.DxgkInterface.DeviceHandle, &notify);
1639 bNeedDpc = TRUE;
1640 }
1641 }
1642 }
1643 }
1644
1645 if (pDevExt->bNotifyDxDpc)
1646 bNeedDpc = TRUE;
1647
1648 if (bNeedDpc)
1649 pDevExt->u.primary.DxgkInterface.DxgkCbQueueDpc(pDevExt->u.primary.DxgkInterface.DeviceHandle);
1650
1651 return bOur;
1652}
1653#endif
1654
1655static BOOLEAN DxgkDdiInterruptRoutineLegacy(
1656 IN CONST PVOID MiniportDeviceContext,
1657 IN ULONG MessageNumber
1658 )
1659{
1660 RT_NOREF(MessageNumber);
1661// LOGF(("ENTER, context(0x%p), msg(0x%x)", MiniportDeviceContext, MessageNumber));
1662
1663 vboxVDbgBreakFv();
1664
1665 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1666 BOOLEAN bOur = FALSE;
1667 BOOLEAN bNeedDpc = FALSE;
1668 if (VBoxCommonFromDeviceExt(pDevExt)->hostCtx.pfHostFlags) /* If HGSMI is enabled at all. */
1669 {
1670 VBOXVTLIST CtlList;
1671#ifdef VBOX_WITH_VDMA
1672 VBOXVTLIST DmaCmdList;
1673#endif
1674 vboxVtListInit(&CtlList);
1675#ifdef VBOX_WITH_VDMA
1676 vboxVtListInit(&DmaCmdList);
1677#endif
1678
1679#ifdef VBOX_WITH_VIDEOHWACCEL
1680 VBOXVTLIST VhwaCmdList;
1681 vboxVtListInit(&VhwaCmdList);
1682#endif
1683
1684 uint32_t flags = VBoxCommonFromDeviceExt(pDevExt)->hostCtx.pfHostFlags->u32HostFlags;
1685 bOur = (flags & HGSMIHOSTFLAGS_IRQ);
1686
1687 if (bOur)
1688 VBoxHGSMIClearIrq(&VBoxCommonFromDeviceExt(pDevExt)->hostCtx);
1689
1690 do
1691 {
1692 if (flags & HGSMIHOSTFLAGS_GCOMMAND_COMPLETED)
1693 {
1694 /* read the command offset */
1695 HGSMIOFFSET offCmd = VBVO_PORT_READ_U32(VBoxCommonFromDeviceExt(pDevExt)->guestCtx.port);
1696 Assert(offCmd != HGSMIOFFSET_VOID);
1697 if (offCmd != HGSMIOFFSET_VOID)
1698 {
1699 VBOXWDDM_HGSMICMD_TYPE enmType = vboxWddmHgsmiGetCmdTypeFromOffset(pDevExt, offCmd);
1700 PVBOXVTLIST pList;
1701 PVBOXSHGSMI pHeap;
1702 switch (enmType)
1703 {
1704#ifdef VBOX_WITH_VDMA
1705 case VBOXWDDM_HGSMICMD_TYPE_DMACMD:
1706 pList = &DmaCmdList;
1707 pHeap = &pDevExt->u.primary.Vdma.CmdHeap;
1708 break;
1709#endif
1710 case VBOXWDDM_HGSMICMD_TYPE_CTL:
1711 pList = &CtlList;
1712 pHeap = &VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx;
1713 break;
1714 default:
1715 AssertBreakpoint();
1716 pList = NULL;
1717 pHeap = NULL;
1718 break;
1719 }
1720
1721 if (pHeap)
1722 {
1723 uint16_t chInfo;
1724 uint8_t RT_UNTRUSTED_VOLATILE_GUEST *pvCmd =
1725 HGSMIBufferDataAndChInfoFromOffset(&pHeap->Heap.area, offCmd, &chInfo);
1726 Assert(pvCmd);
1727 if (pvCmd)
1728 {
1729 switch (chInfo)
1730 {
1731#ifdef VBOX_WITH_VDMA
1732 case VBVA_VDMA_CMD:
1733 case VBVA_VDMA_CTL:
1734 {
1735 int rc = VBoxSHGSMICommandProcessCompletion(pHeap, (VBOXSHGSMIHEADER*)pvCmd,
1736 TRUE /*bool bIrq*/ , pList);
1737 AssertRC(rc);
1738 break;
1739 }
1740#endif
1741#ifdef VBOX_WITH_VIDEOHWACCEL
1742 case VBVA_VHWA_CMD:
1743 {
1744 vboxVhwaPutList(&VhwaCmdList, (VBOXVHWACMD*)pvCmd);
1745 break;
1746 }
1747#endif /* # ifdef VBOX_WITH_VIDEOHWACCEL */
1748 default:
1749 AssertBreakpoint();
1750 }
1751 }
1752 }
1753 }
1754 }
1755 else if (flags & HGSMIHOSTFLAGS_COMMANDS_PENDING)
1756 {
1757 AssertBreakpoint();
1758 /** @todo FIXME: implement !!! */
1759 }
1760 else
1761 break;
1762
1763 flags = VBoxCommonFromDeviceExt(pDevExt)->hostCtx.pfHostFlags->u32HostFlags;
1764 } while (1);
1765
1766 if (!vboxVtListIsEmpty(&CtlList))
1767 {
1768 vboxVtListCat(&pDevExt->CtlList, &CtlList);
1769 bNeedDpc = TRUE;
1770 }
1771#ifdef VBOX_WITH_VDMA
1772 if (!vboxVtListIsEmpty(&DmaCmdList))
1773 {
1774 vboxVtListCat(&pDevExt->DmaCmdList, &DmaCmdList);
1775 bNeedDpc = TRUE;
1776 }
1777#endif
1778 if (!vboxVtListIsEmpty(&VhwaCmdList))
1779 {
1780 vboxVtListCat(&pDevExt->VhwaCmdList, &VhwaCmdList);
1781 bNeedDpc = TRUE;
1782 }
1783
1784 bNeedDpc |= !vboxVdmaDdiCmdIsCompletedListEmptyIsr(pDevExt);
1785
1786 if (pDevExt->bNotifyDxDpc)
1787 {
1788 bNeedDpc = TRUE;
1789 }
1790
1791 if (bOur)
1792 {
1793#ifdef VBOX_VDMA_WITH_WATCHDOG
1794 if (flags & HGSMIHOSTFLAGS_WATCHDOG)
1795 {
1796 Assert(0);
1797 }
1798#endif
1799 if (flags & HGSMIHOSTFLAGS_VSYNC)
1800 {
1801 Assert(0);
1802 DXGKARGCB_NOTIFY_INTERRUPT_DATA notify;
1803 for (UINT i = 0; i < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
1804 {
1805 PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[i];
1806 if (pTarget->fConnected)
1807 {
1808 memset(&notify, 0, sizeof(DXGKARGCB_NOTIFY_INTERRUPT_DATA));
1809 notify.InterruptType = DXGK_INTERRUPT_CRTC_VSYNC;
1810 notify.CrtcVsync.VidPnTargetId = i;
1811 pDevExt->u.primary.DxgkInterface.DxgkCbNotifyInterrupt(pDevExt->u.primary.DxgkInterface.DeviceHandle, &notify);
1812 bNeedDpc = TRUE;
1813 }
1814 }
1815 }
1816
1817 if (pDevExt->bNotifyDxDpc)
1818 {
1819 bNeedDpc = TRUE;
1820 }
1821
1822#if 0 //def DEBUG_misha
1823 /* this is not entirely correct since host may concurrently complete some commands and raise a new IRQ while we are here,
1824 * still this allows to check that the host flags are correctly cleared after the ISR */
1825 Assert(VBoxCommonFromDeviceExt(pDevExt)->hostCtx.pfHostFlags);
1826 uint32_t flags = VBoxCommonFromDeviceExt(pDevExt)->hostCtx.pfHostFlags->u32HostFlags;
1827 Assert(flags == 0);
1828#endif
1829 }
1830
1831 if (bNeedDpc)
1832 {
1833 pDevExt->u.primary.DxgkInterface.DxgkCbQueueDpc(pDevExt->u.primary.DxgkInterface.DeviceHandle);
1834 }
1835 }
1836
1837// LOGF(("LEAVE, context(0x%p), bOur(0x%x)", MiniportDeviceContext, (ULONG)bOur));
1838
1839 return bOur;
1840}
1841
1842
1843typedef struct VBOXWDDM_DPCDATA
1844{
1845 VBOXVTLIST CtlList;
1846#ifdef VBOX_WITH_VDMA
1847 VBOXVTLIST DmaCmdList;
1848#endif
1849#ifdef VBOX_WITH_VIDEOHWACCEL
1850 VBOXVTLIST VhwaCmdList;
1851#endif
1852 LIST_ENTRY CompletedDdiCmdQueue;
1853 BOOL bNotifyDpc;
1854} VBOXWDDM_DPCDATA, *PVBOXWDDM_DPCDATA;
1855
1856typedef struct VBOXWDDM_GETDPCDATA_CONTEXT
1857{
1858 PVBOXMP_DEVEXT pDevExt;
1859 VBOXWDDM_DPCDATA data;
1860} VBOXWDDM_GETDPCDATA_CONTEXT, *PVBOXWDDM_GETDPCDATA_CONTEXT;
1861
1862BOOLEAN vboxWddmGetDPCDataCallback(PVOID Context)
1863{
1864 PVBOXWDDM_GETDPCDATA_CONTEXT pdc = (PVBOXWDDM_GETDPCDATA_CONTEXT)Context;
1865 PVBOXMP_DEVEXT pDevExt = pdc->pDevExt;
1866 vboxVtListDetach2List(&pDevExt->CtlList, &pdc->data.CtlList);
1867#ifdef VBOX_WITH_VDMA
1868 vboxVtListDetach2List(&pDevExt->DmaCmdList, &pdc->data.DmaCmdList);
1869#endif
1870#ifdef VBOX_WITH_VIDEOHWACCEL
1871 vboxVtListDetach2List(&pDevExt->VhwaCmdList, &pdc->data.VhwaCmdList);
1872#endif
1873#ifdef VBOX_WITH_CROGL
1874 if (!pDevExt->fCmdVbvaEnabled)
1875#endif
1876 {
1877 vboxVdmaDdiCmdGetCompletedListIsr(pDevExt, &pdc->data.CompletedDdiCmdQueue);
1878 }
1879
1880 pdc->data.bNotifyDpc = pDevExt->bNotifyDxDpc;
1881 pDevExt->bNotifyDxDpc = FALSE;
1882
1883 ASMAtomicWriteU32(&pDevExt->fCompletingCommands, 0);
1884
1885 return TRUE;
1886}
1887
1888#ifdef VBOX_WITH_CROGL
1889static VOID DxgkDdiDpcRoutineNew(
1890 IN CONST PVOID MiniportDeviceContext
1891 )
1892{
1893// LOGF(("ENTER, context(0x%p)", MiniportDeviceContext));
1894
1895 vboxVDbgBreakFv();
1896
1897 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1898
1899 pDevExt->u.primary.DxgkInterface.DxgkCbNotifyDpc(pDevExt->u.primary.DxgkInterface.DeviceHandle);
1900
1901 if (ASMAtomicReadU32(&pDevExt->fCompletingCommands))
1902 {
1903 VBOXWDDM_GETDPCDATA_CONTEXT context = {0};
1904 BOOLEAN bRet;
1905
1906 context.pDevExt = pDevExt;
1907
1908 /* get DPC data at IRQL */
1909 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
1910 pDevExt->u.primary.DxgkInterface.DeviceHandle,
1911 vboxWddmGetDPCDataCallback,
1912 &context,
1913 0, /* IN ULONG MessageNumber */
1914 &bRet);
1915 AssertNtStatusSuccess(Status); NOREF(Status);
1916
1917 // if (context.data.bNotifyDpc)
1918 pDevExt->u.primary.DxgkInterface.DxgkCbNotifyDpc(pDevExt->u.primary.DxgkInterface.DeviceHandle);
1919
1920 if (!vboxVtListIsEmpty(&context.data.CtlList))
1921 {
1922 int rc = VBoxSHGSMICommandPostprocessCompletion (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, &context.data.CtlList);
1923 AssertRC(rc);
1924 }
1925#ifdef VBOX_WITH_VIDEOHWACCEL
1926 if (!vboxVtListIsEmpty(&context.data.VhwaCmdList))
1927 {
1928 vboxVhwaCompletionListProcess(pDevExt, &context.data.VhwaCmdList);
1929 }
1930#endif
1931 }
1932// LOGF(("LEAVE, context(0x%p)", MiniportDeviceContext));
1933}
1934#endif
1935
1936static VOID DxgkDdiDpcRoutineLegacy(
1937 IN CONST PVOID MiniportDeviceContext
1938 )
1939{
1940// LOGF(("ENTER, context(0x%p)", MiniportDeviceContext));
1941
1942 vboxVDbgBreakFv();
1943
1944 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1945
1946 VBOXWDDM_GETDPCDATA_CONTEXT context = {0};
1947 BOOLEAN bRet;
1948
1949 context.pDevExt = pDevExt;
1950
1951 /* get DPC data at IRQL */
1952 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
1953 pDevExt->u.primary.DxgkInterface.DeviceHandle,
1954 vboxWddmGetDPCDataCallback,
1955 &context,
1956 0, /* IN ULONG MessageNumber */
1957 &bRet);
1958 AssertNtStatusSuccess(Status); NOREF(Status);
1959
1960// if (context.data.bNotifyDpc)
1961 pDevExt->u.primary.DxgkInterface.DxgkCbNotifyDpc(pDevExt->u.primary.DxgkInterface.DeviceHandle);
1962
1963 if (!vboxVtListIsEmpty(&context.data.CtlList))
1964 {
1965 int rc = VBoxSHGSMICommandPostprocessCompletion (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, &context.data.CtlList);
1966 AssertRC(rc);
1967 }
1968#ifdef VBOX_WITH_VDMA
1969 if (!vboxVtListIsEmpty(&context.data.DmaCmdList))
1970 {
1971 int rc = VBoxSHGSMICommandPostprocessCompletion (&pDevExt->u.primary.Vdma.CmdHeap, &context.data.DmaCmdList);
1972 AssertRC(rc);
1973 }
1974#endif
1975#ifdef VBOX_WITH_VIDEOHWACCEL
1976 if (!vboxVtListIsEmpty(&context.data.VhwaCmdList))
1977 {
1978 vboxVhwaCompletionListProcess(pDevExt, &context.data.VhwaCmdList);
1979 }
1980#endif
1981
1982 vboxVdmaDdiCmdHandleCompletedList(pDevExt, &context.data.CompletedDdiCmdQueue);
1983
1984// LOGF(("LEAVE, context(0x%p)", MiniportDeviceContext));
1985}
1986
1987NTSTATUS DxgkDdiQueryChildRelations(
1988 IN CONST PVOID MiniportDeviceContext,
1989 IN OUT PDXGK_CHILD_DESCRIPTOR ChildRelations,
1990 IN ULONG ChildRelationsSize
1991 )
1992{
1993 RT_NOREF(ChildRelationsSize);
1994 /* The DxgkDdiQueryChildRelations function should be made pageable. */
1995 PAGED_CODE();
1996
1997 vboxVDbgBreakFv();
1998
1999 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
2000
2001 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
2002 Assert(ChildRelationsSize == (VBoxCommonFromDeviceExt(pDevExt)->cDisplays + 1)*sizeof(DXGK_CHILD_DESCRIPTOR));
2003 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
2004 {
2005 ChildRelations[i].ChildDeviceType = TypeVideoOutput;
2006 ChildRelations[i].ChildCapabilities.Type.VideoOutput.InterfaceTechnology = D3DKMDT_VOT_HD15; /* VGA */
2007 ChildRelations[i].ChildCapabilities.Type.VideoOutput.MonitorOrientationAwareness = D3DKMDT_MOA_NONE; //D3DKMDT_MOA_INTERRUPTIBLE; /* ?? D3DKMDT_MOA_NONE*/
2008 ChildRelations[i].ChildCapabilities.Type.VideoOutput.SupportsSdtvModes = FALSE;
2009 ChildRelations[i].ChildCapabilities.HpdAwareness = HpdAwarenessInterruptible; /* ?? HpdAwarenessAlwaysConnected; */
2010 ChildRelations[i].AcpiUid = 0; /* */
2011 ChildRelations[i].ChildUid = i; /* should be == target id */
2012 }
2013 LOGF(("LEAVE, context(0x%x)", MiniportDeviceContext));
2014 return STATUS_SUCCESS;
2015}
2016
2017NTSTATUS DxgkDdiQueryChildStatus(
2018 IN CONST PVOID MiniportDeviceContext,
2019 IN PDXGK_CHILD_STATUS ChildStatus,
2020 IN BOOLEAN NonDestructiveOnly
2021 )
2022{
2023 RT_NOREF(NonDestructiveOnly);
2024 /* The DxgkDdiQueryChildStatus should be made pageable. */
2025 PAGED_CODE();
2026
2027 vboxVDbgBreakFv();
2028
2029 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
2030
2031 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
2032
2033 if (ChildStatus->ChildUid >= (uint32_t)VBoxCommonFromDeviceExt(pDevExt)->cDisplays)
2034 {
2035 WARN(("Invalid child id %d", ChildStatus->ChildUid));
2036 return STATUS_INVALID_PARAMETER;
2037 }
2038
2039 NTSTATUS Status = STATUS_SUCCESS;
2040 switch (ChildStatus->Type)
2041 {
2042 case StatusConnection:
2043 {
2044 LOGF(("StatusConnection"));
2045 VBOXWDDM_TARGET *pTarget = &pDevExt->aTargets[ChildStatus->ChildUid];
2046 BOOLEAN Connected = !!pTarget->fConnected;
2047 if (!Connected)
2048 LOGREL(("Tgt[%d] DISCONNECTED!!", ChildStatus->ChildUid));
2049 ChildStatus->HotPlug.Connected = !!pTarget->fConnected;
2050 break;
2051 }
2052 case StatusRotation:
2053 LOGF(("StatusRotation"));
2054 ChildStatus->Rotation.Angle = 0;
2055 break;
2056 default:
2057 WARN(("ERROR: status type: %d", ChildStatus->Type));
2058 Status = STATUS_INVALID_PARAMETER;
2059 break;
2060 }
2061
2062 LOGF(("LEAVE, context(0x%x)", MiniportDeviceContext));
2063
2064 return Status;
2065}
2066
2067NTSTATUS DxgkDdiQueryDeviceDescriptor(
2068 IN CONST PVOID MiniportDeviceContext,
2069 IN ULONG ChildUid,
2070 IN OUT PDXGK_DEVICE_DESCRIPTOR DeviceDescriptor
2071 )
2072{
2073 RT_NOREF(MiniportDeviceContext, ChildUid, DeviceDescriptor);
2074 /* The DxgkDdiQueryDeviceDescriptor should be made pageable. */
2075 PAGED_CODE();
2076
2077 vboxVDbgBreakFv();
2078
2079 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
2080
2081 LOGF(("LEAVE, context(0x%x)", MiniportDeviceContext));
2082
2083 /* we do not support EDID */
2084 return STATUS_MONITOR_NO_DESCRIPTOR;
2085}
2086
2087NTSTATUS DxgkDdiSetPowerState(
2088 IN CONST PVOID MiniportDeviceContext,
2089 IN ULONG DeviceUid,
2090 IN DEVICE_POWER_STATE DevicePowerState,
2091 IN POWER_ACTION ActionType
2092 )
2093{
2094 RT_NOREF(MiniportDeviceContext, DeviceUid, DevicePowerState, ActionType);
2095 /* The DxgkDdiSetPowerState function should be made pageable. */
2096 PAGED_CODE();
2097
2098 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
2099
2100 vboxVDbgBreakFv();
2101
2102 LOGF(("LEAVE, context(0x%x)", MiniportDeviceContext));
2103
2104 return STATUS_SUCCESS;
2105}
2106
2107NTSTATUS DxgkDdiNotifyAcpiEvent(
2108 IN CONST PVOID MiniportDeviceContext,
2109 IN DXGK_EVENT_TYPE EventType,
2110 IN ULONG Event,
2111 IN PVOID Argument,
2112 OUT PULONG AcpiFlags
2113 )
2114{
2115 RT_NOREF(MiniportDeviceContext, EventType, Event, Argument, AcpiFlags);
2116 LOGF(("ENTER, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
2117
2118 vboxVDbgBreakF();
2119
2120 LOGF(("LEAVE, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
2121
2122 return STATUS_SUCCESS;
2123}
2124
2125VOID DxgkDdiResetDevice(
2126 IN CONST PVOID MiniportDeviceContext
2127 )
2128{
2129 RT_NOREF(MiniportDeviceContext);
2130 /* DxgkDdiResetDevice can be called at any IRQL, so it must be in nonpageable memory. */
2131 vboxVDbgBreakF();
2132
2133
2134
2135 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
2136 LOGF(("LEAVE, context(0x%x)", MiniportDeviceContext));
2137}
2138
2139VOID DxgkDdiUnload(
2140 VOID
2141 )
2142{
2143 /* DxgkDdiUnload should be made pageable. */
2144 PAGED_CODE();
2145 LOGF((": unloading"));
2146
2147 vboxVDbgBreakFv();
2148
2149 VbglR0TerminateClient();
2150
2151#ifdef VBOX_WITH_CROGL
2152 VBoxVrTerm();
2153#endif
2154
2155 PRTLOGGER pLogger = RTLogRelSetDefaultInstance(NULL);
2156 if (pLogger)
2157 {
2158 RTLogDestroy(pLogger);
2159 }
2160 pLogger = RTLogSetDefaultInstance(NULL);
2161 if (pLogger)
2162 {
2163 RTLogDestroy(pLogger);
2164 }
2165}
2166
2167NTSTATUS DxgkDdiQueryInterface(
2168 IN CONST PVOID MiniportDeviceContext,
2169 IN PQUERY_INTERFACE QueryInterface
2170 )
2171{
2172 RT_NOREF(MiniportDeviceContext, QueryInterface);
2173 LOGF(("ENTER, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
2174
2175 vboxVDbgBreakFv();
2176
2177 LOGF(("LEAVE, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
2178
2179 return STATUS_NOT_SUPPORTED;
2180}
2181
2182VOID DxgkDdiControlEtwLogging(
2183 IN BOOLEAN Enable,
2184 IN ULONG Flags,
2185 IN UCHAR Level
2186 )
2187{
2188 RT_NOREF(Enable, Flags, Level);
2189 LOGF(("ENTER"));
2190
2191 vboxVDbgBreakF();
2192
2193 LOGF(("LEAVE"));
2194}
2195
2196/**
2197 * DxgkDdiQueryAdapterInfo
2198 */
2199NTSTATUS APIENTRY DxgkDdiQueryAdapterInfo(
2200 CONST HANDLE hAdapter,
2201 CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo)
2202{
2203 /* The DxgkDdiQueryAdapterInfo should be made pageable. */
2204 PAGED_CODE();
2205
2206 LOGF(("ENTER, context(0x%x), Query type (%d)", hAdapter, pQueryAdapterInfo->Type));
2207 NTSTATUS Status = STATUS_SUCCESS;
2208 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
2209
2210 vboxVDbgBreakFv();
2211
2212 switch (pQueryAdapterInfo->Type)
2213 {
2214 case DXGKQAITYPE_DRIVERCAPS:
2215 {
2216 DXGK_DRIVERCAPS *pCaps = (DXGK_DRIVERCAPS*)pQueryAdapterInfo->pOutputData;
2217 memset(pCaps, 0, sizeof (*pCaps));
2218
2219 pCaps->HighestAcceptableAddress.LowPart = ~0UL;
2220#ifdef RT_ARCH_AMD64
2221 /* driver talks to host in terms of page numbers when reffering to RAM
2222 * we use uint32_t field to pass page index to host, so max would be (~0UL) << PAGE_OFFSET,
2223 * which seems quite enough */
2224 pCaps->HighestAcceptableAddress.HighPart = PAGE_OFFSET_MASK;
2225#endif
2226 pCaps->MaxPointerWidth = VBOXWDDM_C_POINTER_MAX_WIDTH;
2227 pCaps->MaxPointerHeight = VBOXWDDM_C_POINTER_MAX_HEIGHT;
2228 pCaps->PointerCaps.Value = 3; /* Monochrome , Color*/ /* MaskedColor == Value | 4, disable for now */
2229 if (!g_VBoxDisplayOnly)
2230 {
2231 pCaps->MaxAllocationListSlotId = 16;
2232 pCaps->ApertureSegmentCommitLimit = 0;
2233 pCaps->InterruptMessageNumber = 0;
2234 pCaps->NumberOfSwizzlingRanges = 0;
2235 pCaps->MaxOverlays = 0;
2236#ifdef VBOX_WITH_VIDEOHWACCEL
2237 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
2238 {
2239 if ( pDevExt->aSources[i].Vhwa.Settings.fFlags & VBOXVHWA_F_ENABLED)
2240 pCaps->MaxOverlays += pDevExt->aSources[i].Vhwa.Settings.cOverlaysSupported;
2241 }
2242#endif
2243 pCaps->GammaRampCaps.Value = 0;
2244 pCaps->PresentationCaps.Value = 0;
2245 pCaps->PresentationCaps.NoScreenToScreenBlt = 1;
2246 pCaps->PresentationCaps.NoOverlapScreenBlt = 1;
2247 pCaps->MaxQueuedFlipOnVSync = 0; /* do we need it? */
2248 pCaps->FlipCaps.Value = 0;
2249 /* ? pCaps->FlipCaps.FlipOnVSyncWithNoWait = 1; */
2250 pCaps->SchedulingCaps.Value = 0;
2251 /* we might need it for Aero.
2252 * Setting this flag means we support DeviceContext, i.e.
2253 * DxgkDdiCreateContext and DxgkDdiDestroyContext
2254 */
2255 pCaps->SchedulingCaps.MultiEngineAware = 1;
2256 pCaps->MemoryManagementCaps.Value = 0;
2257 /** @todo this correlates with pCaps->SchedulingCaps.MultiEngineAware */
2258 pCaps->MemoryManagementCaps.PagingNode = 0;
2259 /** @todo this correlates with pCaps->SchedulingCaps.MultiEngineAware */
2260 pCaps->GpuEngineTopology.NbAsymetricProcessingNodes = VBOXWDDM_NUM_NODES;
2261
2262 if (VBoxQueryWinVersion() >= WINVERSION_8)
2263 pCaps->WDDMVersion = DXGKDDI_WDDMv1;
2264 }
2265 else
2266 {
2267 pCaps->WDDMVersion = DXGKDDI_WDDMv1_2;
2268 }
2269 break;
2270 }
2271 case DXGKQAITYPE_QUERYSEGMENT:
2272 {
2273 if (!g_VBoxDisplayOnly)
2274 {
2275 /* no need for DXGK_QUERYSEGMENTIN as it contains AGP aperture info, which (AGP aperture) we do not support
2276 * DXGK_QUERYSEGMENTIN *pQsIn = (DXGK_QUERYSEGMENTIN*)pQueryAdapterInfo->pInputData; */
2277 DXGK_QUERYSEGMENTOUT *pQsOut = (DXGK_QUERYSEGMENTOUT*)pQueryAdapterInfo->pOutputData;
2278# define VBOXWDDM_SEGMENTS_COUNT 2
2279 if (!pQsOut->pSegmentDescriptor)
2280 {
2281 /* we are requested to provide the number of segments we support */
2282 pQsOut->NbSegment = VBOXWDDM_SEGMENTS_COUNT;
2283 }
2284 else if (pQsOut->NbSegment != VBOXWDDM_SEGMENTS_COUNT)
2285 {
2286 WARN(("NbSegment (%d) != 1", pQsOut->NbSegment));
2287 Status = STATUS_INVALID_PARAMETER;
2288 }
2289 else
2290 {
2291 DXGK_SEGMENTDESCRIPTOR* pDr = pQsOut->pSegmentDescriptor;
2292 /* we are requested to provide segment information */
2293 pDr->BaseAddress.QuadPart = 0;
2294 pDr->CpuTranslatedAddress = VBoxCommonFromDeviceExt(pDevExt)->phVRAM;
2295 /* make sure the size is page aligned */
2296 /** @todo need to setup VBVA buffers and adjust the mem size here */
2297 pDr->Size = vboxWddmVramCpuVisibleSegmentSize(pDevExt);
2298 pDr->NbOfBanks = 0;
2299 pDr->pBankRangeTable = 0;
2300 pDr->CommitLimit = pDr->Size;
2301 pDr->Flags.Value = 0;
2302 pDr->Flags.CpuVisible = 1;
2303
2304 ++pDr;
2305 /* create cpu-invisible segment of the same size */
2306 pDr->BaseAddress.QuadPart = 0;
2307 pDr->CpuTranslatedAddress.QuadPart = 0;
2308 /* make sure the size is page aligned */
2309 /** @todo need to setup VBVA buffers and adjust the mem size here */
2310 pDr->Size = vboxWddmVramCpuInvisibleSegmentSize(pDevExt);
2311 pDr->NbOfBanks = 0;
2312 pDr->pBankRangeTable = 0;
2313 pDr->CommitLimit = pDr->Size;
2314 pDr->Flags.Value = 0;
2315
2316 pQsOut->PagingBufferSegmentId = 0;
2317 pQsOut->PagingBufferSize = PAGE_SIZE;
2318 pQsOut->PagingBufferPrivateDataSize = PAGE_SIZE;
2319 }
2320 }
2321 else
2322 {
2323 WARN(("unsupported Type (%d)", pQueryAdapterInfo->Type));
2324 Status = STATUS_NOT_SUPPORTED;
2325 }
2326
2327 break;
2328 }
2329 case DXGKQAITYPE_UMDRIVERPRIVATE:
2330 if (!g_VBoxDisplayOnly)
2331 {
2332 if (pQueryAdapterInfo->OutputDataSize >= sizeof(VBOXWDDM_QAI))
2333 {
2334 VBOXWDDM_QAI *pQAI = (VBOXWDDM_QAI *)pQueryAdapterInfo->pOutputData;
2335 memset(pQAI, 0, sizeof(VBOXWDDM_QAI));
2336
2337 pQAI->u32Version = VBOXVIDEOIF_VERSION;
2338 pQAI->enmHwType = pDevExt->enmHwType;
2339 if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VBOX)
2340 {
2341#ifdef VBOX_WITH_CROGL
2342 pQAI->u.vbox.u32VBox3DCaps = VBoxMpCrGetHostCaps();
2343#endif
2344 }
2345#ifdef VBOX_WITH_VIDEOHWACCEL
2346 pQAI->cInfos = VBoxCommonFromDeviceExt(pDevExt)->cDisplays;
2347 for (uint32_t i = 0; i < pQAI->cInfos; ++i)
2348 {
2349 pQAI->aInfos[i] = pDevExt->aSources[i].Vhwa.Settings;
2350 }
2351#endif
2352 }
2353 else
2354 {
2355 WARN(("incorrect buffer size %d, expected %d", pQueryAdapterInfo->OutputDataSize, sizeof(VBOXWDDM_QAI)));
2356 Status = STATUS_BUFFER_TOO_SMALL;
2357 }
2358 }
2359 else
2360 {
2361 WARN(("unsupported Type (%d)", pQueryAdapterInfo->Type));
2362 Status = STATUS_NOT_SUPPORTED;
2363 }
2364 break;
2365
2366 case DXGKQAITYPE_QUERYSEGMENT3:
2367 LOGREL(("DXGKQAITYPE_QUERYSEGMENT3 treating as unsupported!"));
2368 Status = STATUS_NOT_SUPPORTED;
2369 break;
2370
2371 default:
2372 WARN(("unsupported Type (%d)", pQueryAdapterInfo->Type));
2373 Status = STATUS_NOT_SUPPORTED;
2374 break;
2375 }
2376 LOGF(("LEAVE, context(0x%x), Status(0x%x)", hAdapter, Status));
2377 return Status;
2378}
2379
2380/**
2381 * DxgkDdiCreateDevice
2382 */
2383NTSTATUS APIENTRY DxgkDdiCreateDevice(
2384 CONST HANDLE hAdapter,
2385 DXGKARG_CREATEDEVICE* pCreateDevice)
2386{
2387 /* DxgkDdiCreateDevice should be made pageable. */
2388 PAGED_CODE();
2389
2390 LOGF(("ENTER, context(0x%x)", hAdapter));
2391 NTSTATUS Status = STATUS_SUCCESS;
2392 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
2393
2394 vboxVDbgBreakFv();
2395
2396 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)vboxWddmMemAllocZero(sizeof (VBOXWDDM_DEVICE));
2397 if (!pDevice)
2398 {
2399 WARN(("vboxWddmMemAllocZero failed for WDDM device structure"));
2400 return STATUS_NO_MEMORY;
2401 }
2402
2403 pDevice->pAdapter = pDevExt;
2404 pDevice->hDevice = pCreateDevice->hDevice;
2405
2406 pCreateDevice->hDevice = pDevice;
2407 if (pCreateDevice->Flags.SystemDevice)
2408 pDevice->enmType = VBOXWDDM_DEVICE_TYPE_SYSTEM;
2409
2410 pCreateDevice->pInfo = NULL;
2411
2412 LOGF(("LEAVE, context(0x%x), Status(0x%x)", hAdapter, Status));
2413
2414 return Status;
2415}
2416
2417PVBOXWDDM_RESOURCE vboxWddmResourceCreate(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_RCINFO pRcInfo)
2418{
2419 RT_NOREF(pDevExt);
2420 PVBOXWDDM_RESOURCE pResource = (PVBOXWDDM_RESOURCE)vboxWddmMemAllocZero(RT_UOFFSETOF_DYN(VBOXWDDM_RESOURCE,
2421 aAllocations[pRcInfo->cAllocInfos]));
2422 if (!pResource)
2423 {
2424 AssertFailed();
2425 return NULL;
2426 }
2427 pResource->cRefs = 1;
2428 pResource->cAllocations = pRcInfo->cAllocInfos;
2429 pResource->fFlags = pRcInfo->fFlags;
2430 pResource->RcDesc = pRcInfo->RcDesc;
2431 return pResource;
2432}
2433
2434VOID vboxWddmResourceRetain(PVBOXWDDM_RESOURCE pResource)
2435{
2436 ASMAtomicIncU32(&pResource->cRefs);
2437}
2438
2439static VOID vboxWddmResourceDestroy(PVBOXWDDM_RESOURCE pResource)
2440{
2441 vboxWddmMemFree(pResource);
2442}
2443
2444VOID vboxWddmResourceWaitDereference(PVBOXWDDM_RESOURCE pResource)
2445{
2446 vboxWddmCounterU32Wait(&pResource->cRefs, 1);
2447}
2448
2449VOID vboxWddmResourceRelease(PVBOXWDDM_RESOURCE pResource)
2450{
2451 uint32_t cRefs = ASMAtomicDecU32(&pResource->cRefs);
2452 Assert(cRefs < UINT32_MAX/2);
2453 if (!cRefs)
2454 {
2455 vboxWddmResourceDestroy(pResource);
2456 }
2457}
2458
2459void vboxWddmAllocationDeleteFromResource(PVBOXWDDM_RESOURCE pResource, PVBOXWDDM_ALLOCATION pAllocation)
2460{
2461 Assert(pAllocation->pResource == pResource);
2462 if (pResource)
2463 {
2464 Assert(&pResource->aAllocations[pAllocation->iIndex] == pAllocation);
2465 vboxWddmResourceRelease(pResource);
2466 }
2467 else
2468 {
2469 vboxWddmMemFree(pAllocation);
2470 }
2471}
2472
2473VOID vboxWddmAllocationCleanupAssignment(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pAllocation)
2474{
2475 switch (pAllocation->enmType)
2476 {
2477 case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
2478 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
2479 {
2480 if (pAllocation->bAssigned)
2481 {
2482 /** @todo do we need to notify host? */
2483 vboxWddmAssignPrimary(&pDevExt->aSources[pAllocation->AllocData.SurfDesc.VidPnSourceId], NULL, pAllocation->AllocData.SurfDesc.VidPnSourceId);
2484 }
2485 break;
2486 }
2487 default:
2488 break;
2489 }
2490}
2491
2492VOID vboxWddmAllocationCleanup(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pAllocation)
2493{
2494 switch (pAllocation->enmType)
2495 {
2496 case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
2497 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
2498 {
2499#if 0
2500 if (pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC)
2501 {
2502 if (pAllocation->hSharedHandle)
2503 {
2504 vboxShRcTreeRemove(pDevExt, pAllocation);
2505 }
2506 }
2507#endif
2508 break;
2509 }
2510 case VBOXWDDM_ALLOC_TYPE_UMD_HGSMI_BUFFER:
2511 {
2512 break;
2513 }
2514 default:
2515 break;
2516 }
2517#ifdef VBOX_WITH_CROGL
2518 PVBOXWDDM_SWAPCHAIN pSwapchain = vboxWddmSwapchainRetainByAlloc(pDevExt, pAllocation);
2519 if (pSwapchain)
2520 {
2521 vboxWddmSwapchainAllocRemove(pDevExt, pSwapchain, pAllocation);
2522 vboxWddmSwapchainRelease(pSwapchain);
2523 }
2524#endif
2525}
2526
2527VOID vboxWddmAllocationDestroy(PVBOXWDDM_ALLOCATION pAllocation)
2528{
2529 PAGED_CODE();
2530
2531 vboxWddmAllocationDeleteFromResource(pAllocation->pResource, pAllocation);
2532}
2533
2534PVBOXWDDM_ALLOCATION vboxWddmAllocationCreateFromResource(PVBOXWDDM_RESOURCE pResource, uint32_t iIndex)
2535{
2536 PVBOXWDDM_ALLOCATION pAllocation = NULL;
2537 if (pResource)
2538 {
2539 Assert(iIndex < pResource->cAllocations);
2540 if (iIndex < pResource->cAllocations)
2541 {
2542 pAllocation = &pResource->aAllocations[iIndex];
2543 memset(pAllocation, 0, sizeof (VBOXWDDM_ALLOCATION));
2544 }
2545 vboxWddmResourceRetain(pResource);
2546 }
2547 else
2548 pAllocation = (PVBOXWDDM_ALLOCATION)vboxWddmMemAllocZero(sizeof (VBOXWDDM_ALLOCATION));
2549
2550 if (pAllocation)
2551 {
2552 if (pResource)
2553 {
2554 pAllocation->pResource = pResource;
2555 pAllocation->iIndex = iIndex;
2556 }
2557 }
2558
2559 return pAllocation;
2560}
2561
2562NTSTATUS vboxWddmAllocationCreate(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_RESOURCE pResource, uint32_t iIndex, DXGK_ALLOCATIONINFO* pAllocationInfo)
2563{
2564 PAGED_CODE();
2565
2566 NTSTATUS Status = STATUS_SUCCESS;
2567
2568 Assert(pAllocationInfo->PrivateDriverDataSize == sizeof (VBOXWDDM_ALLOCINFO));
2569 if (pAllocationInfo->PrivateDriverDataSize >= sizeof (VBOXWDDM_ALLOCINFO))
2570 {
2571 PVBOXWDDM_ALLOCINFO pAllocInfo = (PVBOXWDDM_ALLOCINFO)pAllocationInfo->pPrivateDriverData;
2572 PVBOXWDDM_ALLOCATION pAllocation = vboxWddmAllocationCreateFromResource(pResource, iIndex);
2573 Assert(pAllocation);
2574 if (pAllocation)
2575 {
2576 pAllocationInfo->pPrivateDriverData = NULL;
2577 pAllocationInfo->PrivateDriverDataSize = 0;
2578 pAllocationInfo->Alignment = 0;
2579 pAllocationInfo->PitchAlignedSize = 0;
2580 pAllocationInfo->HintedBank.Value = 0;
2581 pAllocationInfo->PreferredSegment.Value = 0;
2582 pAllocationInfo->SupportedReadSegmentSet = 1;
2583 pAllocationInfo->SupportedWriteSegmentSet = 1;
2584 pAllocationInfo->EvictionSegmentSet = 0;
2585 pAllocationInfo->MaximumRenamingListLength = 0;
2586 pAllocationInfo->hAllocation = pAllocation;
2587 pAllocationInfo->Flags.Value = 0;
2588 pAllocationInfo->pAllocationUsageHint = NULL;
2589 pAllocationInfo->AllocationPriority = D3DDDI_ALLOCATIONPRIORITY_NORMAL;
2590
2591 pAllocation->enmType = pAllocInfo->enmType;
2592 pAllocation->AllocData.Addr.SegmentId = 0;
2593 pAllocation->AllocData.Addr.offVram = VBOXVIDEOOFFSET_VOID;
2594 pAllocation->bVisible = FALSE;
2595 pAllocation->bAssigned = FALSE;
2596 KeInitializeSpinLock(&pAllocation->OpenLock);
2597 InitializeListHead(&pAllocation->OpenList);
2598
2599 switch (pAllocInfo->enmType)
2600 {
2601 case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
2602 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
2603 case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
2604 case VBOXWDDM_ALLOC_TYPE_STD_STAGINGSURFACE:
2605 {
2606 pAllocation->fRcFlags = pAllocInfo->fFlags;
2607 pAllocation->AllocData.SurfDesc = pAllocInfo->SurfDesc;
2608 pAllocation->AllocData.hostID = pAllocInfo->hostID;
2609
2610 pAllocationInfo->Size = pAllocInfo->SurfDesc.cbSize;
2611
2612 switch (pAllocInfo->enmType)
2613 {
2614 case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
2615 break;
2616 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
2617#ifdef VBOX_WITH_VIDEOHWACCEL
2618 if (pAllocInfo->fFlags.Overlay)
2619 {
2620 /* actually we can not "properly" issue create overlay commands to the host here
2621 * because we do not know source VidPn id here, i.e.
2622 * the primary which is supposed to be overlayed,
2623 * however we need to get some info like pitch & size from the host here */
2624 int rc = vboxVhwaHlpGetSurfInfo(pDevExt, pAllocation);
2625 AssertRC(rc);
2626 if (RT_SUCCESS(rc))
2627 {
2628 pAllocationInfo->Flags.Overlay = 1;
2629 pAllocationInfo->Flags.CpuVisible = 1;
2630 pAllocationInfo->Size = pAllocation->AllocData.SurfDesc.cbSize;
2631
2632 pAllocationInfo->AllocationPriority = D3DDDI_ALLOCATIONPRIORITY_HIGH;
2633 }
2634 else
2635 Status = STATUS_UNSUCCESSFUL;
2636 }
2637 else
2638#endif
2639 {
2640 Assert(pAllocation->AllocData.SurfDesc.bpp);
2641 Assert(pAllocation->AllocData.SurfDesc.pitch);
2642 Assert(pAllocation->AllocData.SurfDesc.cbSize);
2643
2644 /*
2645 * Mark the allocation as visible to the CPU so we can
2646 * lock it in the user mode driver for SYSTEM pool allocations.
2647 * See @bugref{8040} for further information.
2648 */
2649 if (!pAllocInfo->fFlags.SharedResource && !pAllocInfo->hostID)
2650 pAllocationInfo->Flags.CpuVisible = 1;
2651
2652 if (pAllocInfo->fFlags.SharedResource)
2653 {
2654 pAllocation->hSharedHandle = (HANDLE)pAllocInfo->hSharedHandle;
2655#if 0
2656 if (pAllocation->hSharedHandle)
2657 {
2658 vboxShRcTreePut(pDevExt, pAllocation);
2659 }
2660#endif
2661 }
2662
2663#if 0
2664 /* Allocation from the CPU invisible second segment does not
2665 * work apparently and actually fails on Vista.
2666 *
2667 * @todo Find out what exactly is wrong.
2668 */
2669// if (pAllocInfo->hostID)
2670 {
2671 pAllocationInfo->SupportedReadSegmentSet = 2;
2672 pAllocationInfo->SupportedWriteSegmentSet = 2;
2673 }
2674#endif
2675 }
2676 break;
2677 case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
2678 case VBOXWDDM_ALLOC_TYPE_STD_STAGINGSURFACE:
2679 pAllocationInfo->Flags.CpuVisible = 1;
2680 break;
2681 default: AssertFailedBreak(); /* Shut up MSC.*/
2682 }
2683
2684 if (Status == STATUS_SUCCESS)
2685 {
2686 pAllocation->UsageHint.Version = 0;
2687 pAllocation->UsageHint.v1.Flags.Value = 0;
2688 pAllocation->UsageHint.v1.Format = pAllocInfo->SurfDesc.format;
2689 pAllocation->UsageHint.v1.SwizzledFormat = 0;
2690 pAllocation->UsageHint.v1.ByteOffset = 0;
2691 pAllocation->UsageHint.v1.Width = pAllocation->AllocData.SurfDesc.width;
2692 pAllocation->UsageHint.v1.Height = pAllocation->AllocData.SurfDesc.height;
2693 pAllocation->UsageHint.v1.Pitch = pAllocation->AllocData.SurfDesc.pitch;
2694 pAllocation->UsageHint.v1.Depth = 0;
2695 pAllocation->UsageHint.v1.SlicePitch = 0;
2696
2697 Assert(!pAllocationInfo->pAllocationUsageHint);
2698 pAllocationInfo->pAllocationUsageHint = &pAllocation->UsageHint;
2699 }
2700
2701 break;
2702 }
2703 case VBOXWDDM_ALLOC_TYPE_UMD_HGSMI_BUFFER:
2704 {
2705 pAllocationInfo->Size = pAllocInfo->cbBuffer;
2706 pAllocation->fUhgsmiType = pAllocInfo->fUhgsmiType;
2707 pAllocation->AllocData.SurfDesc.cbSize = pAllocInfo->cbBuffer;
2708 pAllocationInfo->Flags.CpuVisible = 1;
2709// pAllocationInfo->Flags.SynchronousPaging = 1;
2710 pAllocationInfo->AllocationPriority = D3DDDI_ALLOCATIONPRIORITY_MAXIMUM;
2711 break;
2712 }
2713
2714 default:
2715 LOGREL(("ERROR: invalid alloc info type(%d)", pAllocInfo->enmType));
2716 AssertBreakpoint();
2717 Status = STATUS_INVALID_PARAMETER;
2718 break;
2719
2720 }
2721
2722 if (Status != STATUS_SUCCESS)
2723 vboxWddmAllocationDeleteFromResource(pResource, pAllocation);
2724 }
2725 else
2726 {
2727 LOGREL(("ERROR: failed to create allocation description"));
2728 Status = STATUS_NO_MEMORY;
2729 }
2730
2731 }
2732 else
2733 {
2734 LOGREL(("ERROR: PrivateDriverDataSize(%d) less than header size(%d)", pAllocationInfo->PrivateDriverDataSize, sizeof (VBOXWDDM_ALLOCINFO)));
2735 Status = STATUS_INVALID_PARAMETER;
2736 }
2737
2738 return Status;
2739}
2740
2741NTSTATUS APIENTRY DxgkDdiCreateAllocation(
2742 CONST HANDLE hAdapter,
2743 DXGKARG_CREATEALLOCATION* pCreateAllocation)
2744{
2745 /* DxgkDdiCreateAllocation should be made pageable. */
2746 PAGED_CODE();
2747
2748 LOGF(("ENTER, context(0x%x)", hAdapter));
2749
2750 vboxVDbgBreakFv();
2751
2752 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
2753 NTSTATUS Status = STATUS_SUCCESS;
2754 PVBOXWDDM_RESOURCE pResource = NULL;
2755
2756 if (pCreateAllocation->PrivateDriverDataSize)
2757 {
2758 Assert(pCreateAllocation->PrivateDriverDataSize == sizeof (VBOXWDDM_RCINFO));
2759 Assert(pCreateAllocation->pPrivateDriverData);
2760 if (pCreateAllocation->PrivateDriverDataSize < sizeof (VBOXWDDM_RCINFO))
2761 {
2762 WARN(("invalid private data size (%d)", pCreateAllocation->PrivateDriverDataSize));
2763 return STATUS_INVALID_PARAMETER;
2764 }
2765
2766 PVBOXWDDM_RCINFO pRcInfo = (PVBOXWDDM_RCINFO)pCreateAllocation->pPrivateDriverData;
2767// Assert(pRcInfo->RcDesc.VidPnSourceId < VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
2768 if (pRcInfo->cAllocInfos != pCreateAllocation->NumAllocations)
2769 {
2770 WARN(("invalid number of allocations passed in, (%d), expected (%d)", pRcInfo->cAllocInfos, pCreateAllocation->NumAllocations));
2771 return STATUS_INVALID_PARAMETER;
2772 }
2773
2774 /* a check to ensure we do not get the allocation size which is too big to overflow the 32bit value */
2775 if (VBOXWDDM_TRAILARRAY_MAXELEMENTSU32(VBOXWDDM_RESOURCE, aAllocations) < pRcInfo->cAllocInfos)
2776 {
2777 WARN(("number of allocations passed too big (%d), max is (%d)", pRcInfo->cAllocInfos, VBOXWDDM_TRAILARRAY_MAXELEMENTSU32(VBOXWDDM_RESOURCE, aAllocations)));
2778 return STATUS_INVALID_PARAMETER;
2779 }
2780
2781 pResource = (PVBOXWDDM_RESOURCE)vboxWddmMemAllocZero(RT_UOFFSETOF_DYN(VBOXWDDM_RESOURCE, aAllocations[pRcInfo->cAllocInfos]));
2782 if (!pResource)
2783 {
2784 WARN(("vboxWddmMemAllocZero failed for (%d) allocations", pRcInfo->cAllocInfos));
2785 return STATUS_NO_MEMORY;
2786 }
2787
2788 pResource->cRefs = 1;
2789 pResource->cAllocations = pRcInfo->cAllocInfos;
2790 pResource->fFlags = pRcInfo->fFlags;
2791 pResource->RcDesc = pRcInfo->RcDesc;
2792 }
2793
2794
2795 for (UINT i = 0; i < pCreateAllocation->NumAllocations; ++i)
2796 {
2797 Status = vboxWddmAllocationCreate(pDevExt, pResource, i, &pCreateAllocation->pAllocationInfo[i]);
2798 if (Status != STATUS_SUCCESS)
2799 {
2800 WARN(("vboxWddmAllocationCreate(%d) failed, Status(0x%x)", i, Status));
2801 /* note: i-th allocation is expected to be cleared in a fail handling code above */
2802 for (UINT j = 0; j < i; ++j)
2803 {
2804 PVBOXWDDM_ALLOCATION pAllocation = (PVBOXWDDM_ALLOCATION)pCreateAllocation->pAllocationInfo[j].hAllocation;
2805 vboxWddmAllocationCleanup(pDevExt, pAllocation);
2806 vboxWddmAllocationDestroy(pAllocation);
2807 }
2808 break;
2809 }
2810 }
2811
2812 if (Status == STATUS_SUCCESS)
2813 {
2814 pCreateAllocation->hResource = pResource;
2815 }
2816 else
2817 {
2818 if (pResource)
2819 vboxWddmResourceRelease(pResource);
2820 }
2821
2822 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
2823
2824 return Status;
2825}
2826
2827NTSTATUS
2828APIENTRY
2829DxgkDdiDestroyAllocation(
2830 CONST HANDLE hAdapter,
2831 CONST DXGKARG_DESTROYALLOCATION* pDestroyAllocation)
2832{
2833 /* DxgkDdiDestroyAllocation should be made pageable. */
2834 PAGED_CODE();
2835
2836 LOGF(("ENTER, context(0x%x)", hAdapter));
2837
2838 vboxVDbgBreakFv();
2839
2840 NTSTATUS Status = STATUS_SUCCESS;
2841
2842 PVBOXWDDM_RESOURCE pRc = (PVBOXWDDM_RESOURCE)pDestroyAllocation->hResource;
2843 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
2844
2845 if (pRc)
2846 {
2847 Assert(pRc->cAllocations == pDestroyAllocation->NumAllocations);
2848 }
2849
2850 for (UINT i = 0; i < pDestroyAllocation->NumAllocations; ++i)
2851 {
2852 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pDestroyAllocation->pAllocationList[i];
2853 Assert(pAlloc->pResource == pRc);
2854 vboxWddmAllocationCleanupAssignment(pDevExt, pAlloc);
2855 /* wait for all current allocation-related ops are completed */
2856 vboxWddmAllocationCleanup(pDevExt, pAlloc);
2857 if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VBOX && pAlloc->hSharedHandle && pAlloc->AllocData.hostID)
2858 VBoxVdmaChromiumParameteriCRSubmit(pDevExt, GL_PIN_TEXTURE_CLEAR_CR, pAlloc->AllocData.hostID);
2859 vboxWddmAllocationDestroy(pAlloc);
2860 }
2861
2862 if (pRc)
2863 {
2864 /* wait for all current resource-related ops are completed */
2865 vboxWddmResourceWaitDereference(pRc);
2866 vboxWddmResourceRelease(pRc);
2867 }
2868
2869 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
2870
2871 return Status;
2872}
2873
2874/**
2875 * DxgkDdiDescribeAllocation
2876 */
2877NTSTATUS
2878APIENTRY
2879DxgkDdiDescribeAllocation(
2880 CONST HANDLE hAdapter,
2881 DXGKARG_DESCRIBEALLOCATION* pDescribeAllocation)
2882{
2883 RT_NOREF(hAdapter);
2884// LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
2885
2886 vboxVDbgBreakFv();
2887
2888 PVBOXWDDM_ALLOCATION pAllocation = (PVBOXWDDM_ALLOCATION)pDescribeAllocation->hAllocation;
2889 pDescribeAllocation->Width = pAllocation->AllocData.SurfDesc.width;
2890 pDescribeAllocation->Height = pAllocation->AllocData.SurfDesc.height;
2891 pDescribeAllocation->Format = pAllocation->AllocData.SurfDesc.format;
2892 memset (&pDescribeAllocation->MultisampleMethod, 0, sizeof (pDescribeAllocation->MultisampleMethod));
2893 pDescribeAllocation->RefreshRate.Numerator = 60000;
2894 pDescribeAllocation->RefreshRate.Denominator = 1000;
2895 pDescribeAllocation->PrivateDriverFormatAttribute = 0;
2896
2897// LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
2898
2899 return STATUS_SUCCESS;
2900}
2901
2902/**
2903 * DxgkDdiGetStandardAllocationDriverData
2904 */
2905NTSTATUS
2906APIENTRY
2907DxgkDdiGetStandardAllocationDriverData(
2908 CONST HANDLE hAdapter,
2909 DXGKARG_GETSTANDARDALLOCATIONDRIVERDATA* pGetStandardAllocationDriverData)
2910{
2911 RT_NOREF(hAdapter);
2912 /* DxgkDdiGetStandardAllocationDriverData should be made pageable. */
2913 PAGED_CODE();
2914
2915 LOGF(("ENTER, context(0x%x)", hAdapter));
2916
2917 vboxVDbgBreakFv();
2918
2919 NTSTATUS Status = STATUS_SUCCESS;
2920 PVBOXWDDM_ALLOCINFO pAllocInfo = NULL;
2921
2922 switch (pGetStandardAllocationDriverData->StandardAllocationType)
2923 {
2924 case D3DKMDT_STANDARDALLOCATION_SHAREDPRIMARYSURFACE:
2925 {
2926 LOGF(("D3DKMDT_STANDARDALLOCATION_SHAREDPRIMARYSURFACE"));
2927 if(pGetStandardAllocationDriverData->pAllocationPrivateDriverData)
2928 {
2929 pAllocInfo = (PVBOXWDDM_ALLOCINFO)pGetStandardAllocationDriverData->pAllocationPrivateDriverData;
2930 memset (pAllocInfo, 0, sizeof (VBOXWDDM_ALLOCINFO));
2931 pAllocInfo->enmType = VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE;
2932 pAllocInfo->SurfDesc.width = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Width;
2933 pAllocInfo->SurfDesc.height = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Height;
2934 pAllocInfo->SurfDesc.format = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Format;
2935 pAllocInfo->SurfDesc.bpp = vboxWddmCalcBitsPerPixel(pAllocInfo->SurfDesc.format);
2936 pAllocInfo->SurfDesc.pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Width, pAllocInfo->SurfDesc.format);
2937 pAllocInfo->SurfDesc.cbSize = vboxWddmCalcSize(pAllocInfo->SurfDesc.pitch, pAllocInfo->SurfDesc.height, pAllocInfo->SurfDesc.format);
2938 pAllocInfo->SurfDesc.depth = 0;
2939 pAllocInfo->SurfDesc.slicePitch = 0;
2940 pAllocInfo->SurfDesc.RefreshRate = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->RefreshRate;
2941 pAllocInfo->SurfDesc.VidPnSourceId = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->VidPnSourceId;
2942 }
2943 pGetStandardAllocationDriverData->AllocationPrivateDriverDataSize = sizeof (VBOXWDDM_ALLOCINFO);
2944
2945 pGetStandardAllocationDriverData->ResourcePrivateDriverDataSize = 0;
2946 break;
2947 }
2948 case D3DKMDT_STANDARDALLOCATION_SHADOWSURFACE:
2949 {
2950 LOGF(("D3DKMDT_STANDARDALLOCATION_SHADOWSURFACE"));
2951 UINT bpp = vboxWddmCalcBitsPerPixel(pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format);
2952 Assert(bpp);
2953 if (bpp != 0)
2954 {
2955 UINT Pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Width, pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format);
2956 pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Pitch = Pitch;
2957
2958 /** @todo need [d/q]word align?? */
2959
2960 if (pGetStandardAllocationDriverData->pAllocationPrivateDriverData)
2961 {
2962 pAllocInfo = (PVBOXWDDM_ALLOCINFO)pGetStandardAllocationDriverData->pAllocationPrivateDriverData;
2963 pAllocInfo->enmType = VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE;
2964 pAllocInfo->SurfDesc.width = pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Width;
2965 pAllocInfo->SurfDesc.height = pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Height;
2966 pAllocInfo->SurfDesc.format = pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format;
2967 pAllocInfo->SurfDesc.bpp = vboxWddmCalcBitsPerPixel(pAllocInfo->SurfDesc.format);
2968 pAllocInfo->SurfDesc.pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Width, pAllocInfo->SurfDesc.format);
2969 pAllocInfo->SurfDesc.cbSize = vboxWddmCalcSize(pAllocInfo->SurfDesc.pitch, pAllocInfo->SurfDesc.height, pAllocInfo->SurfDesc.format);
2970 pAllocInfo->SurfDesc.depth = 0;
2971 pAllocInfo->SurfDesc.slicePitch = 0;
2972 pAllocInfo->SurfDesc.RefreshRate.Numerator = 0;
2973 pAllocInfo->SurfDesc.RefreshRate.Denominator = 1000;
2974 pAllocInfo->SurfDesc.VidPnSourceId = D3DDDI_ID_UNINITIALIZED;
2975
2976 pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Pitch = pAllocInfo->SurfDesc.pitch;
2977 }
2978 pGetStandardAllocationDriverData->AllocationPrivateDriverDataSize = sizeof (VBOXWDDM_ALLOCINFO);
2979
2980 pGetStandardAllocationDriverData->ResourcePrivateDriverDataSize = 0;
2981 }
2982 else
2983 {
2984 LOGREL(("Invalid format (%d)", pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format));
2985 Status = STATUS_INVALID_PARAMETER;
2986 }
2987 break;
2988 }
2989 case D3DKMDT_STANDARDALLOCATION_STAGINGSURFACE:
2990 {
2991 LOGF(("D3DKMDT_STANDARDALLOCATION_STAGINGSURFACE"));
2992 if(pGetStandardAllocationDriverData->pAllocationPrivateDriverData)
2993 {
2994 pAllocInfo = (PVBOXWDDM_ALLOCINFO)pGetStandardAllocationDriverData->pAllocationPrivateDriverData;
2995 pAllocInfo->enmType = VBOXWDDM_ALLOC_TYPE_STD_STAGINGSURFACE;
2996 pAllocInfo->SurfDesc.width = pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Width;
2997 pAllocInfo->SurfDesc.height = pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Height;
2998 pAllocInfo->SurfDesc.format = D3DDDIFMT_X8R8G8B8; /* staging has always always D3DDDIFMT_X8R8G8B8 */
2999 pAllocInfo->SurfDesc.bpp = vboxWddmCalcBitsPerPixel(pAllocInfo->SurfDesc.format);
3000 pAllocInfo->SurfDesc.pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Width, pAllocInfo->SurfDesc.format);
3001 pAllocInfo->SurfDesc.cbSize = vboxWddmCalcSize(pAllocInfo->SurfDesc.pitch, pAllocInfo->SurfDesc.height, pAllocInfo->SurfDesc.format);
3002 pAllocInfo->SurfDesc.depth = 0;
3003 pAllocInfo->SurfDesc.slicePitch = 0;
3004 pAllocInfo->SurfDesc.RefreshRate.Numerator = 0;
3005 pAllocInfo->SurfDesc.RefreshRate.Denominator = 1000;
3006 pAllocInfo->SurfDesc.VidPnSourceId = D3DDDI_ID_UNINITIALIZED;
3007
3008 pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Pitch = pAllocInfo->SurfDesc.pitch;
3009 }
3010 pGetStandardAllocationDriverData->AllocationPrivateDriverDataSize = sizeof (VBOXWDDM_ALLOCINFO);
3011
3012 pGetStandardAllocationDriverData->ResourcePrivateDriverDataSize = 0;
3013 break;
3014 }
3015//#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
3016// case D3DKMDT_STANDARDALLOCATION_GDISURFACE:
3017//# error port to Win7 DDI
3018// break;
3019//#endif
3020 default:
3021 LOGREL(("Invalid allocation type (%d)", pGetStandardAllocationDriverData->StandardAllocationType));
3022 Status = STATUS_INVALID_PARAMETER;
3023 break;
3024 }
3025
3026 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
3027
3028 return Status;
3029}
3030
3031NTSTATUS
3032APIENTRY
3033DxgkDdiAcquireSwizzlingRange(
3034 CONST HANDLE hAdapter,
3035 DXGKARG_ACQUIRESWIZZLINGRANGE* pAcquireSwizzlingRange)
3036{
3037 RT_NOREF(hAdapter, pAcquireSwizzlingRange);
3038 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3039
3040 AssertBreakpoint();
3041
3042 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3043
3044 return STATUS_SUCCESS;
3045}
3046
3047NTSTATUS
3048APIENTRY
3049DxgkDdiReleaseSwizzlingRange(
3050 CONST HANDLE hAdapter,
3051 CONST DXGKARG_RELEASESWIZZLINGRANGE* pReleaseSwizzlingRange)
3052{
3053 RT_NOREF(hAdapter, pReleaseSwizzlingRange);
3054 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3055
3056 AssertBreakpoint();
3057
3058 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3059
3060 return STATUS_SUCCESS;
3061}
3062
3063#ifdef VBOX_WITH_CROGL
3064static NTSTATUS
3065APIENTRY
3066DxgkDdiPatchNew(
3067 CONST HANDLE hAdapter,
3068 CONST DXGKARG_PATCH* pPatch)
3069{
3070 RT_NOREF(hAdapter);
3071 /* DxgkDdiPatch should be made pageable. */
3072 PAGED_CODE();
3073
3074 LOGF(("ENTER, context(0x%x)", hAdapter));
3075
3076 vboxVDbgBreakFv();
3077
3078 uint8_t * pPrivateBuf = (uint8_t*)((uint8_t*)pPatch->pDmaBufferPrivateData + pPatch->DmaBufferPrivateDataSubmissionStartOffset);
3079 UINT cbPatchBuff = pPatch->DmaBufferPrivateDataSubmissionEndOffset - pPatch->DmaBufferPrivateDataSubmissionStartOffset;
3080
3081 for (UINT i = pPatch->PatchLocationListSubmissionStart; i < pPatch->PatchLocationListSubmissionLength; ++i)
3082 {
3083 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[i];
3084 Assert(pPatchList->AllocationIndex < pPatch->AllocationListSize);
3085 const DXGK_ALLOCATIONLIST *pAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
3086 if (!pAllocationList->SegmentId)
3087 {
3088 WARN(("no segment id specified"));
3089 continue;
3090 }
3091
3092 if (pPatchList->PatchOffset == ~0UL)
3093 {
3094 /* this is a dummy patch request, ignore */
3095 continue;
3096 }
3097
3098 if (pPatchList->PatchOffset >= cbPatchBuff)
3099 {
3100 WARN(("pPatchList->PatchOffset(%d) >= cbPatchBuff(%d)", pPatchList->PatchOffset, cbPatchBuff));
3101 return STATUS_INVALID_PARAMETER;
3102 }
3103
3104 VBOXCMDVBVAOFFSET *poffVram = (VBOXCMDVBVAOFFSET*)(pPrivateBuf + pPatchList->PatchOffset);
3105 Assert(pAllocationList->SegmentId);
3106 Assert(!pAllocationList->PhysicalAddress.HighPart);
3107 Assert(!(pAllocationList->PhysicalAddress.QuadPart & 0xfffUL)); /* <- just a check to ensure allocation offset does not go here */
3108 *poffVram = pAllocationList->PhysicalAddress.LowPart + pPatchList->AllocationOffset;
3109 }
3110
3111 return STATUS_SUCCESS;
3112}
3113#endif
3114
3115static NTSTATUS
3116APIENTRY
3117DxgkDdiPatchLegacy(
3118 CONST HANDLE hAdapter,
3119 CONST DXGKARG_PATCH* pPatch)
3120{
3121 RT_NOREF(hAdapter);
3122 /* DxgkDdiPatch should be made pageable. */
3123 PAGED_CODE();
3124
3125 NTSTATUS Status = STATUS_SUCCESS;
3126
3127 LOGF(("ENTER, context(0x%x)", hAdapter));
3128
3129 vboxVDbgBreakFv();
3130
3131 /* Value == 2 is Present
3132 * Value == 4 is RedirectedPresent
3133 * we do not expect any other flags to be set here */
3134// Assert(pPatch->Flags.Value == 2 || pPatch->Flags.Value == 4);
3135 if (pPatch->DmaBufferPrivateDataSubmissionEndOffset - pPatch->DmaBufferPrivateDataSubmissionStartOffset >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
3136 {
3137 Assert(pPatch->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR));
3138 VBOXWDDM_DMA_PRIVATEDATA_BASEHDR *pPrivateDataBase = (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR*)((uint8_t*)pPatch->pDmaBufferPrivateData + pPatch->DmaBufferPrivateDataSubmissionStartOffset);
3139 switch (pPrivateDataBase->enmCmd)
3140 {
3141 case VBOXVDMACMD_TYPE_DMA_PRESENT_BLT:
3142 {
3143 PVBOXWDDM_DMA_PRIVATEDATA_BLT pBlt = (PVBOXWDDM_DMA_PRIVATEDATA_BLT)pPrivateDataBase;
3144 Assert(pPatch->PatchLocationListSubmissionLength == 2);
3145 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart];
3146 Assert(pPatchList->AllocationIndex == DXGK_PRESENT_SOURCE_INDEX);
3147 Assert(pPatchList->PatchOffset == 0);
3148 const DXGK_ALLOCATIONLIST *pSrcAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
3149 Assert(pSrcAllocationList->SegmentId);
3150 pBlt->Blt.SrcAlloc.segmentIdAlloc = pSrcAllocationList->SegmentId;
3151 pBlt->Blt.SrcAlloc.offAlloc = (VBOXVIDEOOFFSET)pSrcAllocationList->PhysicalAddress.QuadPart;
3152
3153 pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart + 1];
3154 Assert(pPatchList->AllocationIndex == DXGK_PRESENT_DESTINATION_INDEX);
3155 Assert(pPatchList->PatchOffset == 4);
3156 const DXGK_ALLOCATIONLIST *pDstAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
3157 Assert(pDstAllocationList->SegmentId);
3158 pBlt->Blt.DstAlloc.segmentIdAlloc = pDstAllocationList->SegmentId;
3159 pBlt->Blt.DstAlloc.offAlloc = (VBOXVIDEOOFFSET)pDstAllocationList->PhysicalAddress.QuadPart;
3160 break;
3161 }
3162 case VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP:
3163 {
3164 PVBOXWDDM_DMA_PRIVATEDATA_FLIP pFlip = (PVBOXWDDM_DMA_PRIVATEDATA_FLIP)pPrivateDataBase;
3165 Assert(pPatch->PatchLocationListSubmissionLength == 1);
3166 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart];
3167 Assert(pPatchList->AllocationIndex == DXGK_PRESENT_SOURCE_INDEX);
3168 Assert(pPatchList->PatchOffset == 0);
3169 const DXGK_ALLOCATIONLIST *pSrcAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
3170 Assert(pSrcAllocationList->SegmentId);
3171 pFlip->Flip.Alloc.segmentIdAlloc = pSrcAllocationList->SegmentId;
3172 pFlip->Flip.Alloc.offAlloc = (VBOXVIDEOOFFSET)pSrcAllocationList->PhysicalAddress.QuadPart;
3173 break;
3174 }
3175 case VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL:
3176 {
3177 PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL pCF = (PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL)pPrivateDataBase;
3178 Assert(pPatch->PatchLocationListSubmissionLength == 1);
3179 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart];
3180 Assert(pPatchList->AllocationIndex == DXGK_PRESENT_DESTINATION_INDEX);
3181 Assert(pPatchList->PatchOffset == 0);
3182 const DXGK_ALLOCATIONLIST *pDstAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
3183 Assert(pDstAllocationList->SegmentId);
3184 pCF->ClrFill.Alloc.segmentIdAlloc = pDstAllocationList->SegmentId;
3185 pCF->ClrFill.Alloc.offAlloc = (VBOXVIDEOOFFSET)pDstAllocationList->PhysicalAddress.QuadPart;
3186 break;
3187 }
3188 case VBOXVDMACMD_TYPE_DMA_NOP:
3189 break;
3190 case VBOXVDMACMD_TYPE_CHROMIUM_CMD:
3191 {
3192 uint8_t * pPrivateBuf = (uint8_t*)pPrivateDataBase;
3193 for (UINT i = pPatch->PatchLocationListSubmissionStart; i < pPatch->PatchLocationListSubmissionLength; ++i)
3194 {
3195 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[i];
3196 Assert(pPatchList->AllocationIndex < pPatch->AllocationListSize);
3197 const DXGK_ALLOCATIONLIST *pAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
3198 Assert(pAllocationList->SegmentId);
3199 if (pAllocationList->SegmentId)
3200 {
3201 DXGK_ALLOCATIONLIST *pAllocation2Patch = (DXGK_ALLOCATIONLIST*)(pPrivateBuf + pPatchList->PatchOffset);
3202 pAllocation2Patch->SegmentId = pAllocationList->SegmentId;
3203 pAllocation2Patch->PhysicalAddress.QuadPart = pAllocationList->PhysicalAddress.QuadPart + pPatchList->AllocationOffset;
3204 Assert(!(pAllocationList->PhysicalAddress.QuadPart & 0xfffUL)); /* <- just a check to ensure allocation offset does not go here */
3205 }
3206 }
3207 break;
3208 }
3209 default:
3210 {
3211 AssertBreakpoint();
3212 uint8_t *pBuf = ((uint8_t *)pPatch->pDmaBuffer) + pPatch->DmaBufferSubmissionStartOffset;
3213 for (UINT i = pPatch->PatchLocationListSubmissionStart; i < pPatch->PatchLocationListSubmissionLength; ++i)
3214 {
3215 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[i];
3216 Assert(pPatchList->AllocationIndex < pPatch->AllocationListSize);
3217 const DXGK_ALLOCATIONLIST *pAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
3218 if (pAllocationList->SegmentId)
3219 {
3220 Assert(pPatchList->PatchOffset < (pPatch->DmaBufferSubmissionEndOffset - pPatch->DmaBufferSubmissionStartOffset));
3221 *((VBOXVIDEOOFFSET*)(pBuf+pPatchList->PatchOffset)) = (VBOXVIDEOOFFSET)pAllocationList->PhysicalAddress.QuadPart;
3222 }
3223 else
3224 {
3225 /* sanity */
3226 if (pPatch->Flags.Value == 2 || pPatch->Flags.Value == 4)
3227 Assert(i == 0);
3228 }
3229 }
3230 break;
3231 }
3232 }
3233 }
3234 else if (pPatch->DmaBufferPrivateDataSubmissionEndOffset == pPatch->DmaBufferPrivateDataSubmissionStartOffset)
3235 {
3236 /* this is a NOP, just return success */
3237// LOG(("null data size, treating as NOP"));
3238 return STATUS_SUCCESS;
3239 }
3240 else
3241 {
3242 WARN(("DmaBufferPrivateDataSubmissionEndOffset (%d) - DmaBufferPrivateDataSubmissionStartOffset (%d) < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR) (%d)",
3243 pPatch->DmaBufferPrivateDataSubmissionEndOffset,
3244 pPatch->DmaBufferPrivateDataSubmissionStartOffset,
3245 sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
3246 return STATUS_INVALID_PARAMETER;
3247 }
3248
3249 LOGF(("LEAVE, context(0x%x)", hAdapter));
3250
3251 return Status;
3252}
3253
3254typedef struct VBOXWDDM_CALL_ISR
3255{
3256 PVBOXMP_DEVEXT pDevExt;
3257 ULONG MessageNumber;
3258} VBOXWDDM_CALL_ISR, *PVBOXWDDM_CALL_ISR;
3259
3260static BOOLEAN vboxWddmCallIsrCb(PVOID Context)
3261{
3262 PVBOXWDDM_CALL_ISR pdc = (PVBOXWDDM_CALL_ISR)Context;
3263 PVBOXMP_DEVEXT pDevExt = pdc->pDevExt;
3264#ifdef VBOX_WITH_CROGL
3265 if (pDevExt->fCmdVbvaEnabled)
3266 return DxgkDdiInterruptRoutineNew(pDevExt, pdc->MessageNumber);
3267#endif
3268 return DxgkDdiInterruptRoutineLegacy(pDevExt, pdc->MessageNumber);
3269}
3270
3271NTSTATUS vboxWddmCallIsr(PVBOXMP_DEVEXT pDevExt)
3272{
3273 VBOXWDDM_CALL_ISR context;
3274 context.pDevExt = pDevExt;
3275 context.MessageNumber = 0;
3276 BOOLEAN bRet;
3277 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
3278 pDevExt->u.primary.DxgkInterface.DeviceHandle,
3279 vboxWddmCallIsrCb,
3280 &context,
3281 0, /* IN ULONG MessageNumber */
3282 &bRet);
3283 AssertNtStatusSuccess(Status);
3284 return Status;
3285}
3286
3287#ifdef VBOX_WITH_CRHGSMI
3288DECLCALLBACK(VOID) vboxWddmDmaCompleteChromiumCmd(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext)
3289{
3290 RT_NOREF(pCmd);
3291 PVBOXVDMACBUF_DR pDr = (PVBOXVDMACBUF_DR)pvContext;
3292 vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
3293}
3294#endif
3295
3296#ifdef VBOX_WITH_CROGL
3297static NTSTATUS
3298APIENTRY
3299DxgkDdiSubmitCommandNew(
3300 CONST HANDLE hAdapter,
3301 CONST DXGKARG_SUBMITCOMMAND* pSubmitCommand)
3302{
3303 /* DxgkDdiSubmitCommand runs at dispatch, should not be pageable. */
3304
3305// LOGF(("ENTER, context(0x%x)", hAdapter));
3306
3307 vboxVDbgBreakFv();
3308
3309 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3310#ifdef VBOX_STRICT
3311 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pSubmitCommand->hContext;
3312 Assert(pContext);
3313 Assert(pContext->pDevice);
3314 Assert(pContext->pDevice->pAdapter == pDevExt);
3315 Assert(!pSubmitCommand->DmaBufferSegmentId);
3316#endif
3317
3318 uint32_t cbCmd = pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset - pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset;
3319 uint32_t cbDma = pSubmitCommand->DmaBufferSubmissionEndOffset - pSubmitCommand->DmaBufferSubmissionStartOffset;
3320 VBOXCMDVBVA_HDR *pHdr;
3321 VBOXCMDVBVA_HDR NopCmd;
3322 uint32_t cbCurCmd, cbCurDma;
3323 if (cbCmd < sizeof (VBOXCMDVBVA_HDR))
3324 {
3325 if (cbCmd || cbDma)
3326 {
3327 WARN(("invalid command data"));
3328 return STATUS_INVALID_PARAMETER;
3329 }
3330 Assert(!cbDma);
3331 NopCmd.u8OpCode = VBOXCMDVBVA_OPTYPE_NOPCMD;
3332 NopCmd.u8Flags = 0;
3333 NopCmd.u8State = VBOXCMDVBVA_STATE_SUBMITTED;
3334 NopCmd.u2.complexCmdEl.u16CbCmdHost = sizeof (VBOXCMDVBVA_HDR);
3335 NopCmd.u2.complexCmdEl.u16CbCmdGuest = 0;
3336 cbCmd = sizeof (VBOXCMDVBVA_HDR);
3337 pHdr = &NopCmd;
3338 cbCurCmd = sizeof (VBOXCMDVBVA_HDR);
3339 cbCurDma = 0;
3340 }
3341 else
3342 {
3343 pHdr = (VBOXCMDVBVA_HDR*)(((uint8_t*)pSubmitCommand->pDmaBufferPrivateData) + pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset);
3344 cbCurCmd = pHdr->u2.complexCmdEl.u16CbCmdHost;
3345 cbCurDma = pHdr->u2.complexCmdEl.u16CbCmdGuest;
3346 }
3347
3348
3349 VBOXCMDVBVA_HDR *pDstHdr, *pCurDstCmd;
3350 if (cbCmd != cbCurCmd || cbCurDma != cbDma)
3351 {
3352 if (cbCmd < cbCurCmd || cbDma < cbCurDma)
3353 {
3354 WARN(("incorrect buffer size"));
3355 return STATUS_INVALID_PARAMETER;
3356 }
3357
3358 pDstHdr = VBoxCmdVbvaSubmitLock(pDevExt, &pDevExt->CmdVbva, cbCmd + sizeof (VBOXCMDVBVA_HDR));
3359 if (!pDstHdr)
3360 {
3361 WARN(("VBoxCmdVbvaSubmitLock failed"));
3362 return STATUS_UNSUCCESSFUL;
3363 }
3364
3365 pDstHdr->u8OpCode = VBOXCMDVBVA_OPTYPE_COMPLEXCMD;
3366 pDstHdr->u8Flags = 0;
3367 pDstHdr->u.u8PrimaryID = 0;
3368
3369 pCurDstCmd = pDstHdr + 1;
3370 }
3371 else
3372 {
3373 pDstHdr = VBoxCmdVbvaSubmitLock(pDevExt, &pDevExt->CmdVbva, cbCmd);
3374 if (!pDstHdr)
3375 {
3376 WARN(("VBoxCmdVbvaSubmitLock failed"));
3377 return STATUS_UNSUCCESSFUL;
3378 }
3379 pCurDstCmd = pDstHdr;
3380 }
3381
3382 PHYSICAL_ADDRESS phAddr;
3383 phAddr.QuadPart = pSubmitCommand->DmaBufferPhysicalAddress.QuadPart + pSubmitCommand->DmaBufferSubmissionStartOffset;
3384 NTSTATUS Status = STATUS_SUCCESS;
3385 for (;;)
3386 {
3387 switch (pHdr->u8OpCode)
3388 {
3389 case VBOXCMDVBVA_OPTYPE_SYSMEMCMD:
3390 {
3391 VBOXCMDVBVA_SYSMEMCMD *pSysMem = (VBOXCMDVBVA_SYSMEMCMD*)pHdr;
3392 if (pSubmitCommand->DmaBufferPhysicalAddress.QuadPart & PAGE_OFFSET_MASK)
3393 {
3394 WARN(("command should be page aligned for now"));
3395 return STATUS_INVALID_PARAMETER;
3396 }
3397 pSysMem->phCmd = (VBOXCMDVBVAPHADDR)(pSubmitCommand->DmaBufferPhysicalAddress.QuadPart + pSubmitCommand->DmaBufferSubmissionStartOffset);
3398#ifdef DEBUG
3399 {
3400 uint32_t cbRealDmaCmd = (pSysMem->Hdr.u8Flags | (pSysMem->Hdr.u.u8PrimaryID << 8));
3401 Assert(cbRealDmaCmd >= cbDma);
3402 if (cbDma < cbRealDmaCmd)
3403 WARN(("parrtial sysmem transfer"));
3404 }
3405#endif
3406 break;
3407 }
3408 default:
3409 break;
3410 }
3411
3412 memcpy(pCurDstCmd, pHdr, cbCurCmd);
3413 pCurDstCmd->u2.complexCmdEl.u16CbCmdGuest = 0;
3414
3415 phAddr.QuadPart += cbCurDma;
3416 pHdr = (VBOXCMDVBVA_HDR*)(((uint8_t*)pHdr) + cbCurCmd);
3417 pCurDstCmd = (VBOXCMDVBVA_HDR*)(((uint8_t*)pCurDstCmd) + cbCurCmd);
3418 cbCmd -= cbCurCmd;
3419 cbDma -= cbCurDma;
3420 if (!cbCmd)
3421 {
3422 if (cbDma)
3423 {
3424 WARN(("invalid param"));
3425 Status = STATUS_INVALID_PARAMETER;
3426 }
3427 break;
3428 }
3429
3430 if (cbCmd < sizeof (VBOXCMDVBVA_HDR))
3431 {
3432 WARN(("invalid param"));
3433 Status = STATUS_INVALID_PARAMETER;
3434 break;
3435 }
3436
3437 cbCurCmd = pHdr->u2.complexCmdEl.u16CbCmdHost;
3438 cbCurDma = pHdr->u2.complexCmdEl.u16CbCmdGuest;
3439
3440 if (cbCmd < cbCurCmd)
3441 {
3442 WARN(("invalid param"));
3443 Status = STATUS_INVALID_PARAMETER;
3444 break;
3445 }
3446
3447 if (cbDma < cbCurDma)
3448 {
3449 WARN(("invalid param"));
3450 Status = STATUS_INVALID_PARAMETER;
3451 break;
3452 }
3453 }
3454
3455 uint32_t u32FenceId = pSubmitCommand->SubmissionFenceId;
3456
3457 if (!NT_SUCCESS(Status))
3458 {
3459 /* nop the entire command on failure */
3460 pDstHdr->u8OpCode = VBOXCMDVBVA_OPTYPE_NOPCMD;
3461 pDstHdr->u8Flags = 0;
3462 pDstHdr->u.i8Result = 0;
3463 u32FenceId = 0;
3464 }
3465
3466 VBoxCmdVbvaSubmitUnlock(pDevExt, &pDevExt->CmdVbva, pDstHdr, u32FenceId);
3467
3468 return Status;
3469}
3470#endif
3471
3472static NTSTATUS
3473APIENTRY
3474DxgkDdiSubmitCommandLegacy(
3475 CONST HANDLE hAdapter,
3476 CONST DXGKARG_SUBMITCOMMAND* pSubmitCommand)
3477{
3478 /* DxgkDdiSubmitCommand runs at dispatch, should not be pageable. */
3479 NTSTATUS Status = STATUS_SUCCESS;
3480
3481// LOGF(("ENTER, context(0x%x)", hAdapter));
3482
3483 vboxVDbgBreakFv();
3484
3485 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3486 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pSubmitCommand->hContext;
3487 PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR pPrivateDataBase = NULL;
3488 VBOXVDMACMD_TYPE enmCmd = VBOXVDMACMD_TYPE_UNDEFINED;
3489 Assert(pContext);
3490 Assert(pContext->pDevice);
3491 Assert(pContext->pDevice->pAdapter == pDevExt);
3492 Assert(!pSubmitCommand->DmaBufferSegmentId);
3493
3494 /* the DMA command buffer is located in system RAM, the host will need to pick it from there */
3495 //BufInfo.fFlags = 0; /* see VBOXVDMACBUF_FLAG_xx */
3496 if (pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset - pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
3497 {
3498 pPrivateDataBase = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)((uint8_t*)pSubmitCommand->pDmaBufferPrivateData + pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset);
3499 Assert(pPrivateDataBase);
3500 enmCmd = pPrivateDataBase->enmCmd;
3501 }
3502 else if (pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset == pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset)
3503 {
3504 enmCmd = VBOXVDMACMD_TYPE_DMA_NOP;
3505 }
3506 else
3507 {
3508 WARN(("DmaBufferPrivateDataSubmissionEndOffset (%d) - DmaBufferPrivateDataSubmissionStartOffset (%d) < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR) (%d)",
3509 pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset,
3510 pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset,
3511 sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
3512 return STATUS_INVALID_PARAMETER;
3513 }
3514
3515 switch (enmCmd)
3516 {
3517 case VBOXVDMACMD_TYPE_DMA_PRESENT_BLT:
3518 {
3519 VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR *pPrivateData = (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR*)pPrivateDataBase;
3520 PVBOXWDDM_DMA_PRIVATEDATA_BLT pBlt = (PVBOXWDDM_DMA_PRIVATEDATA_BLT)pPrivateData;
3521 PVBOXWDDM_ALLOCATION pDstAlloc = pBlt->Blt.DstAlloc.pAlloc;
3522 PVBOXWDDM_ALLOCATION pSrcAlloc = pBlt->Blt.SrcAlloc.pAlloc;
3523 BOOLEAN fSrcChanged;
3524 BOOLEAN fDstChanged;
3525
3526 fDstChanged = vboxWddmAddrSetVram(&pDstAlloc->AllocData.Addr, pBlt->Blt.DstAlloc.segmentIdAlloc, pBlt->Blt.DstAlloc.offAlloc);
3527 fSrcChanged = vboxWddmAddrSetVram(&pSrcAlloc->AllocData.Addr, pBlt->Blt.SrcAlloc.segmentIdAlloc, pBlt->Blt.SrcAlloc.offAlloc);
3528
3529 if (VBOXWDDM_IS_FB_ALLOCATION(pDevExt, pDstAlloc))
3530 {
3531 Assert(pDstAlloc->AllocData.SurfDesc.VidPnSourceId < VBOX_VIDEO_MAX_SCREENS);
3532#if 0
3533 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pDstAlloc->AllocData.SurfDesc.VidPnSourceId];
3534 if (VBOXWDDM_IS_FB_ALLOCATION(pDevExt, pDstAlloc) && pDstAlloc->AllocData.hostID)
3535 {
3536 if (pSource->AllocData.hostID != pDstAlloc->AllocData.hostID)
3537 {
3538 pSource->AllocData.hostID = pDstAlloc->AllocData.hostID;
3539 fDstChanged = TRUE;
3540 }
3541
3542 if (fDstChanged)
3543 pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_LOCATION;
3544 }
3545#endif
3546 }
3547
3548 Status = vboxVdmaProcessBltCmd(pDevExt, pContext, pBlt);
3549 if (!NT_SUCCESS(Status))
3550 WARN(("vboxVdmaProcessBltCmd failed, Status 0x%x", Status));
3551
3552 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId,
3553 NT_SUCCESS(Status) ? DXGK_INTERRUPT_DMA_COMPLETED : DXGK_INTERRUPT_DMA_FAULTED);
3554 break;
3555 }
3556 case VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP:
3557 {
3558 VBOXWDDM_DMA_PRIVATEDATA_FLIP *pFlip = (VBOXWDDM_DMA_PRIVATEDATA_FLIP*)pPrivateDataBase;
3559 PVBOXWDDM_ALLOCATION pAlloc = pFlip->Flip.Alloc.pAlloc;
3560 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pAlloc->AllocData.SurfDesc.VidPnSourceId];
3561 vboxWddmAddrSetVram(&pAlloc->AllocData.Addr, pFlip->Flip.Alloc.segmentIdAlloc, pFlip->Flip.Alloc.offAlloc);
3562 vboxWddmAssignPrimary(pSource, pAlloc, pAlloc->AllocData.SurfDesc.VidPnSourceId);
3563 vboxWddmGhDisplayCheckSetInfoFromSource(pDevExt, pSource);
3564
3565 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId,
3566 NT_SUCCESS(Status) ? DXGK_INTERRUPT_DMA_COMPLETED : DXGK_INTERRUPT_DMA_FAULTED);
3567 break;
3568 }
3569 case VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL:
3570 {
3571 PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL pCF = (PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL)pPrivateDataBase;
3572 vboxWddmAddrSetVram(&pCF->ClrFill.Alloc.pAlloc->AllocData.Addr, pCF->ClrFill.Alloc.segmentIdAlloc, pCF->ClrFill.Alloc.offAlloc);
3573
3574 Status = vboxVdmaProcessClrFillCmd(pDevExt, pContext, pCF);
3575 if (!NT_SUCCESS(Status))
3576 WARN(("vboxVdmaProcessClrFillCmd failed, Status 0x%x", Status));
3577
3578 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId,
3579 NT_SUCCESS(Status) ? DXGK_INTERRUPT_DMA_COMPLETED : DXGK_INTERRUPT_DMA_FAULTED);
3580 break;
3581 }
3582 case VBOXVDMACMD_TYPE_DMA_NOP:
3583 {
3584 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_COMPLETED);
3585 AssertNtStatusSuccess(Status);
3586 break;
3587 }
3588 default:
3589 {
3590 WARN(("unexpected command %d", enmCmd));
3591#if 0 //def VBOX_WITH_VDMA
3592 VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR *pPrivateData = (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR*)pPrivateDataBase;
3593 PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate (&pDevExt->u.primary.Vdma, 0);
3594 if (!pDr)
3595 {
3596 /** @todo try flushing.. */
3597 LOGREL(("vboxVdmaCBufDrCreate returned NULL"));
3598 return STATUS_INSUFFICIENT_RESOURCES;
3599 }
3600 // vboxVdmaCBufDrCreate zero initializes the pDr
3601 //pDr->fFlags = 0;
3602 pDr->cbBuf = pSubmitCommand->DmaBufferSubmissionEndOffset - pSubmitCommand->DmaBufferSubmissionStartOffset;
3603 pDr->u32FenceId = pSubmitCommand->SubmissionFenceId;
3604 pDr->rc = VERR_NOT_IMPLEMENTED;
3605 if (pPrivateData)
3606 pDr->u64GuestContext = (uint64_t)pPrivateData->pContext;
3607 // else // vboxVdmaCBufDrCreate zero initializes the pDr
3608 // pDr->u64GuestContext = NULL;
3609 pDr->Location.phBuf = pSubmitCommand->DmaBufferPhysicalAddress.QuadPart + pSubmitCommand->DmaBufferSubmissionStartOffset;
3610
3611 vboxVdmaCBufDrSubmit(pDevExt, &pDevExt->u.primary.Vdma, pDr);
3612#endif
3613 break;
3614 }
3615 }
3616// LOGF(("LEAVE, context(0x%x)", hAdapter));
3617
3618 return Status;
3619}
3620
3621#ifdef VBOX_WITH_CROGL
3622static NTSTATUS
3623APIENTRY
3624DxgkDdiPreemptCommandNew(
3625 CONST HANDLE hAdapter,
3626 CONST DXGKARG_PREEMPTCOMMAND* pPreemptCommand)
3627{
3628 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3629
3630 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3631
3632 vboxVDbgBreakF();
3633
3634 VBoxCmdVbvaPreempt(pDevExt, &pDevExt->CmdVbva, pPreemptCommand->PreemptionFenceId);
3635
3636 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3637
3638 return STATUS_SUCCESS;
3639}
3640#endif
3641
3642static NTSTATUS
3643APIENTRY
3644DxgkDdiPreemptCommandLegacy(
3645 CONST HANDLE hAdapter,
3646 CONST DXGKARG_PREEMPTCOMMAND* pPreemptCommand)
3647{
3648 RT_NOREF(hAdapter, pPreemptCommand);
3649 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3650
3651 AssertFailed();
3652 /** @todo fixme: implement */
3653
3654 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3655
3656 return STATUS_SUCCESS;
3657}
3658
3659#ifdef VBOX_WITH_CROGL
3660/*
3661 * DxgkDdiBuildPagingBuffer
3662 */
3663static NTSTATUS
3664APIENTRY
3665DxgkDdiBuildPagingBufferNew(
3666 CONST HANDLE hAdapter,
3667 DXGKARG_BUILDPAGINGBUFFER* pBuildPagingBuffer)
3668{
3669 RT_NOREF(hAdapter);
3670 /* DxgkDdiBuildPagingBuffer should be made pageable. */
3671 PAGED_CODE();
3672
3673 vboxVDbgBreakFv();
3674
3675 uint32_t cbBuffer = 0, cbPrivateData = 0;
3676
3677 LOGF(("ENTER context(0x%X), operation(0x%X) MultipassOffset(0x%X) DmaSizes(0x%X 0x%X)",
3678 hAdapter, pBuildPagingBuffer->Operation, pBuildPagingBuffer->MultipassOffset,
3679 pBuildPagingBuffer->DmaSize, pBuildPagingBuffer->DmaBufferPrivateDataSize));
3680
3681 /* Checking for bare minimum of DMA buffer sizes*/
3682 if (pBuildPagingBuffer->DmaBufferPrivateDataSize < sizeof (VBOXCMDVBVA_HDR))
3683 {
3684 WARN(("pBuildPagingBuffer->DmaBufferPrivateDataSize(%d) < sizeof (VBOXCMDVBVA_HDR)", pBuildPagingBuffer->DmaBufferPrivateDataSize));
3685 return STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
3686 }
3687
3688 if (pBuildPagingBuffer->DmaSize < VBOXWDDM_DUMMY_DMABUFFER_SIZE)
3689 {
3690 WARN(("pBuildPagingBuffer->DmaSize(%d) < VBOXWDDM_DUMMY_DMABUFFER_SIZE", pBuildPagingBuffer->DmaSize));
3691 return STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
3692 }
3693
3694 VBOXCMDVBVA_HDR *pHdr = (VBOXCMDVBVA_HDR*)pBuildPagingBuffer->pDmaBufferPrivateData;
3695
3696 switch (pBuildPagingBuffer->Operation)
3697 {
3698 case DXGK_OPERATION_TRANSFER:
3699 {
3700#if 0
3701 if (!pBuildPagingBuffer->Transfer.Flags.AllocationIsIdle)
3702 {
3703 WARN(("allocation is not idle"));
3704 return STATUS_GRAPHICS_ALLOCATION_BUSY;
3705 }
3706#endif
3707
3708 if (pBuildPagingBuffer->DmaBufferPrivateDataSize < sizeof (VBOXCMDVBVA_SYSMEMCMD))
3709 {
3710 WARN(("private data too small"));
3711 return STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
3712 }
3713
3714 Assert(!pBuildPagingBuffer->Transfer.MdlOffset);
3715
3716 if ((!pBuildPagingBuffer->Transfer.Source.SegmentId) == (!pBuildPagingBuffer->Transfer.Destination.SegmentId))
3717 {
3718 WARN(("we only support RAM <-> VRAM moves, Src Seg(%d), Dst Seg(%d)", pBuildPagingBuffer->Transfer.Source.SegmentId, pBuildPagingBuffer->Transfer.Destination.SegmentId));
3719 return STATUS_INVALID_PARAMETER;
3720 }
3721
3722 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pBuildPagingBuffer->Transfer.hAllocation;
3723 if (!pAlloc)
3724 {
3725 WARN(("allocation is null"));
3726 return STATUS_INVALID_PARAMETER;
3727 }
3728
3729 if (pAlloc->AllocData.hostID)
3730 {
3731 cbBuffer = VBOXWDDM_DUMMY_DMABUFFER_SIZE;
3732 cbPrivateData = sizeof (*pHdr);
3733
3734 pHdr->u8OpCode = VBOXCMDVBVA_OPTYPE_NOPCMD;
3735 pHdr->u8Flags = 0;
3736 pHdr->u.u8PrimaryID = 0;
3737 pHdr->u8State = VBOXCMDVBVA_STATE_SUBMITTED;
3738 break;
3739 }
3740
3741 if (pBuildPagingBuffer->DmaSize < sizeof (VBOXCMDVBVA_PAGING_TRANSFER))
3742 {
3743 WARN(("pBuildPagingBuffer->DmaSize(%d) < sizeof VBOXCMDVBVA_PAGING_TRANSFER (%d)", pBuildPagingBuffer->DmaSize , sizeof (VBOXCMDVBVA_PAGING_TRANSFER)));
3744 /** @todo can this actually happen? what status to return? */
3745 return STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
3746 }
3747
3748 VBOXCMDVBVA_PAGING_TRANSFER *pPaging = (VBOXCMDVBVA_PAGING_TRANSFER*)pBuildPagingBuffer->pDmaBuffer;
3749 pPaging->Hdr.u8OpCode = VBOXCMDVBVA_OPTYPE_PAGING_TRANSFER;
3750 /* sanity */
3751 pPaging->Hdr.u8Flags = 0;
3752 pPaging->Hdr.u8State = VBOXCMDVBVA_STATE_SUBMITTED;
3753
3754 PMDL pMdl;
3755 uint32_t offVRAM;
3756 BOOLEAN fIn;
3757 UINT SegmentId;
3758
3759 if (pBuildPagingBuffer->Transfer.Source.SegmentId)
3760 {
3761 SegmentId = pBuildPagingBuffer->Transfer.Source.SegmentId;
3762 Assert(!pBuildPagingBuffer->Transfer.Destination.SegmentId);
3763 Assert(!pBuildPagingBuffer->Transfer.Source.SegmentAddress.HighPart);
3764 offVRAM = pBuildPagingBuffer->Transfer.Source.SegmentAddress.LowPart;
3765 pMdl = pBuildPagingBuffer->Transfer.Destination.pMdl;
3766 fIn = FALSE;
3767 }
3768 else
3769 {
3770 SegmentId = pBuildPagingBuffer->Transfer.Destination.SegmentId;
3771 Assert(pBuildPagingBuffer->Transfer.Destination.SegmentId);
3772 Assert(!pBuildPagingBuffer->Transfer.Source.SegmentId);
3773 Assert(!pBuildPagingBuffer->Transfer.Destination.SegmentAddress.HighPart);
3774 offVRAM = pBuildPagingBuffer->Transfer.Destination.SegmentAddress.LowPart;
3775 pMdl = pBuildPagingBuffer->Transfer.Source.pMdl;
3776 fIn = TRUE;
3777 }
3778
3779 if (SegmentId != 1)
3780 {
3781 WARN(("SegmentId"));
3782 cbBuffer = VBOXWDDM_DUMMY_DMABUFFER_SIZE;
3783 break;
3784 }
3785
3786 Assert(!(pBuildPagingBuffer->Transfer.TransferSize & PAGE_OFFSET_MASK));
3787 Assert(!(offVRAM & PAGE_OFFSET_MASK));
3788 uint32_t cPages = (uint32_t)(pBuildPagingBuffer->Transfer.TransferSize >> PAGE_SHIFT);
3789 Assert(cPages > pBuildPagingBuffer->MultipassOffset);
3790 cPages -= pBuildPagingBuffer->MultipassOffset;
3791 uint32_t iFirstPage = pBuildPagingBuffer->MultipassOffset;
3792 uint32_t cPagesWritten;
3793 offVRAM += pBuildPagingBuffer->Transfer.TransferOffset + (pBuildPagingBuffer->MultipassOffset << PAGE_SHIFT);
3794
3795 pPaging->Data.Alloc.u.offVRAM = offVRAM;
3796 if (fIn)
3797 pPaging->Hdr.u8Flags |= VBOXCMDVBVA_OPF_PAGING_TRANSFER_IN;
3798 cbBuffer = VBoxCVDdiPTransferVRamSysBuildEls(pPaging, pMdl, iFirstPage, cPages, pBuildPagingBuffer->DmaSize, &cPagesWritten);
3799 if (cPagesWritten != cPages)
3800 pBuildPagingBuffer->MultipassOffset += cPagesWritten;
3801 else
3802 pBuildPagingBuffer->MultipassOffset = 0;
3803
3804 VBOXCMDVBVA_SYSMEMCMD *pSysMemCmd = (VBOXCMDVBVA_SYSMEMCMD*)pBuildPagingBuffer->pDmaBufferPrivateData;
3805
3806 cbPrivateData = sizeof (*pSysMemCmd);
3807
3808 pSysMemCmd->Hdr.u8OpCode = VBOXCMDVBVA_OPTYPE_SYSMEMCMD;
3809 pSysMemCmd->Hdr.u8Flags = cbBuffer & 0xff;
3810 pSysMemCmd->Hdr.u.u8PrimaryID = (cbBuffer >> 8) & 0xff;
3811 pSysMemCmd->Hdr.u8State = VBOXCMDVBVA_STATE_SUBMITTED;
3812 pSysMemCmd->phCmd = 0;
3813
3814 break;
3815 }
3816 case DXGK_OPERATION_FILL:
3817 {
3818 Assert(pBuildPagingBuffer->Fill.FillPattern == 0);
3819 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pBuildPagingBuffer->Fill.hAllocation;
3820 if (!pAlloc)
3821 {
3822 WARN(("allocation is null"));
3823 return STATUS_INVALID_PARAMETER;
3824 }
3825
3826 if (pAlloc->AllocData.hostID || pBuildPagingBuffer->Fill.Destination.SegmentId != 1)
3827 {
3828 if (!pAlloc->AllocData.hostID)
3829 {
3830 WARN(("unexpected segment id"));
3831 }
3832
3833 cbBuffer = VBOXWDDM_DUMMY_DMABUFFER_SIZE;
3834 cbPrivateData = sizeof (*pHdr);
3835
3836 pHdr->u8OpCode = VBOXCMDVBVA_OPTYPE_NOPCMD;
3837 pHdr->u8Flags = 0;
3838 pHdr->u.u8PrimaryID = 0;
3839 pHdr->u8State = VBOXCMDVBVA_STATE_SUBMITTED;
3840 break;
3841 }
3842
3843 if (pBuildPagingBuffer->DmaBufferPrivateDataSize < sizeof (VBOXCMDVBVA_PAGING_FILL))
3844 {
3845 WARN(("private data too small"));
3846 return STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
3847 }
3848
3849 VBOXCMDVBVA_PAGING_FILL *pFill = (VBOXCMDVBVA_PAGING_FILL*)pBuildPagingBuffer->pDmaBufferPrivateData;
3850 pFill->Hdr.u8OpCode = VBOXCMDVBVA_OPTYPE_PAGING_FILL;
3851 pFill->Hdr.u8Flags = 0;
3852 pFill->Hdr.u.u8PrimaryID = 0;
3853 pFill->Hdr.u8State = VBOXCMDVBVA_STATE_SUBMITTED;
3854 pFill->u32CbFill = (uint32_t)pBuildPagingBuffer->Fill.FillSize;
3855 pFill->u32Pattern = pBuildPagingBuffer->Fill.FillPattern;
3856 Assert(!pBuildPagingBuffer->Fill.Destination.SegmentAddress.HighPart);
3857 pFill->offVRAM = pBuildPagingBuffer->Fill.Destination.SegmentAddress.LowPart;
3858
3859 cbBuffer = VBOXWDDM_DUMMY_DMABUFFER_SIZE;
3860 cbPrivateData = sizeof (*pFill);
3861
3862 break;
3863 }
3864 case DXGK_OPERATION_DISCARD_CONTENT:
3865 {
3866 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pBuildPagingBuffer->DiscardContent.hAllocation;
3867 if (!pAlloc)
3868 {
3869 WARN(("allocation is null"));
3870 return STATUS_INVALID_PARAMETER;
3871 }
3872// WARN(("Do we need to do anything here?"));
3873 break;
3874 }
3875 default:
3876 {
3877 WARN(("unsupported op (%d)", pBuildPagingBuffer->Operation));
3878 break;
3879 }
3880 }
3881
3882 Assert(cbPrivateData >= sizeof (VBOXCMDVBVA_HDR) || pBuildPagingBuffer->Operation == DXGK_OPERATION_DISCARD_CONTENT);
3883 Assert(pBuildPagingBuffer->Operation == DXGK_OPERATION_DISCARD_CONTENT || cbBuffer);
3884 Assert(cbBuffer <= pBuildPagingBuffer->DmaSize);
3885 Assert(cbBuffer == 0 || cbBuffer >= sizeof (VBOXCMDVBVA_PAGING_TRANSFER) || cbBuffer == VBOXWDDM_DUMMY_DMABUFFER_SIZE);
3886 AssertCompile(VBOXWDDM_DUMMY_DMABUFFER_SIZE < 8);
3887
3888 pHdr->u2.complexCmdEl.u16CbCmdHost = cbPrivateData;
3889 pHdr->u2.complexCmdEl.u16CbCmdGuest = cbBuffer;
3890
3891 pBuildPagingBuffer->pDmaBuffer = ((uint8_t*)pBuildPagingBuffer->pDmaBuffer) + cbBuffer;
3892 pBuildPagingBuffer->pDmaBufferPrivateData = ((uint8_t*)pBuildPagingBuffer->pDmaBufferPrivateData) + cbPrivateData;
3893
3894 LOGF(("LEAVE context(0x%X), MultipassOffset(0x%X) cbBuffer(0x%X) cbPrivateData(0x%X)",
3895 hAdapter, pBuildPagingBuffer->MultipassOffset, cbBuffer, cbPrivateData));
3896
3897 if (pBuildPagingBuffer->MultipassOffset)
3898 return STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
3899 return STATUS_SUCCESS;
3900}
3901#endif
3902
3903static NTSTATUS
3904APIENTRY
3905DxgkDdiBuildPagingBufferLegacy(
3906 CONST HANDLE hAdapter,
3907 DXGKARG_BUILDPAGINGBUFFER* pBuildPagingBuffer)
3908{
3909 /* DxgkDdiBuildPagingBuffer should be made pageable. */
3910 PAGED_CODE();
3911
3912 vboxVDbgBreakFv();
3913
3914 NTSTATUS Status = STATUS_SUCCESS;
3915 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3916
3917 LOGF(("ENTER, context(0x%x)", hAdapter));
3918
3919 uint32_t cbCmdDma = 0;
3920
3921 /** @todo */
3922 switch (pBuildPagingBuffer->Operation)
3923 {
3924 case DXGK_OPERATION_TRANSFER:
3925 {
3926 cbCmdDma = VBOXWDDM_DUMMY_DMABUFFER_SIZE;
3927#ifdef VBOX_WITH_VDMA
3928#if 0
3929 if ((!pBuildPagingBuffer->Transfer.Source.SegmentId) != (!pBuildPagingBuffer->Transfer.Destination.SegmentId))
3930 {
3931 PVBOXVDMACMD pCmd = (PVBOXVDMACMD)pBuildPagingBuffer->pDmaBuffer;
3932 pCmd->enmType = VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER_VRAMSYS;
3933 pCmd->u32CmdSpecific = 0;
3934 PVBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS pBody = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS);
3935 PMDL pMdl;
3936 uint32_t cPages = (pBuildPagingBuffer->Transfer.TransferSize + 0xfff) >> 12;
3937 cPages -= pBuildPagingBuffer->MultipassOffset;
3938 uint32_t iFirstPage = pBuildPagingBuffer->Transfer.MdlOffset + pBuildPagingBuffer->MultipassOffset;
3939 uint32_t cPagesRemaining;
3940 if (pBuildPagingBuffer->Transfer.Source.SegmentId)
3941 {
3942 uint64_t off = pBuildPagingBuffer->Transfer.Source.SegmentAddress.QuadPart;
3943 off += pBuildPagingBuffer->Transfer.TransferOffset + (pBuildPagingBuffer->MultipassOffset << PAGE_SHIFT);
3944 pBody->offVramBuf = off;
3945 pMdl = pBuildPagingBuffer->Transfer.Source.pMdl;
3946 pBody->fFlags = 0;//VBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS_SYS2VRAM
3947 }
3948 else
3949 {
3950 uint64_t off = pBuildPagingBuffer->Transfer.Destination.SegmentAddress.QuadPart;
3951 off += pBuildPagingBuffer->Transfer.TransferOffset + (pBuildPagingBuffer->MultipassOffset << PAGE_SHIFT);
3952 pBody->offVramBuf = off;
3953 pMdl = pBuildPagingBuffer->Transfer.Destination.pMdl;
3954 pBody->fFlags = VBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS_SYS2VRAM;
3955 }
3956
3957 uint32_t sbBufferUsed = vboxWddmBpbTransferVRamSysBuildEls(pBody, pMdl, iFirstPage, cPages, pBuildPagingBuffer->DmaSize, &cPagesRemaining);
3958 Assert(sbBufferUsed);
3959 }
3960
3961#else
3962 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pBuildPagingBuffer->Transfer.hAllocation;
3963 Assert(pAlloc);
3964 if (pAlloc
3965 && !pAlloc->fRcFlags.Overlay /* overlay surfaces actually contain a valid data */
3966 && pAlloc->enmType != VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE /* shadow primary - also */
3967 && pAlloc->enmType != VBOXWDDM_ALLOC_TYPE_UMD_HGSMI_BUFFER /* hgsmi buffer - also */
3968 )
3969 {
3970 /* we do not care about the others for now */
3971 Status = STATUS_SUCCESS;
3972 break;
3973 }
3974 UINT cbCmd = VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_BPB_TRANSFER);
3975 VBOXVDMACBUF_DR RT_UNTRUSTED_VOLATILE_HOST *pDr = vboxVdmaCBufDrCreate(&pDevExt->u.primary.Vdma, cbCmd);
3976 Assert(pDr);
3977 if (pDr)
3978 {
3979 SIZE_T cbTransfered = 0;
3980 SIZE_T cbTransferSize = pBuildPagingBuffer->Transfer.TransferSize;
3981 VBOXVDMACMD RT_UNTRUSTED_VOLATILE_HOST *pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
3982 do
3983 {
3984 // vboxVdmaCBufDrCreate zero initializes the pDr
3985 pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR;
3986 pDr->cbBuf = cbCmd;
3987 pDr->rc = VERR_NOT_IMPLEMENTED;
3988
3989 pHdr->enmType = VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER;
3990 pHdr->u32CmdSpecific = 0;
3991 VBOXVDMACMD_DMA_BPB_TRANSFER RT_UNTRUSTED_VOLATILE_HOST *pBody
3992 = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_DMA_BPB_TRANSFER);
3993// pBody->cbTransferSize = (uint32_t)pBuildPagingBuffer->Transfer.TransferSize;
3994 pBody->fFlags = 0;
3995 SIZE_T cSrcPages = (cbTransferSize + 0xfff ) >> 12;
3996 SIZE_T cDstPages = cSrcPages;
3997
3998 if (pBuildPagingBuffer->Transfer.Source.SegmentId)
3999 {
4000 uint64_t off = pBuildPagingBuffer->Transfer.Source.SegmentAddress.QuadPart;
4001 off += pBuildPagingBuffer->Transfer.TransferOffset + cbTransfered;
4002 pBody->Src.offVramBuf = off;
4003 pBody->fFlags |= VBOXVDMACMD_DMA_BPB_TRANSFER_F_SRC_VRAMOFFSET;
4004 }
4005 else
4006 {
4007 UINT index = pBuildPagingBuffer->Transfer.MdlOffset + (UINT)(cbTransfered>>12);
4008 pBody->Src.phBuf = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Source.pMdl)[index] << PAGE_SHIFT;
4009 PFN_NUMBER num = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Source.pMdl)[index];
4010 cSrcPages = 1;
4011 for (UINT i = 1; i < ((cbTransferSize - cbTransfered + 0xfff) >> 12); ++i)
4012 {
4013 PFN_NUMBER cur = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Source.pMdl)[index+i];
4014 if(cur != ++num)
4015 {
4016 cSrcPages+= i-1;
4017 break;
4018 }
4019 }
4020 }
4021
4022 if (pBuildPagingBuffer->Transfer.Destination.SegmentId)
4023 {
4024 uint64_t off = pBuildPagingBuffer->Transfer.Destination.SegmentAddress.QuadPart;
4025 off += pBuildPagingBuffer->Transfer.TransferOffset;
4026 pBody->Dst.offVramBuf = off + cbTransfered;
4027 pBody->fFlags |= VBOXVDMACMD_DMA_BPB_TRANSFER_F_DST_VRAMOFFSET;
4028 }
4029 else
4030 {
4031 UINT index = pBuildPagingBuffer->Transfer.MdlOffset + (UINT)(cbTransfered>>12);
4032 pBody->Dst.phBuf = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Destination.pMdl)[index] << PAGE_SHIFT;
4033 PFN_NUMBER num = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Destination.pMdl)[index];
4034 cDstPages = 1;
4035 for (UINT i = 1; i < ((cbTransferSize - cbTransfered + 0xfff) >> 12); ++i)
4036 {
4037 PFN_NUMBER cur = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Destination.pMdl)[index+i];
4038 if(cur != ++num)
4039 {
4040 cDstPages+= i-1;
4041 break;
4042 }
4043 }
4044 }
4045
4046 SIZE_T cbCurTransfer;
4047 cbCurTransfer = RT_MIN(cbTransferSize - cbTransfered, (SIZE_T)cSrcPages << PAGE_SHIFT);
4048 cbCurTransfer = RT_MIN(cbCurTransfer, (SIZE_T)cDstPages << PAGE_SHIFT);
4049
4050 pBody->cbTransferSize = (UINT)cbCurTransfer;
4051 Assert(!(cbCurTransfer & 0xfff));
4052
4053 int rc = vboxVdmaCBufDrSubmitSynch(pDevExt, &pDevExt->u.primary.Vdma, pDr);
4054 AssertRC(rc);
4055 if (RT_SUCCESS(rc))
4056 {
4057 Status = STATUS_SUCCESS;
4058 cbTransfered += cbCurTransfer;
4059 }
4060 else
4061 Status = STATUS_UNSUCCESSFUL;
4062 } while (cbTransfered < cbTransferSize);
4063 Assert(cbTransfered == cbTransferSize);
4064 vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
4065 }
4066 else
4067 {
4068 /** @todo try flushing.. */
4069 LOGREL(("vboxVdmaCBufDrCreate returned NULL"));
4070 Status = STATUS_INSUFFICIENT_RESOURCES;
4071 }
4072#endif
4073#endif /* #ifdef VBOX_WITH_VDMA */
4074 break;
4075 }
4076 case DXGK_OPERATION_FILL:
4077 {
4078 cbCmdDma = VBOXWDDM_DUMMY_DMABUFFER_SIZE;
4079 Assert(pBuildPagingBuffer->Fill.FillPattern == 0);
4080 /*PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pBuildPagingBuffer->Fill.hAllocation; - unused. Incomplete code? */
4081// pBuildPagingBuffer->pDmaBuffer = (uint8_t*)pBuildPagingBuffer->pDmaBuffer + VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_BPB_FILL);
4082 break;
4083 }
4084 case DXGK_OPERATION_DISCARD_CONTENT:
4085 {
4086// AssertBreakpoint();
4087 break;
4088 }
4089 default:
4090 {
4091 WARN(("unsupported op (%d)", pBuildPagingBuffer->Operation));
4092 break;
4093 }
4094 }
4095
4096 if (cbCmdDma)
4097 {
4098 pBuildPagingBuffer->pDmaBuffer = ((uint8_t*)pBuildPagingBuffer->pDmaBuffer) + cbCmdDma;
4099 }
4100
4101 LOGF(("LEAVE, context(0x%x)", hAdapter));
4102
4103 return Status;
4104
4105}
4106
4107NTSTATUS
4108APIENTRY
4109DxgkDdiSetPalette(
4110 CONST HANDLE hAdapter,
4111 CONST DXGKARG_SETPALETTE* pSetPalette
4112 )
4113{
4114 RT_NOREF(hAdapter, pSetPalette);
4115 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
4116
4117 AssertBreakpoint();
4118 /** @todo fixme: implement */
4119
4120 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
4121
4122 return STATUS_SUCCESS;
4123}
4124
4125BOOL vboxWddmPointerCopyColorData(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVIDEO_POINTER_ATTRIBUTES pPointerAttributes)
4126{
4127 ULONG srcMaskW, srcMaskH;
4128 ULONG dstBytesPerLine;
4129 ULONG x, y;
4130 BYTE *pSrc, *pDst, bit;
4131
4132 srcMaskW = pSetPointerShape->Width;
4133 srcMaskH = pSetPointerShape->Height;
4134
4135 /* truncate masks if we exceed supported size */
4136 pPointerAttributes->Width = min(srcMaskW, VBOXWDDM_C_POINTER_MAX_WIDTH);
4137 pPointerAttributes->Height = min(srcMaskH, VBOXWDDM_C_POINTER_MAX_HEIGHT);
4138 pPointerAttributes->WidthInBytes = pPointerAttributes->Width * 4;
4139
4140 /* cnstruct and mask from alpha color channel */
4141 pSrc = (PBYTE)pSetPointerShape->pPixels;
4142 pDst = pPointerAttributes->Pixels;
4143 dstBytesPerLine = (pPointerAttributes->Width+7)/8;
4144
4145 /* sanity check */
4146 uint32_t cbData = RT_ALIGN_T(dstBytesPerLine*pPointerAttributes->Height, 4, ULONG)+
4147 pPointerAttributes->Height*pPointerAttributes->WidthInBytes;
4148 uint32_t cbPointerAttributes = RT_UOFFSETOF_DYN(VIDEO_POINTER_ATTRIBUTES, Pixels[cbData]);
4149 Assert(VBOXWDDM_POINTER_ATTRIBUTES_SIZE >= cbPointerAttributes);
4150 if (VBOXWDDM_POINTER_ATTRIBUTES_SIZE < cbPointerAttributes)
4151 {
4152 LOGREL(("VBOXWDDM_POINTER_ATTRIBUTES_SIZE(%d) < cbPointerAttributes(%d)", VBOXWDDM_POINTER_ATTRIBUTES_SIZE, cbPointerAttributes));
4153 return FALSE;
4154 }
4155
4156 memset(pDst, 0xFF, dstBytesPerLine*pPointerAttributes->Height);
4157 for (y=0; y<pPointerAttributes->Height; ++y)
4158 {
4159 for (x=0, bit=7; x<pPointerAttributes->Width; ++x, --bit)
4160 {
4161 if (0xFF==bit) bit=7;
4162
4163 if (pSrc[y*pSetPointerShape->Pitch + x*4 + 3] > 0x7F)
4164 {
4165 pDst[y*dstBytesPerLine + x/8] &= ~RT_BIT(bit);
4166 }
4167 }
4168 }
4169
4170 /* copy 32bpp to XOR DIB, it start in pPointerAttributes->Pixels should be 4bytes aligned */
4171 pSrc = (BYTE*)pSetPointerShape->pPixels;
4172 pDst = pPointerAttributes->Pixels + RT_ALIGN_T(dstBytesPerLine*pPointerAttributes->Height, 4, ULONG);
4173 dstBytesPerLine = pPointerAttributes->Width * 4;
4174
4175 for (y=0; y<pPointerAttributes->Height; ++y)
4176 {
4177 memcpy(pDst+y*dstBytesPerLine, pSrc+y*pSetPointerShape->Pitch, dstBytesPerLine);
4178 }
4179
4180 return TRUE;
4181}
4182
4183BOOL vboxWddmPointerCopyMonoData(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVIDEO_POINTER_ATTRIBUTES pPointerAttributes)
4184{
4185 ULONG srcMaskW, srcMaskH;
4186 ULONG dstBytesPerLine;
4187 ULONG x, y;
4188 BYTE *pSrc, *pDst, bit;
4189
4190 srcMaskW = pSetPointerShape->Width;
4191 srcMaskH = pSetPointerShape->Height;
4192
4193 /* truncate masks if we exceed supported size */
4194 pPointerAttributes->Width = min(srcMaskW, VBOXWDDM_C_POINTER_MAX_WIDTH);
4195 pPointerAttributes->Height = min(srcMaskH, VBOXWDDM_C_POINTER_MAX_HEIGHT);
4196 pPointerAttributes->WidthInBytes = pPointerAttributes->Width * 4;
4197
4198 /* copy AND mask */
4199 pSrc = (PBYTE)pSetPointerShape->pPixels;
4200 pDst = pPointerAttributes->Pixels;
4201 dstBytesPerLine = (pPointerAttributes->Width+7)/8;
4202
4203 for (y=0; y<pPointerAttributes->Height; ++y)
4204 {
4205 memcpy(pDst+y*dstBytesPerLine, pSrc+y*pSetPointerShape->Pitch, dstBytesPerLine);
4206 }
4207
4208 /* convert XOR mask to RGB0 DIB, it start in pPointerAttributes->Pixels should be 4bytes aligned */
4209 pSrc = (BYTE*)pSetPointerShape->pPixels + srcMaskH*pSetPointerShape->Pitch;
4210 pDst = pPointerAttributes->Pixels + RT_ALIGN_T(dstBytesPerLine*pPointerAttributes->Height, 4, ULONG);
4211 dstBytesPerLine = pPointerAttributes->Width * 4;
4212
4213 for (y=0; y<pPointerAttributes->Height; ++y)
4214 {
4215 for (x=0, bit=7; x<pPointerAttributes->Width; ++x, --bit)
4216 {
4217 if (0xFF==bit) bit=7;
4218
4219 *(ULONG*)&pDst[y*dstBytesPerLine+x*4] = (pSrc[y*pSetPointerShape->Pitch+x/8] & RT_BIT(bit)) ? 0x00FFFFFF : 0;
4220 }
4221 }
4222
4223 return TRUE;
4224}
4225
4226static BOOLEAN vboxVddmPointerShapeToAttributes(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVBOXWDDM_POINTER_INFO pPointerInfo)
4227{
4228 PVIDEO_POINTER_ATTRIBUTES pPointerAttributes = &pPointerInfo->Attributes.data;
4229 /* pPointerAttributes maintains the visibility state, clear all except visibility */
4230 pPointerAttributes->Enable &= VBOX_MOUSE_POINTER_VISIBLE;
4231
4232 Assert(pSetPointerShape->Flags.Value == 1 || pSetPointerShape->Flags.Value == 2);
4233 if (pSetPointerShape->Flags.Color)
4234 {
4235 if (vboxWddmPointerCopyColorData(pSetPointerShape, pPointerAttributes))
4236 {
4237 pPointerAttributes->Flags = VIDEO_MODE_COLOR_POINTER;
4238 pPointerAttributes->Enable |= VBOX_MOUSE_POINTER_ALPHA;
4239 }
4240 else
4241 {
4242 LOGREL(("vboxWddmPointerCopyColorData failed"));
4243 AssertBreakpoint();
4244 return FALSE;
4245 }
4246
4247 }
4248 else if (pSetPointerShape->Flags.Monochrome)
4249 {
4250 if (vboxWddmPointerCopyMonoData(pSetPointerShape, pPointerAttributes))
4251 {
4252 pPointerAttributes->Flags = VIDEO_MODE_MONO_POINTER;
4253 }
4254 else
4255 {
4256 LOGREL(("vboxWddmPointerCopyMonoData failed"));
4257 AssertBreakpoint();
4258 return FALSE;
4259 }
4260 }
4261 else
4262 {
4263 LOGREL(("unsupported pointer type Flags.Value(0x%x)", pSetPointerShape->Flags.Value));
4264 AssertBreakpoint();
4265 return FALSE;
4266 }
4267
4268 pPointerAttributes->Enable |= VBOX_MOUSE_POINTER_SHAPE;
4269
4270 /*
4271 * The hot spot coordinates and alpha flag will be encoded in the pPointerAttributes::Enable field.
4272 * High word will contain hot spot info and low word - flags.
4273 */
4274 pPointerAttributes->Enable |= (pSetPointerShape->YHot & 0xFF) << 24;
4275 pPointerAttributes->Enable |= (pSetPointerShape->XHot & 0xFF) << 16;
4276
4277 return TRUE;
4278}
4279
4280static void vboxWddmHostPointerEnable(PVBOXMP_DEVEXT pDevExt, BOOLEAN fEnable)
4281{
4282 VIDEO_POINTER_ATTRIBUTES PointerAttributes;
4283 RT_ZERO(PointerAttributes);
4284 if (fEnable)
4285 {
4286 PointerAttributes.Enable = VBOX_MOUSE_POINTER_VISIBLE;
4287 }
4288 VBoxMPCmnUpdatePointerShape(VBoxCommonFromDeviceExt(pDevExt), &PointerAttributes, sizeof(PointerAttributes));
4289}
4290
4291NTSTATUS
4292APIENTRY
4293DxgkDdiSetPointerPosition(
4294 CONST HANDLE hAdapter,
4295 CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition)
4296{
4297// LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
4298
4299 vboxVDbgBreakFv();
4300
4301 /* mouse integration is ON */
4302 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
4303 PVBOXWDDM_POINTER_INFO pPointerInfo = &pDevExt->aSources[pSetPointerPosition->VidPnSourceId].PointerInfo;
4304 PVBOXWDDM_GLOBAL_POINTER_INFO pGlobalPointerInfo = &pDevExt->PointerInfo;
4305 PVIDEO_POINTER_ATTRIBUTES pPointerAttributes = &pPointerInfo->Attributes.data;
4306 BOOLEAN fScreenVisState = !!(pPointerAttributes->Enable & VBOX_MOUSE_POINTER_VISIBLE);
4307 BOOLEAN fVisStateChanged = FALSE;
4308 BOOLEAN fScreenChanged = pGlobalPointerInfo->iLastReportedScreen != pSetPointerPosition->VidPnSourceId;
4309
4310 if (pSetPointerPosition->Flags.Visible)
4311 {
4312 pPointerAttributes->Enable |= VBOX_MOUSE_POINTER_VISIBLE;
4313 if (!fScreenVisState)
4314 {
4315 fVisStateChanged = !!pGlobalPointerInfo->cVisible;
4316 ++pGlobalPointerInfo->cVisible;
4317 }
4318 }
4319 else
4320 {
4321 pPointerAttributes->Enable &= ~VBOX_MOUSE_POINTER_VISIBLE;
4322 if (fScreenVisState)
4323 {
4324 --pGlobalPointerInfo->cVisible;
4325 fVisStateChanged = !!pGlobalPointerInfo->cVisible;
4326 }
4327 }
4328
4329 pGlobalPointerInfo->iLastReportedScreen = pSetPointerPosition->VidPnSourceId;
4330
4331 if ((fVisStateChanged || fScreenChanged) && VBoxQueryHostWantsAbsolute())
4332 {
4333 if (fScreenChanged)
4334 {
4335 BOOLEAN bResult = VBoxMPCmnUpdatePointerShape(VBoxCommonFromDeviceExt(pDevExt), &pPointerInfo->Attributes.data, VBOXWDDM_POINTER_ATTRIBUTES_SIZE);
4336 if (!bResult)
4337 {
4338 vboxWddmHostPointerEnable(pDevExt, FALSE);
4339 }
4340 }
4341 else
4342 {
4343 // tell the host to use the guest's pointer
4344 vboxWddmHostPointerEnable(pDevExt, pSetPointerPosition->Flags.Visible);
4345 }
4346 }
4347
4348// LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
4349
4350 return STATUS_SUCCESS;
4351}
4352
4353NTSTATUS
4354APIENTRY
4355DxgkDdiSetPointerShape(
4356 CONST HANDLE hAdapter,
4357 CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape)
4358{
4359// LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
4360
4361 vboxVDbgBreakFv();
4362
4363 NTSTATUS Status = STATUS_NOT_SUPPORTED;
4364
4365 if (VBoxQueryHostWantsAbsolute())
4366 {
4367 /* mouse integration is ON */
4368 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
4369 PVBOXWDDM_POINTER_INFO pPointerInfo = &pDevExt->aSources[pSetPointerShape->VidPnSourceId].PointerInfo;
4370 /** @todo to avoid extra data copy and extra heap allocation,
4371 * need to maintain the pre-allocated HGSMI buffer and convert the data directly to it */
4372 if (vboxVddmPointerShapeToAttributes(pSetPointerShape, pPointerInfo))
4373 {
4374 pDevExt->PointerInfo.iLastReportedScreen = pSetPointerShape->VidPnSourceId;
4375 if (VBoxMPCmnUpdatePointerShape(VBoxCommonFromDeviceExt(pDevExt), &pPointerInfo->Attributes.data, VBOXWDDM_POINTER_ATTRIBUTES_SIZE))
4376 Status = STATUS_SUCCESS;
4377 else
4378 {
4379 // tell the host to use the guest's pointer
4380 vboxWddmHostPointerEnable(pDevExt, FALSE);
4381 }
4382 }
4383 }
4384
4385// LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
4386
4387 return Status;
4388}
4389
4390NTSTATUS
4391APIENTRY CALLBACK
4392DxgkDdiResetFromTimeout(
4393 CONST HANDLE hAdapter)
4394{
4395 RT_NOREF(hAdapter);
4396 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
4397
4398 AssertBreakpoint();
4399 /** @todo fixme: implement */
4400
4401 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
4402
4403 return STATUS_SUCCESS;
4404}
4405
4406
4407/* the lpRgnData->Buffer comes to us as RECT
4408 * to avoid extra memcpy we cast it to PRTRECT assuming
4409 * they are identical */
4410AssertCompile(sizeof(RECT) == sizeof(RTRECT));
4411AssertCompile(RT_OFFSETOF(RECT, left) == RT_OFFSETOF(RTRECT, xLeft));
4412AssertCompile(RT_OFFSETOF(RECT, bottom) == RT_OFFSETOF(RTRECT, yBottom));
4413AssertCompile(RT_OFFSETOF(RECT, right) == RT_OFFSETOF(RTRECT, xRight));
4414AssertCompile(RT_OFFSETOF(RECT, top) == RT_OFFSETOF(RTRECT, yTop));
4415
4416NTSTATUS
4417APIENTRY
4418DxgkDdiEscape(
4419 CONST HANDLE hAdapter,
4420 CONST DXGKARG_ESCAPE* pEscape)
4421{
4422 PAGED_CODE();
4423
4424// LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
4425
4426 NTSTATUS Status = STATUS_NOT_SUPPORTED;
4427 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
4428 Assert(pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE));
4429 if (pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE))
4430 {
4431 PVBOXDISPIFESCAPE pEscapeHdr = (PVBOXDISPIFESCAPE)pEscape->pPrivateDriverData;
4432 switch (pEscapeHdr->escapeCode)
4433 {
4434#ifdef VBOX_WITH_CRHGSMI
4435 case VBOXESC_UHGSMI_SUBMIT:
4436 {
4437 if (pDevExt->fCmdVbvaEnabled)
4438 {
4439 WARN(("VBOXESC_UHGSMI_SUBMIT not supported for CmdVbva mode"));
4440 Status = STATUS_INVALID_PARAMETER;
4441 break;
4442 }
4443 /* submit VBOXUHGSMI command */
4444 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
4445 PVBOXDISPIFESCAPE_UHGSMI_SUBMIT pSubmit = (PVBOXDISPIFESCAPE_UHGSMI_SUBMIT)pEscapeHdr;
4446 Assert(pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_UHGSMI_SUBMIT)
4447 && pEscape->PrivateDriverDataSize == RT_UOFFSETOF_DYN(VBOXDISPIFESCAPE_UHGSMI_SUBMIT, aBuffers[pEscapeHdr->u32CmdSpecific]));
4448 if ( pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD)
4449 && pEscape->PrivateDriverDataSize == RT_UOFFSETOF_DYN(VBOXDISPIFESCAPE_UHGSMI_SUBMIT, aBuffers[pEscapeHdr->u32CmdSpecific]))
4450 {
4451 Status = vboxVideoAMgrCtxAllocSubmit(pDevExt, &pContext->AllocContext, pEscapeHdr->u32CmdSpecific, pSubmit->aBuffers);
4452 AssertNtStatusSuccess(Status);
4453 }
4454 else
4455 Status = STATUS_BUFFER_TOO_SMALL;
4456
4457 break;
4458 }
4459
4460 case VBOXESC_UHGSMI_ALLOCATE:
4461 {
4462 /* allocate VBOXUHGSMI buffer */
4463 if (pDevExt->fCmdVbvaEnabled)
4464 {
4465 WARN(("VBOXESC_UHGSMI_ALLOCATE not supported for CmdVbva mode"));
4466 Status = STATUS_INVALID_PARAMETER;
4467 break;
4468 }
4469
4470 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
4471 PVBOXDISPIFESCAPE_UHGSMI_ALLOCATE pAlocate = (PVBOXDISPIFESCAPE_UHGSMI_ALLOCATE)pEscapeHdr;
4472 Assert(pEscape->PrivateDriverDataSize == sizeof (VBOXDISPIFESCAPE_UHGSMI_ALLOCATE));
4473 if (pEscape->PrivateDriverDataSize == sizeof (VBOXDISPIFESCAPE_UHGSMI_ALLOCATE))
4474 {
4475 Status = vboxVideoAMgrCtxAllocCreate(&pContext->AllocContext, &pAlocate->Alloc);
4476 AssertNtStatusSuccess(Status);
4477 }
4478 else
4479 Status = STATUS_BUFFER_TOO_SMALL;
4480
4481 break;
4482 }
4483
4484 case VBOXESC_UHGSMI_DEALLOCATE:
4485 {
4486 if (pDevExt->fCmdVbvaEnabled)
4487 {
4488 WARN(("VBOXESC_UHGSMI_DEALLOCATE not supported for CmdVbva mode"));
4489 Status = STATUS_INVALID_PARAMETER;
4490 break;
4491 }
4492 /* deallocate VBOXUHGSMI buffer */
4493 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
4494 PVBOXDISPIFESCAPE_UHGSMI_DEALLOCATE pDealocate = (PVBOXDISPIFESCAPE_UHGSMI_DEALLOCATE)pEscapeHdr;
4495 Assert(pEscape->PrivateDriverDataSize == sizeof (VBOXDISPIFESCAPE_UHGSMI_DEALLOCATE));
4496 if (pEscape->PrivateDriverDataSize == sizeof (VBOXDISPIFESCAPE_UHGSMI_DEALLOCATE))
4497 {
4498 Status = vboxVideoAMgrCtxAllocDestroy(&pContext->AllocContext, pDealocate->hAlloc);
4499 AssertNtStatusSuccess(Status);
4500 }
4501 else
4502 Status = STATUS_BUFFER_TOO_SMALL;
4503
4504 break;
4505 }
4506
4507 case VBOXESC_CRHGSMICTLCON_CALL:
4508 {
4509 if (pDevExt->fCmdVbvaEnabled)
4510 {
4511 WARN(("VBOXESC_CRHGSMICTLCON_CALL not supported for CmdVbva mode"));
4512 Status = STATUS_INVALID_PARAMETER;
4513 break;
4514 }
4515
4516 PVBOXDISPIFESCAPE_CRHGSMICTLCON_CALL pCall = (PVBOXDISPIFESCAPE_CRHGSMICTLCON_CALL)pEscapeHdr;
4517 if (pEscape->PrivateDriverDataSize >= sizeof (*pCall))
4518 {
4519 /* this is true due to the above condition */
4520 Assert(pEscape->PrivateDriverDataSize > RT_OFFSETOF(VBOXDISPIFESCAPE_CRHGSMICTLCON_CALL, CallInfo));
4521 int rc = VBoxMpCrCtlConCallUserData(&pDevExt->CrCtlCon, &pCall->CallInfo, pEscape->PrivateDriverDataSize - RT_OFFSETOF(VBOXDISPIFESCAPE_CRHGSMICTLCON_CALL, CallInfo));
4522 pEscapeHdr->u32CmdSpecific = (uint32_t)rc;
4523 Status = STATUS_SUCCESS; /* <- always return success here, otherwise the private data buffer modifications
4524 * i.e. rc status stored in u32CmdSpecific will not be copied to user mode */
4525 if (!RT_SUCCESS(rc))
4526 WARN(("VBoxMpCrUmCtlConCall failed, rc(%d)", rc));
4527 }
4528 else
4529 {
4530 WARN(("buffer too small!"));
4531 Status = STATUS_BUFFER_TOO_SMALL;
4532 }
4533
4534 break;
4535 }
4536
4537 case VBOXESC_CRHGSMICTLCON_GETCLIENTID:
4538 {
4539 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
4540 if (!pContext)
4541 {
4542 WARN(("context not specified"));
4543 return STATUS_INVALID_PARAMETER;
4544 }
4545 if (pEscape->PrivateDriverDataSize == sizeof (*pEscapeHdr))
4546 {
4547 pEscapeHdr->u32CmdSpecific = pContext->u32CrConClientID;
4548 Status = STATUS_SUCCESS;
4549 }
4550 else
4551 {
4552 WARN(("unexpected buffer size!"));
4553 Status = STATUS_INVALID_PARAMETER;
4554 }
4555
4556 break;
4557 }
4558
4559 case VBOXESC_CRHGSMICTLCON_GETHOSTCAPS:
4560 {
4561 if (pEscape->PrivateDriverDataSize == sizeof (*pEscapeHdr))
4562 {
4563 if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VBOX)
4564 pEscapeHdr->u32CmdSpecific = VBoxMpCrGetHostCaps();
4565 else
4566 pEscapeHdr->u32CmdSpecific = 0;
4567 Status = STATUS_SUCCESS;
4568 }
4569 else
4570 {
4571 WARN(("unexpected buffer size!"));
4572 Status = STATUS_INVALID_PARAMETER;
4573 }
4574
4575 break;
4576 }
4577#endif
4578
4579 case VBOXESC_SETVISIBLEREGION:
4580 {
4581#ifdef VBOX_DISPIF_WITH_OPCONTEXT
4582 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
4583 if (!pContext)
4584 {
4585 WARN(("VBOXESC_SETVISIBLEREGION no context supplied!"));
4586 Status = STATUS_INVALID_PARAMETER;
4587 break;
4588 }
4589
4590 if (pContext->enmType != VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_SEAMLESS)
4591 {
4592 WARN(("VBOXESC_SETVISIBLEREGION invalid context supplied %d!", pContext->enmType));
4593 Status = STATUS_INVALID_PARAMETER;
4594 break;
4595 }
4596#endif
4597 /* visible regions for seamless */
4598 LPRGNDATA lpRgnData = VBOXDISPIFESCAPE_DATA(pEscapeHdr, RGNDATA);
4599 uint32_t cbData = VBOXDISPIFESCAPE_DATA_SIZE(pEscape->PrivateDriverDataSize);
4600 uint32_t cbRects = cbData - RT_UOFFSETOF(RGNDATA, Buffer);
4601 /* the lpRgnData->Buffer comes to us as RECT
4602 * to avoid extra memcpy we cast it to PRTRECT assuming
4603 * they are identical
4604 * see AssertCompile's above */
4605
4606 RTRECT *pRect = (RTRECT *)&lpRgnData->Buffer;
4607
4608 uint32_t cRects = cbRects/sizeof(RTRECT);
4609 int rc;
4610
4611 LOG(("IOCTL_VIDEO_VBOX_SETVISIBLEREGION cRects=%d", cRects));
4612 Assert(cbRects >= sizeof(RTRECT)
4613 && cbRects == cRects*sizeof(RTRECT)
4614 && cRects == lpRgnData->rdh.nCount);
4615 if ( cbRects >= sizeof(RTRECT)
4616 && cbRects == cRects*sizeof(RTRECT)
4617 && cRects == lpRgnData->rdh.nCount)
4618 {
4619 /*
4620 * Inform the host about the visible region
4621 */
4622 VMMDevVideoSetVisibleRegion *req = NULL;
4623
4624 rc = VbglR0GRAlloc ((VMMDevRequestHeader **)&req,
4625 sizeof (VMMDevVideoSetVisibleRegion) + (cRects-1)*sizeof(RTRECT),
4626 VMMDevReq_VideoSetVisibleRegion);
4627 AssertRC(rc);
4628 if (RT_SUCCESS(rc))
4629 {
4630 req->cRect = cRects;
4631 memcpy(&req->Rect, pRect, cRects*sizeof(RTRECT));
4632
4633 rc = VbglR0GRPerform (&req->header);
4634 AssertRC(rc);
4635 if (RT_SUCCESS(rc))
4636 Status = STATUS_SUCCESS;
4637 else
4638 {
4639 WARN(("VbglR0GRPerform failed rc (%d)", rc));
4640 Status = STATUS_UNSUCCESSFUL;
4641 }
4642 }
4643 else
4644 {
4645 WARN(("VbglR0GRAlloc failed rc (%d)", rc));
4646 Status = STATUS_UNSUCCESSFUL;
4647 }
4648 }
4649 else
4650 {
4651 WARN(("VBOXESC_SETVISIBLEREGION: incorrect buffer size (%d), reported count (%d)", cbRects, lpRgnData->rdh.nCount));
4652 Status = STATUS_INVALID_PARAMETER;
4653 }
4654 break;
4655 }
4656 case VBOXESC_ISVRDPACTIVE:
4657 /** @todo implement */
4658 Status = STATUS_SUCCESS;
4659 break;
4660#ifdef VBOX_WITH_CROGL
4661 case VBOXESC_SETCTXHOSTID:
4662 {
4663 /* set swapchain information */
4664 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
4665 if (!pContext)
4666 {
4667 WARN(("VBOXESC_SETCTXHOSTID: no context specified"));
4668 Status = STATUS_INVALID_PARAMETER;
4669 break;
4670 }
4671
4672 if (pEscape->PrivateDriverDataSize != sizeof (VBOXDISPIFESCAPE))
4673 {
4674 WARN(("VBOXESC_SETCTXHOSTID: invalid data size %d", pEscape->PrivateDriverDataSize));
4675 Status = STATUS_INVALID_PARAMETER;
4676 break;
4677 }
4678
4679 int32_t hostID = (int32_t)pEscapeHdr->u32CmdSpecific;
4680 if (hostID <= 0)
4681 {
4682 WARN(("VBOXESC_SETCTXHOSTID: invalid hostID %d", hostID));
4683 Status = STATUS_INVALID_PARAMETER;
4684 break;
4685 }
4686
4687 if (pContext->hostID)
4688 {
4689 WARN(("VBOXESC_SETCTXHOSTID: context already has hostID specified"));
4690 Status = STATUS_INVALID_PARAMETER;
4691 break;
4692 }
4693
4694 pContext->hostID = hostID;
4695 Status = STATUS_SUCCESS;
4696 break;
4697 }
4698 case VBOXESC_SWAPCHAININFO:
4699 {
4700 /* set swapchain information */
4701 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
4702 Status = vboxWddmSwapchainCtxEscape(pDevExt, pContext, (PVBOXDISPIFESCAPE_SWAPCHAININFO)pEscapeHdr, pEscape->PrivateDriverDataSize);
4703 AssertNtStatusSuccess(Status);
4704 break;
4705 }
4706#endif
4707 case VBOXESC_CONFIGURETARGETS:
4708 {
4709 LOG(("=> VBOXESC_CONFIGURETARGETS"));
4710
4711 if (!pEscape->Flags.HardwareAccess)
4712 {
4713 WARN(("VBOXESC_CONFIGURETARGETS called without HardwareAccess flag set, failing"));
4714 Status = STATUS_INVALID_PARAMETER;
4715 break;
4716 }
4717
4718#ifdef VBOX_DISPIF_WITH_OPCONTEXT
4719 /* win8.1 does not allow context-based escapes for display-only mode */
4720 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
4721 if (!pContext)
4722 {
4723 WARN(("VBOXESC_CONFIGURETARGETS no context supplied!"));
4724 Status = STATUS_INVALID_PARAMETER;
4725 break;
4726 }
4727
4728 if (pContext->enmType != VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_RESIZE)
4729 {
4730 WARN(("VBOXESC_CONFIGURETARGETS invalid context supplied %d!", pContext->enmType));
4731 Status = STATUS_INVALID_PARAMETER;
4732 break;
4733 }
4734#endif
4735
4736 if (pEscape->PrivateDriverDataSize != sizeof (*pEscapeHdr))
4737 {
4738 WARN(("VBOXESC_CONFIGURETARGETS invalid private driver size %d", pEscape->PrivateDriverDataSize));
4739 Status = STATUS_INVALID_PARAMETER;
4740 break;
4741 }
4742
4743 if (pEscapeHdr->u32CmdSpecific)
4744 {
4745 WARN(("VBOXESC_CONFIGURETARGETS invalid command %d", pEscapeHdr->u32CmdSpecific));
4746 Status = STATUS_INVALID_PARAMETER;
4747 break;
4748 }
4749
4750 HANDLE hKey = NULL;
4751 WCHAR aNameBuf[100];
4752 uint32_t cAdjusted = 0;
4753
4754 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
4755 {
4756 VBOXWDDM_TARGET *pTarget = &pDevExt->aTargets[i];
4757 if (pTarget->fConfigured)
4758 continue;
4759
4760 pTarget->fConfigured = true;
4761
4762 if (!pTarget->fConnected)
4763 {
4764 Status = VBoxWddmChildStatusConnect(pDevExt, (uint32_t)i, TRUE);
4765 if (NT_SUCCESS(Status))
4766 ++cAdjusted;
4767 else
4768 WARN(("VBOXESC_CONFIGURETARGETS vboxWddmChildStatusConnectSecondaries failed Status 0x%x\n", Status));
4769 }
4770
4771 if (!hKey)
4772 {
4773 Status = IoOpenDeviceRegistryKey(pDevExt->pPDO, PLUGPLAY_REGKEY_DRIVER, GENERIC_WRITE, &hKey);
4774 if (!NT_SUCCESS(Status))
4775 {
4776 WARN(("VBOXESC_CONFIGURETARGETS IoOpenDeviceRegistryKey failed, Status = 0x%x", Status));
4777 hKey = NULL;
4778 continue;
4779 }
4780 }
4781
4782 Assert(hKey);
4783
4784 swprintf(aNameBuf, L"%s%d", VBOXWDDM_REG_DRV_DISPFLAGS_PREFIX, i);
4785 Status = vboxWddmRegSetValueDword(hKey, aNameBuf, VBOXWDDM_CFG_DRVTARGET_CONNECTED);
4786 if (!NT_SUCCESS(Status))
4787 WARN(("VBOXESC_CONFIGURETARGETS vboxWddmRegSetValueDword (%d) failed Status 0x%x\n", aNameBuf, Status));
4788
4789 }
4790
4791 if (hKey)
4792 {
4793 NTSTATUS rcNt2 = ZwClose(hKey);
4794 Assert(rcNt2 == STATUS_SUCCESS); NOREF(rcNt2);
4795 }
4796
4797 pEscapeHdr->u32CmdSpecific = cAdjusted;
4798
4799 Status = STATUS_SUCCESS;
4800
4801 LOG(("<= VBOXESC_CONFIGURETARGETS"));
4802 break;
4803 }
4804 case VBOXESC_SETALLOCHOSTID:
4805 {
4806 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)pEscape->hDevice;
4807 if (!pDevice)
4808 {
4809 WARN(("VBOXESC_SETALLOCHOSTID called without no device specified, failing"));
4810 Status = STATUS_INVALID_PARAMETER;
4811 break;
4812 }
4813
4814 if (pEscape->PrivateDriverDataSize != sizeof (VBOXDISPIFESCAPE_SETALLOCHOSTID))
4815 {
4816 WARN(("invalid buffer size for VBOXDISPIFESCAPE_SHRC_REF, was(%d), but expected (%d)",
4817 pEscape->PrivateDriverDataSize, sizeof (VBOXDISPIFESCAPE_SHRC_REF)));
4818 Status = STATUS_INVALID_PARAMETER;
4819 break;
4820 }
4821
4822 if (!pEscape->Flags.HardwareAccess)
4823 {
4824 WARN(("VBOXESC_SETALLOCHOSTID not HardwareAccess"));
4825 Status = STATUS_INVALID_PARAMETER;
4826 break;
4827 }
4828
4829 PVBOXDISPIFESCAPE_SETALLOCHOSTID pSetHostID = (PVBOXDISPIFESCAPE_SETALLOCHOSTID)pEscapeHdr;
4830 PVBOXWDDM_ALLOCATION pAlloc = vboxWddmGetAllocationFromHandle(pDevExt, (D3DKMT_HANDLE)pSetHostID->hAlloc);
4831 if (!pAlloc)
4832 {
4833 WARN(("failed to get allocation from handle"));
4834 Status = STATUS_INVALID_PARAMETER;
4835 break;
4836 }
4837
4838 if (pAlloc->enmType != VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE)
4839 {
4840 WARN(("setHostID: invalid allocation type: %d", pAlloc->enmType));
4841 Status = STATUS_INVALID_PARAMETER;
4842 break;
4843 }
4844
4845 pSetHostID->rc = VBoxWddmOaSetHostID(pDevice, pAlloc, pSetHostID->hostID, &pSetHostID->EscapeHdr.u32CmdSpecific);
4846
4847 if (pAlloc->bAssigned)
4848 {
4849 PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
4850 Assert(pAlloc->AllocData.SurfDesc.VidPnSourceId < (D3DDDI_VIDEO_PRESENT_SOURCE_ID)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
4851 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pAlloc->AllocData.SurfDesc.VidPnSourceId];
4852 if (pSource->AllocData.hostID != pAlloc->AllocData.hostID)
4853 {
4854 pSource->AllocData.hostID = pAlloc->AllocData.hostID;
4855 pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_LOCATION;
4856
4857 vboxWddmGhDisplayCheckSetInfo(pDevExt);
4858 }
4859 }
4860
4861 Status = STATUS_SUCCESS;
4862 break;
4863 }
4864 case VBOXESC_SHRC_ADDREF:
4865 case VBOXESC_SHRC_RELEASE:
4866 {
4867 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)pEscape->hDevice;
4868 if (!pDevice)
4869 {
4870 WARN(("VBOXESC_SHRC_ADDREF|VBOXESC_SHRC_RELEASE called without no device specified, failing"));
4871 Status = STATUS_INVALID_PARAMETER;
4872 break;
4873 }
4874
4875 /* query whether the allocation represanted by the given [wine-generated] shared resource handle still exists */
4876 if (pEscape->PrivateDriverDataSize != sizeof (VBOXDISPIFESCAPE_SHRC_REF))
4877 {
4878 WARN(("invalid buffer size for VBOXDISPIFESCAPE_SHRC_REF, was(%d), but expected (%d)",
4879 pEscape->PrivateDriverDataSize, sizeof (VBOXDISPIFESCAPE_SHRC_REF)));
4880 Status = STATUS_INVALID_PARAMETER;
4881 break;
4882 }
4883
4884 PVBOXDISPIFESCAPE_SHRC_REF pShRcRef = (PVBOXDISPIFESCAPE_SHRC_REF)pEscapeHdr;
4885 PVBOXWDDM_ALLOCATION pAlloc = vboxWddmGetAllocationFromHandle(pDevExt, (D3DKMT_HANDLE)pShRcRef->hAlloc);
4886 if (!pAlloc)
4887 {
4888 WARN(("failed to get allocation from handle"));
4889 Status = STATUS_INVALID_PARAMETER;
4890 break;
4891 }
4892
4893 PVBOXWDDM_OPENALLOCATION pOa = VBoxWddmOaSearch(pDevice, pAlloc);
4894 if (!pOa)
4895 {
4896 WARN(("failed to get open allocation from alloc"));
4897 Status = STATUS_INVALID_PARAMETER;
4898 break;
4899 }
4900
4901 Assert(pAlloc->cShRcRefs >= pOa->cShRcRefs);
4902
4903 if (pEscapeHdr->escapeCode == VBOXESC_SHRC_ADDREF)
4904 {
4905#ifdef DEBUG
4906 Assert(!pAlloc->fAssumedDeletion);
4907#endif
4908 ++pAlloc->cShRcRefs;
4909 ++pOa->cShRcRefs;
4910 }
4911 else
4912 {
4913 Assert(pAlloc->cShRcRefs);
4914 Assert(pOa->cShRcRefs);
4915 --pAlloc->cShRcRefs;
4916 --pOa->cShRcRefs;
4917#ifdef DEBUG
4918 Assert(!pAlloc->fAssumedDeletion);
4919 if (!pAlloc->cShRcRefs)
4920 {
4921 pAlloc->fAssumedDeletion = TRUE;
4922 }
4923#endif
4924 }
4925
4926 pShRcRef->EscapeHdr.u32CmdSpecific = pAlloc->cShRcRefs;
4927 Status = STATUS_SUCCESS;
4928 break;
4929 }
4930 case VBOXESC_ISANYX:
4931 {
4932 if (pEscape->PrivateDriverDataSize != sizeof (VBOXDISPIFESCAPE_ISANYX))
4933 {
4934 WARN(("invalid private driver size %d", pEscape->PrivateDriverDataSize));
4935 Status = STATUS_INVALID_PARAMETER;
4936 break;
4937 }
4938
4939 PVBOXDISPIFESCAPE_ISANYX pIsAnyX = (PVBOXDISPIFESCAPE_ISANYX)pEscapeHdr;
4940 pIsAnyX->u32IsAnyX = VBoxCommonFromDeviceExt(pDevExt)->fAnyX;
4941 Status = STATUS_SUCCESS;
4942 break;
4943 }
4944 case VBOXESC_UPDATEMODES:
4945 {
4946 LOG(("=> VBOXESC_UPDATEMODES"));
4947
4948 if (!pEscape->Flags.HardwareAccess)
4949 {
4950 WARN(("VBOXESC_UPDATEMODES called without HardwareAccess flag set, failing"));
4951 Status = STATUS_INVALID_PARAMETER;
4952 break;
4953 }
4954
4955#ifdef VBOX_DISPIF_WITH_OPCONTEXT
4956 /* win8.1 does not allow context-based escapes for display-only mode */
4957 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
4958 if (!pContext)
4959 {
4960 WARN(("VBOXESC_UPDATEMODES no context supplied!"));
4961 Status = STATUS_INVALID_PARAMETER;
4962 break;
4963 }
4964
4965 if (pContext->enmType != VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_RESIZE)
4966 {
4967 WARN(("VBOXESC_UPDATEMODES invalid context supplied %d!", pContext->enmType));
4968 Status = STATUS_INVALID_PARAMETER;
4969 break;
4970 }
4971#endif
4972
4973 if (pEscape->PrivateDriverDataSize != sizeof (VBOXDISPIFESCAPE_UPDATEMODES))
4974 {
4975 WARN(("VBOXESC_UPDATEMODES invalid private driver size %d", pEscape->PrivateDriverDataSize));
4976 Status = STATUS_INVALID_PARAMETER;
4977 break;
4978 }
4979
4980 VBOXDISPIFESCAPE_UPDATEMODES *pData = (VBOXDISPIFESCAPE_UPDATEMODES*)pEscapeHdr;
4981 Status = VBoxVidPnUpdateModes(pDevExt, pData->u32TargetId, &pData->Size);
4982 if (!NT_SUCCESS(Status))
4983 {
4984 WARN(("VBoxVidPnUpdateModes failed Status(%#x)\n", Status));
4985 return Status;
4986 }
4987
4988 break;
4989 }
4990 case VBOXESC_TARGET_CONNECTIVITY:
4991 {
4992 if (!pEscape->Flags.HardwareAccess)
4993 {
4994 WARN(("VBOXESC_TARGET_CONNECTIVITY called without HardwareAccess flag set, failing"));
4995 Status = STATUS_INVALID_PARAMETER;
4996 break;
4997 }
4998
4999 if (pEscape->PrivateDriverDataSize != sizeof(VBOXDISPIFESCAPE_TARGETCONNECTIVITY))
5000 {
5001 WARN(("VBOXESC_TARGET_CONNECTIVITY invalid private driver size %d", pEscape->PrivateDriverDataSize));
5002 Status = STATUS_INVALID_PARAMETER;
5003 break;
5004 }
5005
5006 VBOXDISPIFESCAPE_TARGETCONNECTIVITY *pData = (VBOXDISPIFESCAPE_TARGETCONNECTIVITY *)pEscapeHdr;
5007 LOG(("=> VBOXESC_TARGET_CONNECTIVITY[%d] 0x%08X", pData->u32TargetId, pData->fu32Connect));
5008
5009 if (pData->u32TargetId >= (uint32_t)VBoxCommonFromDeviceExt(pDevExt)->cDisplays)
5010 {
5011 WARN(("VBOXESC_TARGET_CONNECTIVITY invalid screen index 0x%x", pData->u32TargetId));
5012 Status = STATUS_INVALID_PARAMETER;
5013 break;
5014 }
5015
5016 PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[pData->u32TargetId];
5017 pTarget->fDisabled = !RT_BOOL(pData->fu32Connect & 1);
5018 pTarget->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_TOPOLOGY;
5019
5020 break;
5021 }
5022 case VBOXESC_DBGPRINT:
5023 {
5024 /* use RT_OFFSETOF instead of sizeof since sizeof will give an aligned size that might
5025 * be bigger than the VBOXDISPIFESCAPE_DBGPRINT with a data containing just a few chars */
5026 Assert(pEscape->PrivateDriverDataSize >= RT_UOFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1]));
5027 /* only do DbgPrint when pEscape->PrivateDriverDataSize > RT_OFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1])
5028 * since == RT_OFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1]) means the buffer contains just \0,
5029 * i.e. no need to print it */
5030 if (pEscape->PrivateDriverDataSize > RT_UOFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1]))
5031 {
5032 PVBOXDISPIFESCAPE_DBGPRINT pDbgPrint = (PVBOXDISPIFESCAPE_DBGPRINT)pEscapeHdr;
5033 /* ensure the last char is \0*/
5034 if (*((uint8_t*)pDbgPrint + pEscape->PrivateDriverDataSize - 1) == '\0')
5035 {
5036 if (g_VBoxLogUm & VBOXWDDM_CFG_LOG_UM_DBGPRINT)
5037 DbgPrint("%s\n", pDbgPrint->aStringBuf);
5038 if (g_VBoxLogUm & VBOXWDDM_CFG_LOG_UM_BACKDOOR)
5039 LOGREL_EXACT(("%s\n", pDbgPrint->aStringBuf));
5040 }
5041 }
5042 Status = STATUS_SUCCESS;
5043 break;
5044 }
5045 case VBOXESC_DBGDUMPBUF:
5046 {
5047 Status = vboxUmdDumpBuf((PVBOXDISPIFESCAPE_DBGDUMPBUF)pEscapeHdr, pEscape->PrivateDriverDataSize);
5048 break;
5049 }
5050 case VBOXESC_GUEST_DISPLAYCHANGED:
5051 {
5052 LOG(("=> VBOXESC_GUEST_DISPLAYCHANGED"));
5053
5054 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
5055 {
5056 vboxWddmDisplaySettingsCheckPos(pDevExt, i);
5057 }
5058 break;
5059 }
5060 default:
5061 WARN(("unsupported escape code (0x%x)", pEscapeHdr->escapeCode));
5062 break;
5063 }
5064 }
5065 else
5066 {
5067 WARN(("pEscape->PrivateDriverDataSize(%d) < (%d)", pEscape->PrivateDriverDataSize, sizeof (VBOXDISPIFESCAPE)));
5068 Status = STATUS_BUFFER_TOO_SMALL;
5069 }
5070
5071// LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
5072
5073 return Status;
5074}
5075
5076NTSTATUS
5077APIENTRY
5078DxgkDdiCollectDbgInfo(
5079 CONST HANDLE hAdapter,
5080 CONST DXGKARG_COLLECTDBGINFO* pCollectDbgInfo
5081 )
5082{
5083 RT_NOREF(hAdapter, pCollectDbgInfo);
5084 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
5085
5086 AssertBreakpoint();
5087
5088 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
5089
5090 return STATUS_SUCCESS;
5091}
5092
5093typedef struct VBOXWDDM_QUERYCURFENCE_CB
5094{
5095 PVBOXMP_DEVEXT pDevExt;
5096 ULONG MessageNumber;
5097 ULONG uLastCompletedCmdFenceId;
5098} VBOXWDDM_QUERYCURFENCE_CB, *PVBOXWDDM_QUERYCURFENCE_CB;
5099
5100static BOOLEAN vboxWddmQueryCurrentFenceCb(PVOID Context)
5101{
5102 PVBOXWDDM_QUERYCURFENCE_CB pdc = (PVBOXWDDM_QUERYCURFENCE_CB)Context;
5103 PVBOXMP_DEVEXT pDevExt = pdc->pDevExt;
5104 BOOL bRc = DxgkDdiInterruptRoutineLegacy(pDevExt, pdc->MessageNumber);
5105 pdc->uLastCompletedCmdFenceId = pDevExt->u.primary.Vdma.uLastCompletedPagingBufferCmdFenceId;
5106 return bRc;
5107}
5108
5109#ifdef VBOX_WITH_CROGL
5110static NTSTATUS
5111APIENTRY
5112DxgkDdiQueryCurrentFenceNew(
5113 CONST HANDLE hAdapter,
5114 DXGKARG_QUERYCURRENTFENCE* pCurrentFence)
5115{
5116 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
5117
5118 vboxVDbgBreakF();
5119
5120 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
5121
5122 WARN(("=>DxgkDdiQueryCurrentFenceNew"));
5123
5124 uint32_t u32FenceSubmitted = 0;
5125 uint32_t u32FenceCompleted = 0;
5126 uint32_t u32FenceProcessed = 0;
5127
5128 LARGE_INTEGER DelayInterval;
5129 DelayInterval.QuadPart = -10LL * 1000LL * 1000LL;
5130
5131 for (;;)
5132 {
5133 u32FenceCompleted = VBoxCmdVbvaCheckCompleted(pDevExt, &pDevExt->CmdVbva, false, &u32FenceSubmitted, &u32FenceProcessed);
5134 if (!u32FenceCompleted)
5135 {
5136 WARN(("VBoxCmdVbvaCheckCompleted failed"));
5137 return STATUS_UNSUCCESSFUL;
5138 }
5139
5140 if (u32FenceSubmitted == u32FenceProcessed)
5141 break;
5142
5143 WARN(("uncompleted fences, u32FenceSubmitted(%d), u32FenceCompleted(%d) u32FenceProcessed(%d)", u32FenceSubmitted, u32FenceCompleted, u32FenceProcessed));
5144
5145 NTSTATUS Status = KeDelayExecutionThread(KernelMode, FALSE, &DelayInterval);
5146 if (Status != STATUS_SUCCESS)
5147 WARN(("KeDelayExecutionThread failed %#x", Status));
5148 }
5149
5150 pCurrentFence->CurrentFence = u32FenceCompleted;
5151
5152 WARN(("<=DxgkDdiQueryCurrentFenceNew"));
5153
5154 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
5155
5156 return STATUS_SUCCESS;
5157}
5158#endif
5159
5160static NTSTATUS
5161APIENTRY
5162DxgkDdiQueryCurrentFenceLegacy(
5163 CONST HANDLE hAdapter,
5164 DXGKARG_QUERYCURRENTFENCE* pCurrentFence)
5165{
5166 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
5167
5168 vboxVDbgBreakF();
5169
5170 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
5171 VBOXWDDM_QUERYCURFENCE_CB context = {0};
5172 context.pDevExt = pDevExt;
5173 BOOLEAN bRet;
5174 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
5175 pDevExt->u.primary.DxgkInterface.DeviceHandle,
5176 vboxWddmQueryCurrentFenceCb,
5177 &context,
5178 0, /* IN ULONG MessageNumber */
5179 &bRet);
5180 AssertNtStatusSuccess(Status);
5181 if (Status == STATUS_SUCCESS)
5182 {
5183 pCurrentFence->CurrentFence = context.uLastCompletedCmdFenceId;
5184 }
5185
5186 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
5187
5188 return STATUS_SUCCESS;
5189}
5190
5191NTSTATUS
5192APIENTRY
5193DxgkDdiIsSupportedVidPn(
5194 CONST HANDLE hAdapter,
5195 OUT DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPnArg
5196 )
5197{
5198 /* The DxgkDdiIsSupportedVidPn should be made pageable. */
5199 PAGED_CODE();
5200
5201 LOGF(("ENTER, context(0x%x)", hAdapter));
5202
5203 vboxVDbgBreakFv();
5204
5205 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
5206 NTSTATUS Status = VBoxVidPnIsSupported(pDevExt, pIsSupportedVidPnArg->hDesiredVidPn, &pIsSupportedVidPnArg->IsVidPnSupported);
5207 if (!NT_SUCCESS(Status))
5208 {
5209 WARN(("VBoxVidPnIsSupported failed Status(%#x)\n", Status));
5210 return Status;
5211 }
5212
5213 LOGF(("LEAVE, isSupported(%d), context(0x%x)", pIsSupportedVidPnArg->IsVidPnSupported, hAdapter));
5214
5215 return STATUS_SUCCESS;
5216}
5217
5218NTSTATUS
5219APIENTRY
5220DxgkDdiRecommendFunctionalVidPn(
5221 CONST HANDLE hAdapter,
5222 CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPnArg
5223 )
5224{
5225 /* The DxgkDdiRecommendFunctionalVidPn should be made pageable. */
5226 PAGED_CODE();
5227
5228 LOGF(("ENTER, context(0x%x)", hAdapter));
5229
5230 vboxVDbgBreakFv();
5231
5232 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
5233
5234 if (pRecommendFunctionalVidPnArg->PrivateDriverDataSize != sizeof (VBOXWDDM_RECOMMENDVIDPN))
5235 {
5236 WARN(("invalid size"));
5237 return STATUS_INVALID_PARAMETER;
5238 }
5239
5240 VBOXWDDM_RECOMMENDVIDPN *pData = (VBOXWDDM_RECOMMENDVIDPN*)pRecommendFunctionalVidPnArg->pPrivateDriverData;
5241 Assert(pData);
5242
5243 NTSTATUS Status = VBoxVidPnRecommendFunctional(pDevExt, pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, pData);
5244 if (!NT_SUCCESS(Status))
5245 {
5246 WARN(("VBoxVidPnRecommendFunctional failed %#x", Status));
5247 return Status;
5248 }
5249
5250 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
5251
5252 return STATUS_SUCCESS;
5253}
5254
5255NTSTATUS
5256APIENTRY
5257DxgkDdiEnumVidPnCofuncModality(
5258 CONST HANDLE hAdapter,
5259 CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModalityArg
5260 )
5261{
5262 /* The DxgkDdiEnumVidPnCofuncModality function should be made pageable. */
5263 PAGED_CODE();
5264
5265 LOGF(("ENTER, context(0x%x)", hAdapter));
5266
5267 vboxVDbgBreakFv();
5268
5269 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
5270
5271 NTSTATUS Status = VBoxVidPnCofuncModality(pDevExt, pEnumCofuncModalityArg->hConstrainingVidPn, pEnumCofuncModalityArg->EnumPivotType, &pEnumCofuncModalityArg->EnumPivot);
5272 if (!NT_SUCCESS(Status))
5273 {
5274 WARN(("VBoxVidPnCofuncModality failed Status(%#x)\n", Status));
5275 return Status;
5276 }
5277
5278 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
5279
5280 return STATUS_SUCCESS;
5281}
5282
5283NTSTATUS
5284APIENTRY
5285DxgkDdiSetVidPnSourceAddress(
5286 CONST HANDLE hAdapter,
5287 CONST DXGKARG_SETVIDPNSOURCEADDRESS* pSetVidPnSourceAddress
5288 )
5289{
5290 /* The DxgkDdiSetVidPnSourceAddress function should be made pageable. */
5291 PAGED_CODE();
5292
5293 vboxVDbgBreakFv();
5294
5295 LOGF(("ENTER, context(0x%x)", hAdapter));
5296
5297 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
5298 if ((UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays <= pSetVidPnSourceAddress->VidPnSourceId)
5299 {
5300 WARN(("invalid VidPnSourceId (%d), for displays(%d)", pSetVidPnSourceAddress->VidPnSourceId, VBoxCommonFromDeviceExt(pDevExt)->cDisplays));
5301 return STATUS_INVALID_PARAMETER;
5302 }
5303
5304 vboxWddmDisplaySettingsCheckPos(pDevExt, pSetVidPnSourceAddress->VidPnSourceId);
5305
5306 NTSTATUS Status = STATUS_SUCCESS;
5307 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pSetVidPnSourceAddress->VidPnSourceId];
5308 PVBOXWDDM_ALLOCATION pAllocation;
5309 Assert(pSetVidPnSourceAddress->hAllocation);
5310 Assert(pSetVidPnSourceAddress->hAllocation || pSource->pPrimaryAllocation);
5311 Assert (pSetVidPnSourceAddress->Flags.Value < 2); /* i.e. 0 or 1 (ModeChange) */
5312
5313 if (pSetVidPnSourceAddress->hAllocation)
5314 {
5315 pAllocation = (PVBOXWDDM_ALLOCATION)pSetVidPnSourceAddress->hAllocation;
5316 vboxWddmAssignPrimary(pSource, pAllocation, pSetVidPnSourceAddress->VidPnSourceId);
5317 }
5318 else
5319 pAllocation = pSource->pPrimaryAllocation;
5320
5321 if (pAllocation)
5322 {
5323 vboxWddmAddrSetVram(&pAllocation->AllocData.Addr, pSetVidPnSourceAddress->PrimarySegment, (VBOXVIDEOOFFSET)pSetVidPnSourceAddress->PrimaryAddress.QuadPart);
5324 }
5325
5326 if (g_VBoxDisplayOnly && !pAllocation)
5327 {
5328 /* the VRAM here is an absolute address, nto an offset!
5329 * convert to offset since all internal VBox functionality is offset-based */
5330 vboxWddmAddrSetVram(&pSource->AllocData.Addr, pSetVidPnSourceAddress->PrimarySegment,
5331 vboxWddmVramAddrToOffset(pDevExt, pSetVidPnSourceAddress->PrimaryAddress));
5332 }
5333 else
5334 {
5335 Assert(!g_VBoxDisplayOnly);
5336 vboxWddmAddrSetVram(&pSource->AllocData.Addr, pSetVidPnSourceAddress->PrimarySegment,
5337 pSetVidPnSourceAddress->PrimaryAddress.QuadPart);
5338 }
5339
5340 pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_LOCATION;
5341
5342 vboxWddmGhDisplayCheckSetInfoFromSource(pDevExt, pSource);
5343
5344 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
5345
5346 return Status;
5347}
5348
5349NTSTATUS
5350APIENTRY
5351DxgkDdiSetVidPnSourceVisibility(
5352 CONST HANDLE hAdapter,
5353 CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility
5354 )
5355{
5356 /* DxgkDdiSetVidPnSourceVisibility should be made pageable. */
5357 PAGED_CODE();
5358
5359 vboxVDbgBreakFv();
5360
5361 LOGF(("ENTER, context(0x%x)", hAdapter));
5362
5363 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
5364
5365 if ((UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays <= pSetVidPnSourceVisibility->VidPnSourceId)
5366 {
5367 WARN(("invalid VidPnSourceId (%d), for displays(%d)", pSetVidPnSourceVisibility->VidPnSourceId, VBoxCommonFromDeviceExt(pDevExt)->cDisplays));
5368 return STATUS_INVALID_PARAMETER;
5369 }
5370
5371 vboxWddmDisplaySettingsCheckPos(pDevExt, pSetVidPnSourceVisibility->VidPnSourceId);
5372
5373 NTSTATUS Status = STATUS_SUCCESS;
5374 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pSetVidPnSourceVisibility->VidPnSourceId];
5375 PVBOXWDDM_ALLOCATION pAllocation = pSource->pPrimaryAllocation;
5376 if (pAllocation)
5377 {
5378 Assert(pAllocation->bVisible == pSource->bVisible);
5379 pAllocation->bVisible = pSetVidPnSourceVisibility->Visible;
5380 }
5381
5382 if (pSource->bVisible != pSetVidPnSourceVisibility->Visible)
5383 {
5384 pSource->bVisible = pSetVidPnSourceVisibility->Visible;
5385// pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_VISIBILITY;
5386// if (pDevExt->fCmdVbvaEnabled || pSource->bVisible)
5387// {
5388// vboxWddmGhDisplayCheckSetInfoFromSource(pDevExt, pSource);
5389// }
5390 }
5391
5392 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
5393
5394 return Status;
5395}
5396
5397NTSTATUS
5398APIENTRY
5399DxgkDdiCommitVidPn(
5400 CONST HANDLE hAdapter,
5401 CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPnArg
5402 )
5403{
5404 LOG(("ENTER AffectedVidPnSourceId(%d) hAdapter(0x%x)", pCommitVidPnArg->AffectedVidPnSourceId, hAdapter));
5405
5406 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
5407 NTSTATUS Status;
5408
5409 vboxVDbgBreakFv();
5410
5411 VBOXWDDM_SOURCE *paSources = (VBOXWDDM_SOURCE*)RTMemAlloc(sizeof (VBOXWDDM_SOURCE) * VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
5412 if (!paSources)
5413 {
5414 WARN(("RTMemAlloc failed"));
5415 return STATUS_NO_MEMORY;
5416 }
5417
5418 VBOXWDDM_TARGET *paTargets = (VBOXWDDM_TARGET*)RTMemAlloc(sizeof (VBOXWDDM_TARGET) * VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
5419 if (!paTargets)
5420 {
5421 WARN(("RTMemAlloc failed"));
5422 RTMemFree(paSources);
5423 return STATUS_NO_MEMORY;
5424 }
5425
5426 VBoxVidPnSourcesInit(paSources, VBoxCommonFromDeviceExt(pDevExt)->cDisplays, VBOXWDDM_HGSYNC_F_SYNCED_ALL);
5427
5428 VBoxVidPnTargetsInit(paTargets, VBoxCommonFromDeviceExt(pDevExt)->cDisplays, VBOXWDDM_HGSYNC_F_SYNCED_ALL);
5429
5430 VBoxVidPnSourcesCopy(paSources, pDevExt->aSources, VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
5431 VBoxVidPnTargetsCopy(paTargets, pDevExt->aTargets, VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
5432
5433 do {
5434 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
5435 Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pCommitVidPnArg->hFunctionalVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
5436 if (!NT_SUCCESS(Status))
5437 {
5438 WARN(("DxgkCbQueryVidPnInterface failed Status 0x%x", Status));
5439 break;
5440 }
5441
5442#ifdef VBOXWDDM_DEBUG_VIDPN
5443 vboxVidPnDumpVidPn("\n>>>>COMMIT VidPN: >>>>", pDevExt, pCommitVidPnArg->hFunctionalVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<\n");
5444#endif
5445
5446 if (pCommitVidPnArg->AffectedVidPnSourceId != D3DDDI_ID_ALL)
5447 {
5448 Status = VBoxVidPnCommitSourceModeForSrcId(
5449 pDevExt,
5450 pCommitVidPnArg->hFunctionalVidPn, pVidPnInterface,
5451 (PVBOXWDDM_ALLOCATION)pCommitVidPnArg->hPrimaryAllocation,
5452 pCommitVidPnArg->AffectedVidPnSourceId, paSources, paTargets, pCommitVidPnArg->Flags.PathPowerTransition);
5453 if (!NT_SUCCESS(Status))
5454 {
5455 WARN(("VBoxVidPnCommitSourceModeForSrcId for current VidPn failed Status 0x%x", Status));
5456 break;
5457 }
5458 }
5459 else
5460 {
5461 Status = VBoxVidPnCommitAll(pDevExt, pCommitVidPnArg->hFunctionalVidPn, pVidPnInterface,
5462 (PVBOXWDDM_ALLOCATION)pCommitVidPnArg->hPrimaryAllocation,
5463 paSources, paTargets);
5464 if (!NT_SUCCESS(Status))
5465 {
5466 WARN(("VBoxVidPnCommitAll for current VidPn failed Status 0x%x", Status));
5467 break;
5468 }
5469 }
5470
5471 Assert(NT_SUCCESS(Status));
5472 pDevExt->u.primary.hCommittedVidPn = pCommitVidPnArg->hFunctionalVidPn;
5473 VBoxVidPnSourcesCopy(pDevExt->aSources, paSources, VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
5474 VBoxVidPnTargetsCopy(pDevExt->aTargets, paTargets, VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
5475
5476 VBoxDumpSourceTargetArrays(paSources, paTargets, VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
5477
5478 vboxWddmGhDisplayCheckSetInfo(pDevExt);
5479 } while (0);
5480
5481 RTMemFree(paSources);
5482 RTMemFree(paTargets);
5483
5484 LOG(("LEAVE, status(0x%x), hAdapter(0x%x)", Status, hAdapter));
5485
5486 return Status;
5487}
5488
5489NTSTATUS
5490APIENTRY
5491DxgkDdiUpdateActiveVidPnPresentPath(
5492 CONST HANDLE hAdapter,
5493 CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPathArg
5494 )
5495{
5496 RT_NOREF(hAdapter, pUpdateActiveVidPnPresentPathArg);
5497 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
5498
5499 AssertBreakpoint();
5500
5501 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
5502
5503 return STATUS_SUCCESS;
5504}
5505
5506NTSTATUS
5507APIENTRY
5508DxgkDdiRecommendMonitorModes(
5509 CONST HANDLE hAdapter,
5510 CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModesArg
5511 )
5512{
5513 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
5514
5515 vboxVDbgBreakFv();
5516
5517 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
5518
5519 NTSTATUS Status = VBoxVidPnRecommendMonitorModes(pDevExt, pRecommendMonitorModesArg->VideoPresentTargetId,
5520 pRecommendMonitorModesArg->hMonitorSourceModeSet, pRecommendMonitorModesArg->pMonitorSourceModeSetInterface);
5521 if (!NT_SUCCESS(Status))
5522 {
5523 WARN(("VBoxVidPnRecommendMonitorModes failed %#x", Status));
5524 return Status;
5525 }
5526
5527 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
5528
5529 return STATUS_SUCCESS;
5530}
5531
5532NTSTATUS
5533APIENTRY
5534DxgkDdiRecommendVidPnTopology(
5535 CONST HANDLE hAdapter,
5536 CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopologyArg
5537 )
5538{
5539 RT_NOREF(hAdapter, pRecommendVidPnTopologyArg);
5540 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
5541
5542 vboxVDbgBreakFv();
5543
5544 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
5545
5546 return STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY;
5547}
5548
5549NTSTATUS
5550APIENTRY
5551DxgkDdiGetScanLine(
5552 CONST HANDLE hAdapter,
5553 DXGKARG_GETSCANLINE* pGetScanLine)
5554{
5555 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
5556
5557 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
5558
5559#ifdef DEBUG_misha
5560// RT_BREAKPOINT();
5561#endif
5562
5563 NTSTATUS Status = VBoxWddmSlGetScanLine(pDevExt, pGetScanLine);
5564
5565 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
5566
5567 return Status;
5568}
5569
5570NTSTATUS
5571APIENTRY
5572DxgkDdiStopCapture(
5573 CONST HANDLE hAdapter,
5574 CONST DXGKARG_STOPCAPTURE* pStopCapture)
5575{
5576 RT_NOREF(hAdapter, pStopCapture);
5577 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
5578
5579 AssertBreakpoint();
5580
5581 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
5582
5583 return STATUS_SUCCESS;
5584}
5585
5586NTSTATUS
5587APIENTRY
5588DxgkDdiControlInterrupt(
5589 CONST HANDLE hAdapter,
5590 CONST DXGK_INTERRUPT_TYPE InterruptType,
5591 BOOLEAN Enable
5592 )
5593{
5594 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
5595
5596 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
5597 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
5598
5599 switch (InterruptType)
5600 {
5601 case DXGK_INTERRUPT_DISPLAYONLY_VSYNC:
5602 case DXGK_INTERRUPT_CRTC_VSYNC:
5603 {
5604 Status = VBoxWddmSlEnableVSyncNotification(pDevExt, Enable);
5605 if (NT_SUCCESS(Status))
5606 Status = STATUS_SUCCESS; /* <- sanity */
5607 else
5608 WARN(("VSYNC Interrupt control failed Enable(%d), Status(0x%x)", Enable, Status));
5609 break;
5610 }
5611 case DXGK_INTERRUPT_DMA_COMPLETED:
5612 case DXGK_INTERRUPT_DMA_PREEMPTED:
5613 case DXGK_INTERRUPT_DMA_FAULTED:
5614 WARN(("Unexpected interrupt type! %d", InterruptType));
5615 break;
5616 default:
5617 WARN(("UNSUPPORTED interrupt type! %d", InterruptType));
5618 break;
5619 }
5620
5621 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
5622
5623 return Status;
5624}
5625
5626NTSTATUS
5627APIENTRY
5628DxgkDdiCreateOverlay(
5629 CONST HANDLE hAdapter,
5630 DXGKARG_CREATEOVERLAY *pCreateOverlay)
5631{
5632 LOGF(("ENTER, hAdapter(0x%p)", hAdapter));
5633
5634 NTSTATUS Status = STATUS_SUCCESS;
5635 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
5636 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)vboxWddmMemAllocZero(sizeof (VBOXWDDM_OVERLAY));
5637 Assert(pOverlay);
5638 if (pOverlay)
5639 {
5640 int rc = vboxVhwaHlpOverlayCreate(pDevExt, pCreateOverlay->VidPnSourceId, &pCreateOverlay->OverlayInfo, pOverlay);
5641 AssertRC(rc);
5642 if (RT_SUCCESS(rc))
5643 {
5644 pCreateOverlay->hOverlay = pOverlay;
5645 }
5646 else
5647 {
5648 vboxWddmMemFree(pOverlay);
5649 Status = STATUS_UNSUCCESSFUL;
5650 }
5651 }
5652 else
5653 Status = STATUS_NO_MEMORY;
5654
5655 LOGF(("LEAVE, hAdapter(0x%p)", hAdapter));
5656
5657 return Status;
5658}
5659
5660NTSTATUS
5661APIENTRY
5662DxgkDdiDestroyDevice(
5663 CONST HANDLE hDevice)
5664{
5665 /* DxgkDdiDestroyDevice should be made pageable. */
5666 PAGED_CODE();
5667
5668 LOGF(("ENTER, hDevice(0x%x)", hDevice));
5669
5670 vboxVDbgBreakFv();
5671
5672 vboxWddmMemFree(hDevice);
5673
5674 LOGF(("LEAVE, "));
5675
5676 return STATUS_SUCCESS;
5677}
5678
5679
5680
5681/*
5682 * DxgkDdiOpenAllocation
5683 */
5684NTSTATUS
5685APIENTRY
5686DxgkDdiOpenAllocation(
5687 CONST HANDLE hDevice,
5688 CONST DXGKARG_OPENALLOCATION *pOpenAllocation)
5689{
5690 /* DxgkDdiOpenAllocation should be made pageable. */
5691 PAGED_CODE();
5692
5693 LOGF(("ENTER, hDevice(0x%x)", hDevice));
5694
5695 vboxVDbgBreakFv();
5696
5697 NTSTATUS Status = STATUS_SUCCESS;
5698 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)hDevice;
5699 PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
5700 PVBOXWDDM_RCINFO pRcInfo = NULL;
5701 if (pOpenAllocation->PrivateDriverSize)
5702 {
5703 Assert(pOpenAllocation->pPrivateDriverData);
5704 if (pOpenAllocation->PrivateDriverSize == sizeof (VBOXWDDM_RCINFO))
5705 {
5706 pRcInfo = (PVBOXWDDM_RCINFO)pOpenAllocation->pPrivateDriverData;
5707 Assert(pRcInfo->cAllocInfos == pOpenAllocation->NumAllocations);
5708 }
5709 else
5710 {
5711 WARN(("Invalid PrivateDriverSize %d", pOpenAllocation->PrivateDriverSize));
5712 Status = STATUS_INVALID_PARAMETER;
5713 }
5714 }
5715
5716 if (Status == STATUS_SUCCESS)
5717 {
5718 UINT i = 0;
5719 for (; i < pOpenAllocation->NumAllocations; ++i)
5720 {
5721 DXGK_OPENALLOCATIONINFO* pInfo = &pOpenAllocation->pOpenAllocation[i];
5722 Assert(pInfo->PrivateDriverDataSize == sizeof (VBOXWDDM_ALLOCINFO));
5723 Assert(pInfo->pPrivateDriverData);
5724 PVBOXWDDM_ALLOCATION pAllocation = vboxWddmGetAllocationFromHandle(pDevExt, pInfo->hAllocation);
5725 if (!pAllocation)
5726 {
5727 WARN(("invalid handle"));
5728 Status = STATUS_INVALID_PARAMETER;
5729 break;
5730 }
5731
5732#ifdef DEBUG
5733 Assert(!pAllocation->fAssumedDeletion);
5734#endif
5735 if (pRcInfo)
5736 {
5737 Assert(pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC);
5738
5739 if (pInfo->PrivateDriverDataSize != sizeof (VBOXWDDM_ALLOCINFO)
5740 || !pInfo->pPrivateDriverData)
5741 {
5742 WARN(("invalid data size"));
5743 Status = STATUS_INVALID_PARAMETER;
5744 break;
5745 }
5746 PVBOXWDDM_ALLOCINFO pAllocInfo = (PVBOXWDDM_ALLOCINFO)pInfo->pPrivateDriverData;
5747
5748#ifdef VBOX_WITH_VIDEOHWACCEL
5749 if (pRcInfo->RcDesc.fFlags.Overlay)
5750 {
5751 /* we have queried host for some surface info, like pitch & size,
5752 * need to return it back to the UMD (User Mode Drive) */
5753 pAllocInfo->SurfDesc = pAllocation->AllocData.SurfDesc;
5754 /* success, just continue */
5755 }
5756#endif
5757 }
5758
5759 KIRQL OldIrql;
5760 PVBOXWDDM_OPENALLOCATION pOa;
5761 KeAcquireSpinLock(&pAllocation->OpenLock, &OldIrql);
5762 pOa = VBoxWddmOaSearchLocked(pDevice, pAllocation);
5763 if (pOa)
5764 {
5765 ++pOa->cOpens;
5766 ++pAllocation->cOpens;
5767 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
5768 }
5769 else
5770 {
5771 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
5772 pOa = (PVBOXWDDM_OPENALLOCATION)vboxWddmMemAllocZero(sizeof (VBOXWDDM_OPENALLOCATION));
5773 if (!pOa)
5774 {
5775 WARN(("failed to allocation alloc info"));
5776 Status = STATUS_INSUFFICIENT_RESOURCES;
5777 break;
5778 }
5779
5780 pOa->hAllocation = pInfo->hAllocation;
5781 pOa->pAllocation = pAllocation;
5782 pOa->pDevice = pDevice;
5783 pOa->cOpens = 1;
5784
5785 PVBOXWDDM_OPENALLOCATION pConcurrentOa;
5786 KeAcquireSpinLock(&pAllocation->OpenLock, &OldIrql);
5787 pConcurrentOa = VBoxWddmOaSearchLocked(pDevice, pAllocation);
5788 if (!pConcurrentOa)
5789 InsertHeadList(&pAllocation->OpenList, &pOa->ListEntry);
5790 else
5791 ++pConcurrentOa->cOpens;
5792 ++pAllocation->cOpens;
5793 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
5794 if (pConcurrentOa)
5795 {
5796 vboxWddmMemFree(pOa);
5797 pOa = pConcurrentOa;
5798 }
5799 }
5800
5801 pInfo->hDeviceSpecificAllocation = pOa;
5802 }
5803
5804 if (Status != STATUS_SUCCESS)
5805 {
5806 for (UINT j = 0; j < i; ++j)
5807 {
5808 DXGK_OPENALLOCATIONINFO* pInfo2Free = &pOpenAllocation->pOpenAllocation[j];
5809 PVBOXWDDM_OPENALLOCATION pOa2Free = (PVBOXWDDM_OPENALLOCATION)pInfo2Free->hDeviceSpecificAllocation;
5810 VBoxWddmOaRelease(pOa2Free);
5811 }
5812 }
5813 }
5814 LOGF(("LEAVE, hDevice(0x%x)", hDevice));
5815
5816 return Status;
5817}
5818
5819NTSTATUS
5820APIENTRY
5821DxgkDdiCloseAllocation(
5822 CONST HANDLE hDevice,
5823 CONST DXGKARG_CLOSEALLOCATION* pCloseAllocation)
5824{
5825 RT_NOREF(hDevice);
5826 /* DxgkDdiCloseAllocation should be made pageable. */
5827 PAGED_CODE();
5828
5829 LOGF(("ENTER, hDevice(0x%x)", hDevice));
5830
5831 vboxVDbgBreakFv();
5832
5833 for (UINT i = 0; i < pCloseAllocation->NumAllocations; ++i)
5834 {
5835 PVBOXWDDM_OPENALLOCATION pOa2Free = (PVBOXWDDM_OPENALLOCATION)pCloseAllocation->pOpenHandleList[i];
5836 PVBOXWDDM_ALLOCATION pAllocation = pOa2Free->pAllocation;
5837 Assert(pAllocation->cShRcRefs >= pOa2Free->cShRcRefs);
5838 pAllocation->cShRcRefs -= pOa2Free->cShRcRefs;
5839 VBoxWddmOaRelease(pOa2Free);
5840 }
5841
5842 LOGF(("LEAVE, hDevice(0x%x)", hDevice));
5843
5844 return STATUS_SUCCESS;
5845}
5846
5847#ifdef VBOX_WITH_CROGL
5848static NTSTATUS
5849APIENTRY
5850DxgkDdiRenderNew(
5851 CONST HANDLE hContext,
5852 DXGKARG_RENDER *pRender)
5853{
5854 RT_NOREF(hContext);
5855// LOGF(("ENTER, hContext(0x%x)", hContext));
5856 vboxVDbgBreakF();
5857
5858 if (pRender->DmaBufferPrivateDataSize < sizeof (VBOXCMDVBVA_HDR))
5859 {
5860 WARN(("pRender->DmaBufferPrivateDataSize(%d) < sizeof VBOXCMDVBVA_HDR (%d)",
5861 pRender->DmaBufferPrivateDataSize , sizeof (VBOXCMDVBVA_HDR)));
5862 /** @todo can this actually happen? what status to return? */
5863 return STATUS_INVALID_PARAMETER;
5864 }
5865 if (pRender->CommandLength < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
5866 {
5867 WARN(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_BASEHDR (%d)",
5868 pRender->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
5869 return STATUS_INVALID_PARAMETER;
5870 }
5871 if (pRender->PatchLocationListOutSize < pRender->AllocationListSize)
5872 {
5873 WARN(("pRender->PatchLocationListOutSize(%d) < pRender->AllocationListSize(%d)",
5874 pRender->PatchLocationListOutSize, pRender->AllocationListSize));
5875 return STATUS_INVALID_PARAMETER;
5876 }
5877
5878 NTSTATUS Status = STATUS_SUCCESS;
5879
5880 __try
5881 {
5882 PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR pInputHdr = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)pRender->pCommand;
5883
5884 uint32_t cbBuffer = 0;
5885 uint32_t cbPrivateData = 0;
5886 uint32_t cbCmd = 0;
5887 VBOXCMDVBVA_HDR* pCmd = (VBOXCMDVBVA_HDR*)pRender->pDmaBufferPrivateData;
5888
5889 switch (pInputHdr->enmCmd)
5890 {
5891 case VBOXVDMACMD_TYPE_CHROMIUM_CMD:
5892 {
5893 if (pRender->AllocationListSize >= (UINT32_MAX - RT_UOFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD, aBufInfos))/ RT_SIZEOFMEMB(VBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD, aBufInfos[0]))
5894 {
5895 WARN(("Invalid AllocationListSize %d", pRender->AllocationListSize));
5896 return STATUS_INVALID_PARAMETER;
5897 }
5898
5899 if (pRender->CommandLength != RT_UOFFSETOF_DYN(VBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD, aBufInfos[pRender->AllocationListSize]))
5900 {
5901 WARN(("pRender->CommandLength (%d) != RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD, aBufInfos[pRender->AllocationListSize](%d)",
5902 pRender->CommandLength, (int)RT_UOFFSETOF_DYN(VBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD, aBufInfos[pRender->AllocationListSize])));
5903 return STATUS_INVALID_PARAMETER;
5904 }
5905
5906 if (pRender->AllocationListSize >= (UINT32_MAX - RT_UOFFSETOF(VBOXCMDVBVA_CRCMD, Cmd.aBuffers))/ RT_SIZEOFMEMB(VBOXCMDVBVA_CRCMD, Cmd.aBuffers[0]))
5907 {
5908 WARN(("Invalid AllocationListSize %d", pRender->AllocationListSize));
5909 return STATUS_INVALID_PARAMETER;
5910 }
5911
5912 cbBuffer = VBOXWDDM_DUMMY_DMABUFFER_SIZE;
5913 cbPrivateData = RT_UOFFSETOF_DYN(VBOXCMDVBVA_CRCMD, Cmd.aBuffers[pRender->AllocationListSize]);
5914
5915 if (pRender->DmaBufferPrivateDataSize < cbPrivateData)
5916 {
5917 WARN(("pRender->DmaBufferPrivateDataSize too small %d, requested %d", pRender->DmaBufferPrivateDataSize, cbPrivateData));
5918 return STATUS_INVALID_PARAMETER;
5919 }
5920
5921 if (pRender->DmaSize < cbBuffer)
5922 {
5923 WARN(("dma buffer %d too small", pRender->DmaSize));
5924 return STATUS_INVALID_PARAMETER;
5925 }
5926
5927 // Assert(pRender->PatchLocationListOutSize == pRender->AllocationListSize);
5928
5929 if (pRender->PatchLocationListOutSize < pRender->AllocationListSize)
5930 {
5931 WARN(("pRender->PatchLocationListOutSize too small %d, requested %d", pRender->PatchLocationListOutSize, pRender->AllocationListSize));
5932 return STATUS_INVALID_PARAMETER;
5933 }
5934
5935 PVBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD pUmCmd = (PVBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD)pInputHdr;
5936 VBOXCMDVBVA_CRCMD* pChromiumCmd = (VBOXCMDVBVA_CRCMD*)pRender->pDmaBufferPrivateData;
5937
5938 pChromiumCmd->Hdr.u8OpCode = VBOXCMDVBVA_OPTYPE_CRCMD;
5939 pChromiumCmd->Hdr.u8Flags = 0;
5940 pChromiumCmd->Cmd.cBuffers = pRender->AllocationListSize;
5941
5942 DXGK_ALLOCATIONLIST *pAllocationList = pRender->pAllocationList;
5943 VBOXCMDVBVA_CRCMD_BUFFER *pSubmInfo = pChromiumCmd->Cmd.aBuffers;
5944 PVBOXWDDM_UHGSMI_BUFFER_UI_SUBMIT_INFO pSubmUmInfo = pUmCmd->aBufInfos;
5945
5946 for (UINT i = 0; i < pRender->AllocationListSize; ++i, ++pRender->pPatchLocationListOut, ++pAllocationList, ++pSubmInfo, ++pSubmUmInfo)
5947 {
5948 VBOXWDDM_UHGSMI_BUFFER_UI_SUBMIT_INFO SubmUmInfo = *pSubmUmInfo;
5949 D3DDDI_PATCHLOCATIONLIST* pPLL = pRender->pPatchLocationListOut;
5950 PVBOXWDDM_ALLOCATION pAlloc = vboxWddmGetAllocationFromAllocList(pAllocationList);
5951 if (SubmUmInfo.offData >= pAlloc->AllocData.SurfDesc.cbSize
5952 || SubmUmInfo.cbData > pAlloc->AllocData.SurfDesc.cbSize
5953 || SubmUmInfo.offData + SubmUmInfo.cbData > pAlloc->AllocData.SurfDesc.cbSize)
5954 {
5955 WARN(("invalid data"));
5956 return STATUS_INVALID_PARAMETER;
5957 }
5958
5959 memset(pPLL, 0, sizeof (*pPLL));
5960
5961 if (pAllocationList->SegmentId)
5962 pSubmInfo->offBuffer = pAllocationList->PhysicalAddress.LowPart + SubmUmInfo.offData;
5963
5964 pSubmInfo->cbBuffer = SubmUmInfo.cbData;
5965
5966 pPLL->AllocationIndex = i;
5967 pPLL->PatchOffset = RT_UOFFSETOF_DYN(VBOXCMDVBVA_CRCMD, Cmd.aBuffers[i].offBuffer);
5968 pPLL->AllocationOffset = SubmUmInfo.offData;
5969 }
5970
5971 cbCmd = cbPrivateData;
5972
5973 break;
5974 }
5975 case VBOXVDMACMD_TYPE_DMA_NOP:
5976 {
5977 cbPrivateData = sizeof (VBOXCMDVBVA_HDR);
5978 cbBuffer = VBOXWDDM_DUMMY_DMABUFFER_SIZE;
5979
5980 if (pRender->DmaBufferPrivateDataSize < cbPrivateData)
5981 {
5982 WARN(("pRender->DmaBufferPrivateDataSize too small %d, requested %d", pRender->DmaBufferPrivateDataSize, cbPrivateData));
5983 return STATUS_INVALID_PARAMETER;
5984 }
5985
5986 if (pRender->DmaSize < cbBuffer)
5987 {
5988 WARN(("dma buffer %d too small", pRender->DmaSize));
5989 return STATUS_INVALID_PARAMETER;
5990 }
5991
5992 pCmd->u8OpCode = VBOXCMDVBVA_OPTYPE_NOPCMD;
5993 pCmd->u8Flags = 0;
5994
5995 for (UINT i = 0; i < pRender->AllocationListSize; ++i, ++pRender->pPatchLocationListOut)
5996 {
5997 D3DDDI_PATCHLOCATIONLIST* pPLL = pRender->pPatchLocationListOut;
5998 memset(pPLL, 0, sizeof (*pPLL));
5999 pPLL->AllocationIndex = i;
6000 pPLL->PatchOffset = ~0UL;
6001 pPLL->AllocationOffset = 0;
6002 }
6003
6004 cbCmd = cbPrivateData;
6005
6006 break;
6007 }
6008 default:
6009 {
6010 WARN(("unsupported render command %d", pInputHdr->enmCmd));
6011 return STATUS_INVALID_PARAMETER;
6012 }
6013 }
6014
6015 Assert(cbPrivateData >= sizeof (VBOXCMDVBVA_HDR));
6016 pRender->pDmaBufferPrivateData = ((uint8_t*)pRender->pDmaBufferPrivateData) + cbPrivateData;
6017 pRender->pDmaBuffer = ((uint8_t*)pRender->pDmaBuffer) + cbBuffer;
6018
6019 pCmd->u8State = VBOXCMDVBVA_STATE_SUBMITTED;
6020 pCmd->u2.complexCmdEl.u16CbCmdHost = cbPrivateData;
6021 pCmd->u2.complexCmdEl.u16CbCmdGuest = cbBuffer;
6022 }
6023 __except (EXCEPTION_EXECUTE_HANDLER)
6024 {
6025 Status = STATUS_INVALID_PARAMETER;
6026 WARN(("invalid parameter"));
6027 }
6028// LOGF(("LEAVE, hContext(0x%x)", hContext));
6029
6030 return Status;
6031}
6032#endif
6033
6034static void vboxWddmPatchLocationInit(D3DDDI_PATCHLOCATIONLIST *pPatchLocationListOut, UINT idx, UINT offPatch)
6035{
6036 memset(pPatchLocationListOut, 0, sizeof (*pPatchLocationListOut));
6037 pPatchLocationListOut->AllocationIndex = idx;
6038 pPatchLocationListOut->PatchOffset = offPatch;
6039}
6040
6041static NTSTATUS
6042APIENTRY
6043DxgkDdiRenderLegacy(
6044 CONST HANDLE hContext,
6045 DXGKARG_RENDER *pRender)
6046{
6047 RT_NOREF(hContext);
6048// LOGF(("ENTER, hContext(0x%x)", hContext));
6049
6050 if (pRender->DmaBufferPrivateDataSize < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
6051 {
6052 WARN(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_BASEHDR (%d)",
6053 pRender->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
6054 return STATUS_INVALID_PARAMETER;
6055 }
6056 if (pRender->CommandLength < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
6057 {
6058 WARN(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_BASEHDR (%d)",
6059 pRender->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
6060 return STATUS_INVALID_PARAMETER;
6061 }
6062 if (pRender->DmaSize < pRender->CommandLength)
6063 {
6064 WARN(("pRender->DmaSize(%d) < pRender->CommandLength(%d)",
6065 pRender->DmaSize, pRender->CommandLength));
6066 return STATUS_INVALID_PARAMETER;
6067 }
6068 if (pRender->PatchLocationListOutSize < pRender->PatchLocationListInSize)
6069 {
6070 WARN(("pRender->PatchLocationListOutSize(%d) < pRender->PatchLocationListInSize(%d)",
6071 pRender->PatchLocationListOutSize, pRender->PatchLocationListInSize));
6072 return STATUS_INVALID_PARAMETER;
6073 }
6074 if (pRender->AllocationListSize != pRender->PatchLocationListInSize)
6075 {
6076 WARN(("pRender->AllocationListSize(%d) != pRender->PatchLocationListInSize(%d)",
6077 pRender->AllocationListSize, pRender->PatchLocationListInSize));
6078 return STATUS_INVALID_PARAMETER;
6079 }
6080
6081 NTSTATUS Status = STATUS_SUCCESS;
6082
6083 __try
6084 {
6085 PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR pInputHdr = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)pRender->pCommand;
6086 switch (pInputHdr->enmCmd)
6087 {
6088 case VBOXVDMACMD_TYPE_DMA_NOP:
6089 {
6090 PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR pPrivateData = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)pRender->pDmaBufferPrivateData;
6091 pPrivateData->enmCmd = VBOXVDMACMD_TYPE_DMA_NOP;
6092 pRender->pDmaBufferPrivateData = (uint8_t*)pRender->pDmaBufferPrivateData + sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR);
6093 pRender->pDmaBuffer = ((uint8_t*)pRender->pDmaBuffer) + pRender->CommandLength;
6094 for (UINT i = 0; i < pRender->PatchLocationListInSize; ++i)
6095 {
6096 UINT offPatch = i * 4;
6097 if (offPatch + 4 > pRender->CommandLength)
6098 {
6099 WARN(("wrong offPatch"));
6100 return STATUS_INVALID_PARAMETER;
6101 }
6102 if (offPatch != pRender->pPatchLocationListIn[i].PatchOffset)
6103 {
6104 WARN(("wrong PatchOffset"));
6105 return STATUS_INVALID_PARAMETER;
6106 }
6107 if (i != pRender->pPatchLocationListIn[i].AllocationIndex)
6108 {
6109 WARN(("wrong AllocationIndex"));
6110 return STATUS_INVALID_PARAMETER;
6111 }
6112 vboxWddmPatchLocationInit(&pRender->pPatchLocationListOut[i], i, offPatch);
6113 }
6114 break;
6115 }
6116 default:
6117 {
6118 WARN(("unsupported command %d", pInputHdr->enmCmd));
6119 return STATUS_INVALID_PARAMETER;
6120 }
6121 }
6122 }
6123 __except (EXCEPTION_EXECUTE_HANDLER)
6124 {
6125 Status = STATUS_INVALID_PARAMETER;
6126 WARN(("invalid parameter"));
6127 }
6128// LOGF(("LEAVE, hContext(0x%x)", hContext));
6129
6130 return Status;
6131}
6132
6133#define VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE() (VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_PRESENT_BLT))
6134#define VBOXVDMACMD_DMA_PRESENT_BLT_SIZE(_c) (VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects[_c]))
6135
6136#ifdef VBOX_WITH_VDMA
6137DECLINLINE(VOID) vboxWddmRectlFromRect(const RECT *pRect, PVBOXVDMA_RECTL pRectl)
6138{
6139 pRectl->left = (int16_t)pRect->left;
6140 pRectl->width = (uint16_t)(pRect->right - pRect->left);
6141 pRectl->top = (int16_t)pRect->top;
6142 pRectl->height = (uint16_t)(pRect->bottom - pRect->top);
6143}
6144
6145DECLINLINE(VBOXVDMA_PIXEL_FORMAT) vboxWddmFromPixFormat(D3DDDIFORMAT format)
6146{
6147 return (VBOXVDMA_PIXEL_FORMAT)format;
6148}
6149
6150DECLINLINE(VOID) vboxWddmSurfDescFromAllocation(PVBOXWDDM_ALLOCATION pAllocation, PVBOXVDMA_SURF_DESC pDesc)
6151{
6152 pDesc->width = pAllocation->AllocData.SurfDesc.width;
6153 pDesc->height = pAllocation->AllocData.SurfDesc.height;
6154 pDesc->format = vboxWddmFromPixFormat(pAllocation->AllocData.SurfDesc.format);
6155 pDesc->bpp = pAllocation->AllocData.SurfDesc.bpp;
6156 pDesc->pitch = pAllocation->AllocData.SurfDesc.pitch;
6157 pDesc->fFlags = 0;
6158}
6159#endif
6160
6161DECLINLINE(BOOLEAN) vboxWddmPixFormatConversionSupported(D3DDDIFORMAT From, D3DDDIFORMAT To)
6162{
6163 Assert(From != D3DDDIFMT_UNKNOWN);
6164 Assert(To != D3DDDIFMT_UNKNOWN);
6165 Assert(From == To);
6166 return From == To;
6167}
6168
6169#ifdef VBOX_WITH_CROGL
6170
6171DECLINLINE(void) VBoxCVDdiFillAllocDescHostID(VBOXCMDVBVA_ALLOCDESC *pDesc, const VBOXWDDM_ALLOCATION *pAlloc)
6172{
6173 pDesc->Info.u.id = pAlloc->AllocData.hostID;
6174 /* we do not care about wdth and height, zero them up though */
6175 pDesc->u16Width = 0;
6176 pDesc->u16Height = 0;
6177}
6178
6179DECLINLINE(void) VBoxCVDdiFillAllocInfoOffVRAM(VBOXCMDVBVA_ALLOCINFO *pInfo, const DXGK_ALLOCATIONLIST *pList)
6180{
6181 Assert(!pList->PhysicalAddress.HighPart);
6182 pInfo->u.offVRAM = pList->PhysicalAddress.LowPart;
6183}
6184
6185DECLINLINE(void) VBoxCVDdiFillAllocDescOffVRAM(VBOXCMDVBVA_ALLOCDESC *pDesc, const VBOXWDDM_ALLOCATION *pAlloc, const DXGK_ALLOCATIONLIST *pList)
6186{
6187 VBoxCVDdiFillAllocInfoOffVRAM(&pDesc->Info, pList);
6188 pDesc->u16Width = (uint16_t)pAlloc->AllocData.SurfDesc.width;
6189 pDesc->u16Height = (uint16_t)pAlloc->AllocData.SurfDesc.height;
6190}
6191
6192static NTSTATUS vboxWddmCmCmdBltIdNotIdFill(VBOXCMDVBVA_BLT_HDR *pBltHdr, const VBOXWDDM_ALLOCATION *pIdAlloc, const VBOXWDDM_ALLOCATION *pAlloc, const DXGK_ALLOCATIONLIST *pList,
6193 BOOLEAN fToId, uint32_t *poffPatch, uint32_t *poffRects)
6194{
6195 uint8_t fFlags;
6196 Assert(pIdAlloc->AllocData.hostID);
6197 Assert(!pAlloc->AllocData.hostID);
6198
6199 D3DDDIFORMAT enmFormat = vboxWddmFmtNoAlphaFormat(pAlloc->AllocData.SurfDesc.format);
6200 if (enmFormat != D3DDDIFMT_X8R8G8B8)
6201 {
6202 WARN(("unsupported format"));
6203 return STATUS_INVALID_PARAMETER;
6204 }
6205
6206 if (pIdAlloc->AllocData.SurfDesc.width == pAlloc->AllocData.SurfDesc.width
6207 && pIdAlloc->AllocData.SurfDesc.height == pAlloc->AllocData.SurfDesc.height)
6208 {
6209 fFlags = VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID | VBOXCMDVBVA_OPF_OPERAND2_ISID;
6210 VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *pBlt = (VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID*)pBltHdr;
6211 VBoxCVDdiFillAllocInfoOffVRAM(&pBlt->alloc, pList);
6212 pBlt->id = pIdAlloc->AllocData.hostID;
6213 *poffPatch = RT_UOFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, alloc.u.offVRAM);
6214 *poffRects = RT_UOFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects);
6215 }
6216 else
6217 {
6218 fFlags = VBOXCMDVBVA_OPF_BLT_TYPE_SAMEDIM_A8R8G8B8 | VBOXCMDVBVA_OPF_OPERAND2_ISID;
6219 VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8 *pBlt = (VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8*)pBltHdr;
6220 VBoxCVDdiFillAllocDescOffVRAM(&pBlt->alloc1, pAlloc, pList);
6221 pBlt->info2.u.id = pIdAlloc->AllocData.hostID;
6222 *poffPatch = RT_UOFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, alloc1.Info.u.offVRAM);
6223 *poffRects = RT_UOFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, aRects);
6224 }
6225
6226 if (fToId)
6227 fFlags |= VBOXCMDVBVA_OPF_BLT_DIR_IN_2;
6228
6229 pBltHdr->Hdr.u8Flags |= fFlags;
6230 return STATUS_SUCCESS;
6231}
6232
6233static NTSTATUS vboxWddmCmCmdBltNotIdNotIdFill(VBOXCMDVBVA_BLT_HDR *pBltHdr, const VBOXWDDM_ALLOCATION *pSrcAlloc, const DXGK_ALLOCATIONLIST *pSrcList,
6234 const VBOXWDDM_ALLOCATION *pDstAlloc, const DXGK_ALLOCATIONLIST *pDstList,
6235 uint32_t *poffSrcPatch, uint32_t *poffDstPatch, uint32_t *poffRects)
6236{
6237 if (pDstAlloc->AllocData.SurfDesc.width == pSrcAlloc->AllocData.SurfDesc.width
6238 && pDstAlloc->AllocData.SurfDesc.height == pSrcAlloc->AllocData.SurfDesc.height)
6239 {
6240 pBltHdr->Hdr.u8Flags |= VBOXCMDVBVA_OPF_BLT_TYPE_SAMEDIM_A8R8G8B8;
6241 VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8 *pBlt = (VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8*)pBltHdr;
6242 VBoxCVDdiFillAllocDescOffVRAM(&pBlt->alloc1, pDstAlloc, pDstList);
6243 VBoxCVDdiFillAllocInfoOffVRAM(&pBlt->info2, pSrcList);
6244 *poffDstPatch = RT_UOFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, alloc1.Info.u.offVRAM);
6245 *poffSrcPatch = RT_UOFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, info2.u.offVRAM);
6246 *poffRects = RT_UOFFSETOF(VBOXCMDVBVA_BLT_SAMEDIM_A8R8G8B8, aRects);
6247 }
6248 else
6249 {
6250 pBltHdr->Hdr.u8Flags |= VBOXCMDVBVA_OPF_BLT_TYPE_GENERIC_A8R8G8B8;
6251 VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8 *pBlt = (VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8*)pBltHdr;
6252 VBoxCVDdiFillAllocDescOffVRAM(&pBlt->alloc1, pDstAlloc, pDstList);
6253 VBoxCVDdiFillAllocDescOffVRAM(&pBlt->alloc2, pSrcAlloc, pSrcList);
6254 *poffDstPatch = RT_UOFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, alloc1.Info.u.offVRAM);
6255 *poffSrcPatch = RT_UOFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, alloc2.Info.u.offVRAM);
6256 *poffRects = RT_UOFFSETOF(VBOXCMDVBVA_BLT_GENERIC_A8R8G8B8, aRects);
6257 }
6258 return STATUS_SUCCESS;
6259}
6260/**
6261 * DxgkDdiPresent
6262 */
6263static NTSTATUS
6264APIENTRY
6265DxgkDdiPresentNew(
6266 CONST HANDLE hContext,
6267 DXGKARG_PRESENT *pPresent)
6268{
6269 RT_NOREF(hContext);
6270 PAGED_CODE();
6271
6272// LOGF(("ENTER, hContext(0x%x)", hContext));
6273
6274 vboxVDbgBreakFv();
6275
6276#ifdef VBOX_STRICT
6277 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
6278 PVBOXWDDM_DEVICE pDevice = pContext->pDevice;
6279 PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
6280#endif
6281 uint32_t cbBuffer = 0;
6282 uint32_t cbPrivateData = 0;
6283
6284 if (pPresent->DmaBufferPrivateDataSize < sizeof (VBOXCMDVBVA_HDR))
6285 {
6286 WARN(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXCMDVBVA_HDR (%d)", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXCMDVBVA_HDR)));
6287 /** @todo can this actually happen? what status to return? */
6288 return STATUS_INVALID_PARAMETER;
6289 }
6290
6291 VBOXCMDVBVA_HDR* pHdr = (VBOXCMDVBVA_HDR*)pPresent->pDmaBufferPrivateData;
6292
6293 UINT u32SrcPatch = ~0UL;
6294 UINT u32DstPatch = ~0UL;
6295 BOOLEAN fPatchSrc = false;
6296 BOOLEAN fPatchDst = false;
6297 VBOXCMDVBVA_RECT *paRects = NULL;
6298
6299 if (pPresent->DmaSize < VBOXWDDM_DUMMY_DMABUFFER_SIZE)
6300 {
6301 WARN(("Present->DmaSize(%d) < VBOXWDDM_DUMMY_DMABUFFER_SIZE (%d)", pPresent->DmaSize , VBOXWDDM_DUMMY_DMABUFFER_SIZE));
6302 /** @todo can this actually happen? what status to return? */
6303 return STATUS_INVALID_PARAMETER;
6304 }
6305
6306#ifdef VBOX_WDDM_DUMP_REGIONS_ON_PRESENT
6307 LogRel(("%s: [%ld, %ld, %ld, %ld] -> [%ld, %ld, %ld, %ld] (SubRectCnt=%u)\n",
6308 pPresent->Flags.Blt ? "Blt" : (pPresent->Flags.Flip ? "Flip" : (pPresent->Flags.ColorFill ? "ColorFill" : "Unknown OP")),
6309 pPresent->SrcRect.left, pPresent->SrcRect.top, pPresent->SrcRect.right, pPresent->SrcRect.bottom,
6310 pPresent->DstRect.left, pPresent->DstRect.top, pPresent->DstRect.right, pPresent->DstRect.bottom,
6311 pPresent->SubRectCnt));
6312 for (unsigned int i = 0; i < pPresent->SubRectCnt; i++)
6313 LogRel(("\tsub#%u = [%ld, %ld, %ld, %ld]\n", i, pPresent->pDstSubRects[i].left, pPresent->pDstSubRects[i].top, pPresent->pDstSubRects[i].right, pPresent->pDstSubRects[i].bottom));
6314#endif
6315
6316 if (pPresent->Flags.Blt)
6317 {
6318 Assert(pPresent->Flags.Value == 1); /* only Blt is set, we do not support anything else for now */
6319 DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
6320 DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
6321 PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pSrc);
6322 if (!pSrcAlloc)
6323 {
6324 /* this should not happen actually */
6325 WARN(("failed to get Src Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
6326 return STATUS_INVALID_HANDLE;
6327 }
6328
6329 PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDst);
6330 if (!pDstAlloc)
6331 {
6332 /* this should not happen actually */
6333 WARN(("failed to get Dst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
6334 return STATUS_INVALID_HANDLE;
6335 }
6336
6337 fPatchSrc = TRUE;
6338 fPatchDst = TRUE;
6339
6340 BOOLEAN fDstPrimary = (!pDstAlloc->AllocData.hostID
6341 && pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
6342 && pDstAlloc->bAssigned);
6343 BOOLEAN fSrcPrimary = (!pSrcAlloc->AllocData.hostID
6344 && pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
6345 && pSrcAlloc->bAssigned);
6346
6347 pHdr->u8OpCode = VBOXCMDVBVA_OPTYPE_BLT;
6348 pHdr->u8Flags = 0;
6349
6350 VBOXCMDVBVA_BLT_HDR *pBltHdr = (VBOXCMDVBVA_BLT_HDR*)pHdr;
6351 pBltHdr->Pos.x = (int16_t)(pPresent->DstRect.left - pPresent->SrcRect.left);
6352 pBltHdr->Pos.y = (int16_t)(pPresent->DstRect.top - pPresent->SrcRect.top);
6353
6354 if (pPresent->DmaBufferPrivateDataSize < VBOXCMDVBVA_SIZEOF_BLTSTRUCT_MAX)
6355 {
6356 WARN(("Present->DmaBufferPrivateDataSize(%d) < (%d)", pPresent->DmaBufferPrivateDataSize , VBOXCMDVBVA_SIZEOF_BLTSTRUCT_MAX));
6357 /** @todo can this actually happen? what status to return? */
6358 return STATUS_INVALID_PARAMETER;
6359 }
6360
6361 if (pSrcAlloc->AllocData.hostID)
6362 {
6363 if (pDstAlloc->AllocData.hostID)
6364 {
6365 VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *pBlt = (VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID*)pBltHdr;
6366 pHdr->u8Flags |= VBOXCMDVBVA_OPF_BLT_TYPE_OFFPRIMSZFMT_OR_ID | VBOXCMDVBVA_OPF_OPERAND1_ISID | VBOXCMDVBVA_OPF_OPERAND2_ISID;
6367 pBlt->id = pDstAlloc->AllocData.hostID;
6368 pBlt->alloc.u.id = pSrcAlloc->AllocData.hostID;
6369 cbPrivateData = RT_UOFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects);
6370 }
6371 else
6372 {
6373 NTSTATUS Status = vboxWddmCmCmdBltIdNotIdFill(pBltHdr, pSrcAlloc, pDstAlloc, pDst, FALSE, &u32DstPatch, &cbPrivateData);
6374 if (!NT_SUCCESS(Status))
6375 {
6376 WARN(("vboxWddmCmCmdBltIdNotIdFill failed, %#x", Status));
6377 return Status;
6378 }
6379 }
6380 }
6381 else
6382 {
6383 if (pDstAlloc->AllocData.hostID)
6384 {
6385 NTSTATUS Status = vboxWddmCmCmdBltIdNotIdFill(pBltHdr, pDstAlloc, pSrcAlloc, pSrc, TRUE, &u32SrcPatch, &cbPrivateData);
6386 if (!NT_SUCCESS(Status))
6387 {
6388 WARN(("vboxWddmCmCmdBltIdNotIdFill failed, %#x", Status));
6389 return Status;
6390 }
6391 }
6392 else
6393 {
6394 vboxWddmCmCmdBltNotIdNotIdFill(pBltHdr, pSrcAlloc, pSrc, pDstAlloc, pDst, &u32SrcPatch, &u32DstPatch, &cbPrivateData);
6395 }
6396 }
6397
6398 if (fDstPrimary)
6399 pBltHdr->Hdr.u.u8PrimaryID = (uint8_t)pDstAlloc->AllocData.SurfDesc.VidPnSourceId;
6400 else if (fSrcPrimary)
6401 {
6402 pBltHdr->Hdr.u8Flags |= VBOXCMDVBVA_OPF_PRIMARY_HINT_SRC;
6403 pBltHdr->Hdr.u.u8PrimaryID = (uint8_t)pSrcAlloc->AllocData.SurfDesc.VidPnSourceId;
6404 }
6405 else
6406 pBltHdr->Hdr.u.u8PrimaryID = 0xff;
6407
6408 paRects = (VBOXCMDVBVA_RECT*)(((uint8_t*)pPresent->pDmaBufferPrivateData) + cbPrivateData);
6409 cbBuffer = VBOXWDDM_DUMMY_DMABUFFER_SIZE;
6410 }
6411 else if (pPresent->Flags.Flip)
6412 {
6413 if (pPresent->DmaBufferPrivateDataSize < sizeof (VBOXCMDVBVA_FLIP))
6414 {
6415 WARN(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXCMDVBVA_FLIP (%d)", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXCMDVBVA_FLIP)));
6416 /** @todo can this actually happen? what status to return? */
6417 return STATUS_INVALID_PARAMETER;
6418 }
6419
6420 fPatchSrc = TRUE;
6421
6422 Assert(pPresent->Flags.Value == 4); /* only Blt is set, we do not support anything else for now */
6423 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D);
6424 DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
6425 PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pSrc);
6426
6427 if (!pSrcAlloc)
6428 {
6429 /* this should not happen actually */
6430 WARN(("failed to get pSrc Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
6431 return STATUS_INVALID_HANDLE;
6432 }
6433
6434 Assert(pDevExt->cContexts3D);
6435 pHdr->u8OpCode = VBOXCMDVBVA_OPTYPE_FLIP;
6436 Assert((UINT)pSrcAlloc->AllocData.SurfDesc.VidPnSourceId < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
6437 pHdr->u.u8PrimaryID = pSrcAlloc->AllocData.SurfDesc.VidPnSourceId;
6438 VBOXCMDVBVA_FLIP *pFlip = (VBOXCMDVBVA_FLIP*)pHdr;
6439
6440 if (pSrcAlloc->AllocData.hostID)
6441 {
6442 pHdr->u8Flags = VBOXCMDVBVA_OPF_OPERAND1_ISID;
6443 pFlip->src.u.id = pSrcAlloc->AllocData.hostID;
6444 }
6445 else
6446 {
6447 WARN(("VBoxCVDdiFillAllocInfo reported no host id for flip!"));
6448 pHdr->u8Flags = 0;
6449 VBoxCVDdiFillAllocInfoOffVRAM(&pFlip->src, pSrc);
6450 u32SrcPatch = RT_UOFFSETOF(VBOXCMDVBVA_FLIP, src.u.offVRAM);
6451 }
6452
6453 cbBuffer = VBOXWDDM_DUMMY_DMABUFFER_SIZE;
6454 paRects = pFlip->aRects;
6455 cbPrivateData = VBOXCMDVBVA_SIZEOF_FLIPSTRUCT_MIN;
6456 }
6457 else if (pPresent->Flags.ColorFill)
6458 {
6459#ifdef DEBUG_misha
6460 WARN(("test color fill!"));
6461#endif
6462
6463 fPatchDst = TRUE;
6464
6465 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D);
6466 Assert(pPresent->Flags.Value == 2); /* only ColorFill is set, we do not support anything else for now */
6467 DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
6468 PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDst);
6469 if (!pDstAlloc)
6470 {
6471 /* this should not happen actually */
6472 WARN(("failed to get pDst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
6473 return STATUS_INVALID_HANDLE;
6474 }
6475
6476 if (pDstAlloc->AllocData.hostID)
6477 {
6478 WARN(("color fill present for texid not supported"));
6479 pHdr->u8OpCode = VBOXCMDVBVA_OPTYPE_NOPCMD;
6480 pHdr->u8Flags = 0;
6481 pHdr->u8State = VBOXCMDVBVA_STATE_SUBMITTED;
6482 cbPrivateData = sizeof (VBOXCMDVBVA_HDR);
6483 cbBuffer = VBOXWDDM_DUMMY_DMABUFFER_SIZE;
6484 }
6485 else
6486 {
6487 BOOLEAN fDstPrimary = (!pDstAlloc->AllocData.hostID
6488 && pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
6489 && pDstAlloc->bAssigned);
6490
6491 if (pPresent->DmaBufferPrivateDataSize < VBOXCMDVBVA_SIZEOF_CLRFILLSTRUCT_MAX)
6492 {
6493 WARN(("Present->DmaBufferPrivateDataSize(%d) < VBOXCMDVBVA_SIZEOF_CLRFILLSTRUCT_MAX (%d)", pPresent->DmaBufferPrivateDataSize , VBOXCMDVBVA_SIZEOF_CLRFILLSTRUCT_MAX));
6494 /** @todo can this actually happen? what status to return? */
6495 return STATUS_INVALID_PARAMETER;
6496 }
6497
6498 VBOXCMDVBVA_CLRFILL_HDR *pClrFillHdr = (VBOXCMDVBVA_CLRFILL_HDR*)pHdr;
6499
6500 pClrFillHdr->Hdr.u8OpCode = VBOXCMDVBVA_OPTYPE_CLRFILL;
6501 pClrFillHdr->u32Color = pPresent->Color;
6502
6503 pHdr->u8Flags = VBOXCMDVBVA_OPF_CLRFILL_TYPE_GENERIC_A8R8G8B8;
6504 pHdr->u.u8PrimaryID = 0;
6505
6506 VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8 *pCFill = (VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8*)pHdr;
6507 VBoxCVDdiFillAllocInfoOffVRAM(&pCFill->dst.Info, pDst);
6508 pCFill->dst.u16Width = (uint16_t)pDstAlloc->AllocData.SurfDesc.width;
6509 pCFill->dst.u16Height = (uint16_t)pDstAlloc->AllocData.SurfDesc.height;
6510 u32DstPatch = RT_UOFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, dst.Info.u.offVRAM);
6511 paRects = pCFill->aRects;
6512 cbPrivateData = RT_UOFFSETOF(VBOXCMDVBVA_CLRFILL_GENERIC_A8R8G8B8, aRects);
6513
6514 if (fDstPrimary)
6515 pCFill->Hdr.Hdr.u.u8PrimaryID = (uint8_t)pDstAlloc->AllocData.SurfDesc.VidPnSourceId;
6516 else
6517 pCFill->Hdr.Hdr.u.u8PrimaryID = 0xff;
6518
6519 cbBuffer = VBOXWDDM_DUMMY_DMABUFFER_SIZE;
6520 }
6521 }
6522 else
6523 {
6524 WARN(("cmd NOT IMPLEMENTED!! Flags(0x%x)", pPresent->Flags.Value));
6525 return STATUS_NOT_SUPPORTED;
6526 }
6527
6528 if (paRects)
6529 {
6530 uint32_t cbMaxRects = pPresent->DmaBufferPrivateDataSize - cbPrivateData;
6531 UINT iStartRect = pPresent->MultipassOffset;
6532 UINT cMaxRects = cbMaxRects / sizeof (VBOXCMDVBVA_RECT);
6533 Assert(pPresent->SubRectCnt > iStartRect);
6534 UINT cRects = pPresent->SubRectCnt - iStartRect;
6535 if (cRects > cMaxRects)
6536 {
6537 pPresent->MultipassOffset += cMaxRects;
6538 cRects = cMaxRects;
6539 }
6540 else
6541 pPresent->MultipassOffset = 0;
6542
6543 Assert(cRects);
6544 const RECT *paDstSubRects = &pPresent->pDstSubRects[iStartRect];
6545 VBoxCVDdiPackRects(paRects, paDstSubRects, cRects);
6546 cbPrivateData += (cRects * sizeof (VBOXCMDVBVA_RECT));
6547 }
6548
6549 if (fPatchSrc)
6550 {
6551 memset(pPresent->pPatchLocationListOut, 0, sizeof (D3DDDI_PATCHLOCATIONLIST));
6552 pPresent->pPatchLocationListOut->PatchOffset = u32SrcPatch;
6553 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
6554 ++pPresent->pPatchLocationListOut;
6555 }
6556
6557 if (fPatchDst)
6558 {
6559 memset(pPresent->pPatchLocationListOut, 0, sizeof (D3DDDI_PATCHLOCATIONLIST));
6560 pPresent->pPatchLocationListOut->PatchOffset = u32DstPatch;
6561 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
6562 ++pPresent->pPatchLocationListOut;
6563 }
6564
6565 pHdr->u8State = VBOXCMDVBVA_STATE_SUBMITTED;
6566
6567 pHdr->u2.complexCmdEl.u16CbCmdHost = cbPrivateData;
6568 pHdr->u2.complexCmdEl.u16CbCmdGuest = cbBuffer;
6569
6570 Assert(cbBuffer);
6571 Assert(cbPrivateData);
6572 Assert(cbPrivateData >= sizeof (VBOXCMDVBVA_HDR));
6573 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + cbBuffer;
6574 pPresent->pDmaBufferPrivateData = ((uint8_t*)pPresent->pDmaBufferPrivateData) + cbPrivateData;
6575
6576 if (pPresent->MultipassOffset)
6577 return STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
6578 return STATUS_SUCCESS;
6579}
6580#endif
6581
6582/**
6583 * DxgkDdiPresent
6584 */
6585static NTSTATUS
6586APIENTRY
6587DxgkDdiPresentLegacy(
6588 CONST HANDLE hContext,
6589 DXGKARG_PRESENT *pPresent)
6590{
6591 RT_NOREF(hContext);
6592 PAGED_CODE();
6593
6594// LOGF(("ENTER, hContext(0x%x)", hContext));
6595
6596 vboxVDbgBreakFv();
6597
6598 NTSTATUS Status = STATUS_SUCCESS;
6599#ifdef VBOX_STRICT
6600 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
6601 PVBOXWDDM_DEVICE pDevice = pContext->pDevice;
6602 PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
6603#endif
6604
6605 Assert(pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR));
6606 if (pPresent->DmaBufferPrivateDataSize < sizeof (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR))
6607 {
6608 LOGREL(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR (%d)", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR)));
6609 /** @todo can this actually happen? what status tu return? */
6610 return STATUS_INVALID_PARAMETER;
6611 }
6612
6613 PVBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR pPrivateData = (PVBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR)pPresent->pDmaBufferPrivateData;
6614 pPrivateData->BaseHdr.fFlags.Value = 0;
6615 /*uint32_t cContexts2D = ASMAtomicReadU32(&pDevExt->cContexts2D); - unused */
6616
6617 if (pPresent->Flags.Blt)
6618 {
6619 Assert(pPresent->Flags.Value == 1); /* only Blt is set, we do not support anything else for now */
6620 DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
6621 DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
6622 PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pSrc);
6623 if (!pSrcAlloc)
6624 {
6625 /* this should not happen actually */
6626 WARN(("failed to get Src Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
6627 Status = STATUS_INVALID_HANDLE;
6628 goto done;
6629 }
6630
6631 PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDst);
6632 if (!pDstAlloc)
6633 {
6634 /* this should not happen actually */
6635 WARN(("failed to get Dst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
6636 Status = STATUS_INVALID_HANDLE;
6637 goto done;
6638 }
6639
6640
6641 UINT cbCmd = pPresent->DmaBufferPrivateDataSize;
6642 pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
6643
6644 PVBOXWDDM_DMA_PRIVATEDATA_BLT pBlt = (PVBOXWDDM_DMA_PRIVATEDATA_BLT)pPrivateData;
6645
6646 vboxWddmPopulateDmaAllocInfo(&pBlt->Blt.SrcAlloc, pSrcAlloc, pSrc);
6647 vboxWddmPopulateDmaAllocInfo(&pBlt->Blt.DstAlloc, pDstAlloc, pDst);
6648
6649 ASSERT_WARN(!pSrcAlloc->fRcFlags.SharedResource, ("Shared Allocatoin used in Present!"));
6650
6651 pBlt->Blt.SrcRect = pPresent->SrcRect;
6652 pBlt->Blt.DstRects.ContextRect = pPresent->DstRect;
6653 pBlt->Blt.DstRects.UpdateRects.cRects = 0;
6654 UINT cbHead = RT_UOFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_BLT, Blt.DstRects.UpdateRects.aRects[0]);
6655 Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
6656 UINT cbRects = (pPresent->SubRectCnt - pPresent->MultipassOffset) * sizeof (RECT);
6657 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
6658 Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
6659 cbCmd -= cbHead;
6660 Assert(cbCmd < UINT32_MAX/2);
6661 Assert(cbCmd > sizeof (RECT));
6662 if (cbCmd >= cbRects)
6663 {
6664 cbCmd -= cbRects;
6665 memcpy(&pBlt->Blt.DstRects.UpdateRects.aRects[0], &pPresent->pDstSubRects[pPresent->MultipassOffset], cbRects);
6666 pBlt->Blt.DstRects.UpdateRects.cRects += cbRects/sizeof (RECT);
6667
6668 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbHead + cbRects;
6669 }
6670 else
6671 {
6672 UINT cbFitingRects = (cbCmd/sizeof (RECT)) * sizeof (RECT);
6673 Assert(cbFitingRects);
6674 memcpy(&pBlt->Blt.DstRects.UpdateRects.aRects[0], &pPresent->pDstSubRects[pPresent->MultipassOffset], cbFitingRects);
6675 cbCmd -= cbFitingRects;
6676 pPresent->MultipassOffset += cbFitingRects/sizeof (RECT);
6677 pBlt->Blt.DstRects.UpdateRects.cRects += cbFitingRects/sizeof (RECT);
6678 Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
6679
6680 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbHead + cbFitingRects;
6681 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
6682 }
6683
6684 memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
6685 pPresent->pPatchLocationListOut->PatchOffset = 0;
6686 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
6687 ++pPresent->pPatchLocationListOut;
6688 pPresent->pPatchLocationListOut->PatchOffset = 4;
6689 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
6690 ++pPresent->pPatchLocationListOut;
6691 }
6692 else if (pPresent->Flags.Flip)
6693 {
6694 Assert(pPresent->Flags.Value == 4); /* only Blt is set, we do not support anything else for now */
6695 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D);
6696 DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
6697 PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pSrc);
6698
6699 if (!pSrcAlloc)
6700 {
6701 /* this should not happen actually */
6702 WARN(("failed to get pSrc Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
6703 Status = STATUS_INVALID_HANDLE;
6704 goto done;
6705 }
6706
6707 Assert(pDevExt->cContexts3D);
6708 pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP;
6709 PVBOXWDDM_DMA_PRIVATEDATA_FLIP pFlip = (PVBOXWDDM_DMA_PRIVATEDATA_FLIP)pPrivateData;
6710
6711 vboxWddmPopulateDmaAllocInfo(&pFlip->Flip.Alloc, pSrcAlloc, pSrc);
6712
6713 UINT cbCmd = sizeof (VBOXWDDM_DMA_PRIVATEDATA_FLIP);
6714 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbCmd;
6715 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
6716 Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
6717
6718 memset(pPresent->pPatchLocationListOut, 0, sizeof (D3DDDI_PATCHLOCATIONLIST));
6719 pPresent->pPatchLocationListOut->PatchOffset = 0;
6720 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
6721 ++pPresent->pPatchLocationListOut;
6722 }
6723 else if (pPresent->Flags.ColorFill)
6724 {
6725 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D);
6726 Assert(pPresent->Flags.Value == 2); /* only ColorFill is set, we do not support anything else for now */
6727 DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
6728 PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDst);
6729 if (!pDstAlloc)
6730 {
6731
6732 /* this should not happen actually */
6733 WARN(("failed to get pDst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
6734 Status = STATUS_INVALID_HANDLE;
6735 goto done;
6736 }
6737
6738 UINT cbCmd = pPresent->DmaBufferPrivateDataSize;
6739 pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL;
6740 PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL pCF = (PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL)pPrivateData;
6741
6742 vboxWddmPopulateDmaAllocInfo(&pCF->ClrFill.Alloc, pDstAlloc, pDst);
6743
6744 pCF->ClrFill.Color = pPresent->Color;
6745 pCF->ClrFill.Rects.cRects = 0;
6746 UINT cbHead = RT_UOFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_CLRFILL, ClrFill.Rects.aRects[0]);
6747 Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
6748 UINT cbRects = (pPresent->SubRectCnt - pPresent->MultipassOffset) * sizeof (RECT);
6749 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
6750 Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
6751 cbCmd -= cbHead;
6752 Assert(cbCmd < UINT32_MAX/2);
6753 Assert(cbCmd > sizeof (RECT));
6754 if (cbCmd >= cbRects)
6755 {
6756 cbCmd -= cbRects;
6757 memcpy(&pCF->ClrFill.Rects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbRects);
6758 pCF->ClrFill.Rects.cRects += cbRects/sizeof (RECT);
6759
6760 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbHead + cbRects;
6761 }
6762 else
6763 {
6764 UINT cbFitingRects = (cbCmd/sizeof (RECT)) * sizeof (RECT);
6765 Assert(cbFitingRects);
6766 memcpy(&pCF->ClrFill.Rects.aRects[0], pPresent->pDstSubRects, cbFitingRects);
6767 cbCmd -= cbFitingRects;
6768 pPresent->MultipassOffset += cbFitingRects/sizeof (RECT);
6769 pCF->ClrFill.Rects.cRects += cbFitingRects/sizeof (RECT);
6770 Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
6771
6772 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbHead + cbFitingRects;
6773 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
6774 }
6775
6776 memset(pPresent->pPatchLocationListOut, 0, sizeof (D3DDDI_PATCHLOCATIONLIST));
6777 pPresent->pPatchLocationListOut->PatchOffset = 0;
6778 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
6779 ++pPresent->pPatchLocationListOut;
6780 }
6781 else
6782 {
6783 WARN(("cmd NOT IMPLEMENTED!! Flags(0x%x)", pPresent->Flags.Value));
6784 Status = STATUS_NOT_SUPPORTED;
6785 }
6786
6787done:
6788// LOGF(("LEAVE, hContext(0x%x), Status(0x%x)", hContext, Status));
6789
6790 return Status;
6791}
6792
6793NTSTATUS
6794APIENTRY
6795DxgkDdiUpdateOverlay(
6796 CONST HANDLE hOverlay,
6797 CONST DXGKARG_UPDATEOVERLAY *pUpdateOverlay)
6798{
6799 LOGF(("ENTER, hOverlay(0x%p)", hOverlay));
6800
6801 NTSTATUS Status = STATUS_SUCCESS;
6802 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)hOverlay;
6803 Assert(pOverlay);
6804 int rc = vboxVhwaHlpOverlayUpdate(pOverlay, &pUpdateOverlay->OverlayInfo);
6805 AssertRC(rc);
6806 if (RT_FAILURE(rc))
6807 Status = STATUS_UNSUCCESSFUL;
6808
6809 LOGF(("LEAVE, hOverlay(0x%p)", hOverlay));
6810
6811 return Status;
6812}
6813
6814NTSTATUS
6815APIENTRY
6816DxgkDdiFlipOverlay(
6817 CONST HANDLE hOverlay,
6818 CONST DXGKARG_FLIPOVERLAY *pFlipOverlay)
6819{
6820 LOGF(("ENTER, hOverlay(0x%p)", hOverlay));
6821
6822 NTSTATUS Status = STATUS_SUCCESS;
6823 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)hOverlay;
6824 Assert(pOverlay);
6825 int rc = vboxVhwaHlpOverlayFlip(pOverlay, pFlipOverlay);
6826 AssertRC(rc);
6827 if (RT_FAILURE(rc))
6828 Status = STATUS_UNSUCCESSFUL;
6829
6830 LOGF(("LEAVE, hOverlay(0x%p)", hOverlay));
6831
6832 return Status;
6833}
6834
6835NTSTATUS
6836APIENTRY
6837DxgkDdiDestroyOverlay(
6838 CONST HANDLE hOverlay)
6839{
6840 LOGF(("ENTER, hOverlay(0x%p)", hOverlay));
6841
6842 NTSTATUS Status = STATUS_SUCCESS;
6843 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)hOverlay;
6844 Assert(pOverlay);
6845 int rc = vboxVhwaHlpOverlayDestroy(pOverlay);
6846 AssertRC(rc);
6847 if (RT_SUCCESS(rc))
6848 vboxWddmMemFree(pOverlay);
6849 else
6850 Status = STATUS_UNSUCCESSFUL;
6851
6852 LOGF(("LEAVE, hOverlay(0x%p)", hOverlay));
6853
6854 return Status;
6855}
6856
6857/**
6858 * DxgkDdiCreateContext
6859 */
6860NTSTATUS
6861APIENTRY
6862DxgkDdiCreateContext(
6863 CONST HANDLE hDevice,
6864 DXGKARG_CREATECONTEXT *pCreateContext)
6865{
6866 /* DxgkDdiCreateContext should be made pageable */
6867 PAGED_CODE();
6868
6869 LOGF(("ENTER, hDevice(0x%x)", hDevice));
6870
6871 vboxVDbgBreakFv();
6872
6873 if (pCreateContext->NodeOrdinal >= VBOXWDDM_NUM_NODES)
6874 {
6875 WARN(("Invalid NodeOrdinal (%d), expected to be less that (%d)\n", pCreateContext->NodeOrdinal, VBOXWDDM_NUM_NODES));
6876 return STATUS_INVALID_PARAMETER;
6877 }
6878
6879 NTSTATUS Status = STATUS_SUCCESS;
6880 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)hDevice;
6881 PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
6882 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)vboxWddmMemAllocZero(sizeof (VBOXWDDM_CONTEXT));
6883 Assert(pContext);
6884 if (pContext)
6885 {
6886 pContext->pDevice = pDevice;
6887 pContext->hContext = pCreateContext->hContext;
6888 pContext->EngineAffinity = pCreateContext->EngineAffinity;
6889 pContext->NodeOrdinal = pCreateContext->NodeOrdinal;
6890 vboxVideoCmCtxInitEmpty(&pContext->CmContext);
6891 if (pCreateContext->Flags.SystemContext || pCreateContext->PrivateDriverDataSize == 0)
6892 {
6893 Assert(pCreateContext->PrivateDriverDataSize == 0);
6894 Assert(!pCreateContext->pPrivateDriverData);
6895 Assert(pCreateContext->Flags.Value <= 2); /* 2 is a GDI context in Win7 */
6896 pContext->enmType = VBOXWDDM_CONTEXT_TYPE_SYSTEM;
6897 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
6898 {
6899 vboxWddmDisplaySettingsCheckPos(pDevExt, i);
6900 }
6901
6902 if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VBOX)
6903 {
6904#ifdef VBOX_WITH_CROGL
6905 if (!VBOXWDDM_IS_DISPLAYONLY() && pDevExt->f3DEnabled)
6906 {
6907 VBoxMpCrPackerInit(&pContext->CrPacker);
6908 int rc = VBoxMpCrCtlConConnect(pDevExt, &pDevExt->CrCtlCon, CR_PROTOCOL_VERSION_MAJOR, CR_PROTOCOL_VERSION_MINOR, &pContext->u32CrConClientID);
6909 if (!RT_SUCCESS(rc))
6910 WARN(("VBoxMpCrCtlConConnect failed rc (%d), ignoring for system context", rc));
6911 }
6912#endif
6913 }
6914 Status = STATUS_SUCCESS;
6915 }
6916 else
6917 {
6918 Assert(pCreateContext->Flags.Value == 0);
6919 Assert(pCreateContext->PrivateDriverDataSize == sizeof (VBOXWDDM_CREATECONTEXT_INFO));
6920 Assert(pCreateContext->pPrivateDriverData);
6921 if (pCreateContext->PrivateDriverDataSize == sizeof (VBOXWDDM_CREATECONTEXT_INFO))
6922 {
6923 PVBOXWDDM_CREATECONTEXT_INFO pInfo = (PVBOXWDDM_CREATECONTEXT_INFO)pCreateContext->pPrivateDriverData;
6924 switch (pInfo->enmType)
6925 {
6926#ifdef VBOX_WITH_CROGL
6927 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D:
6928 {
6929 if (!pDevExt->fCmdVbvaEnabled)
6930 {
6931 Status = vboxVideoAMgrCtxCreate(&pDevExt->AllocMgr, &pContext->AllocContext);
6932 if (!NT_SUCCESS(Status))
6933 WARN(("vboxVideoAMgrCtxCreate failed %#x", Status));
6934 }
6935 else
6936 Status = STATUS_SUCCESS;
6937
6938 if (Status == STATUS_SUCCESS)
6939 {
6940 Status = vboxWddmSwapchainCtxInit(pDevExt, pContext);
6941 AssertNtStatusSuccess(Status);
6942 if (Status == STATUS_SUCCESS)
6943 {
6944 pContext->enmType = VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D;
6945 Status = vboxVideoCmCtxAdd(&pDevice->pAdapter->CmMgr, &pContext->CmContext, (HANDLE)pInfo->u.vbox.hUmEvent, pInfo->u.vbox.u64UmInfo);
6946 AssertNtStatusSuccess(Status);
6947 if (Status == STATUS_SUCCESS)
6948 {
6949 if (pInfo->u.vbox.crVersionMajor || pInfo->u.vbox.crVersionMinor)
6950 {
6951 if (pDevExt->f3DEnabled)
6952 {
6953 if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VBOX)
6954 {
6955 int rc = VBoxMpCrCtlConConnect(pDevExt, &pDevExt->CrCtlCon,
6956 pInfo->u.vbox.crVersionMajor, pInfo->u.vbox.crVersionMinor,
6957 &pContext->u32CrConClientID);
6958 if (RT_SUCCESS(rc))
6959 {
6960 VBoxMpCrPackerInit(&pContext->CrPacker);
6961 }
6962 else
6963 {
6964 WARN(("VBoxMpCrCtlConConnect failed rc (%d)", rc));
6965 Status = STATUS_UNSUCCESSFUL;
6966 }
6967 }
6968 }
6969 else
6970 {
6971 LOG(("3D Not Enabled, failing 3D context creation"));
6972 Status = STATUS_UNSUCCESSFUL;
6973 }
6974 }
6975
6976 if (NT_SUCCESS(Status))
6977 {
6978 ASMAtomicIncU32(&pDevExt->cContexts3D);
6979 break;
6980 }
6981 }
6982
6983 vboxWddmSwapchainCtxTerm(pDevExt, pContext);
6984 }
6985 vboxVideoAMgrCtxDestroy(&pContext->AllocContext);
6986 }
6987 break;
6988 }
6989 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_3D:
6990 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_GL:
6991 {
6992 pContext->enmType = pInfo->enmType;
6993 if (!pDevExt->fCmdVbvaEnabled)
6994 {
6995 Status = vboxVideoAMgrCtxCreate(&pDevExt->AllocMgr, &pContext->AllocContext);
6996 if (!NT_SUCCESS(Status))
6997 WARN(("vboxVideoAMgrCtxCreate failed %#x", Status));
6998 }
6999 else
7000 Status = STATUS_SUCCESS;
7001
7002 if (Status == STATUS_SUCCESS)
7003 {
7004 if (pInfo->u.vbox.crVersionMajor || pInfo->u.vbox.crVersionMinor)
7005 {
7006 if (pDevExt->f3DEnabled)
7007 {
7008 if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VBOX)
7009 {
7010 int rc = VBoxMpCrCtlConConnect(pDevExt, &pDevExt->CrCtlCon,
7011 pInfo->u.vbox.crVersionMajor, pInfo->u.vbox.crVersionMinor,
7012 &pContext->u32CrConClientID);
7013 if (!RT_SUCCESS(rc))
7014 {
7015 WARN(("VBoxMpCrCtlConConnect failed rc (%d)", rc));
7016 Status = STATUS_UNSUCCESSFUL;
7017 }
7018 }
7019 }
7020 else
7021 {
7022 LOG(("3D Not Enabled, failing 3D (hgsmi) context creation"));
7023 Status = STATUS_UNSUCCESSFUL;
7024 }
7025 }
7026
7027 if (NT_SUCCESS(Status))
7028 {
7029 ASMAtomicIncU32(&pDevExt->cContexts3D);
7030 break;
7031 }
7032 vboxVideoAMgrCtxDestroy(&pContext->AllocContext);
7033 }
7034 break;
7035 }
7036#endif
7037 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D:
7038 {
7039 pContext->enmType = pInfo->enmType;
7040 ASMAtomicIncU32(&pDevExt->cContexts2D);
7041 break;
7042 }
7043 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_RESIZE:
7044 {
7045 pContext->enmType = pInfo->enmType;
7046 ASMAtomicIncU32(&pDevExt->cContextsDispIfResize);
7047 break;
7048 }
7049 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_SEAMLESS:
7050 {
7051 pContext->enmType = pInfo->enmType;
7052 Status = vboxVideoCmCtxAdd(&pDevice->pAdapter->SeamlessCtxMgr, &pContext->CmContext, (HANDLE)pInfo->u.vbox.hUmEvent, pInfo->u.vbox.u64UmInfo);
7053 if (!NT_SUCCESS(Status))
7054 {
7055 WARN(("vboxVideoCmCtxAdd failed, Status 0x%x", Status));
7056 }
7057 break;
7058 }
7059 default:
7060 {
7061 WARN(("unsupported context type %d", pInfo->enmType));
7062 Status = STATUS_INVALID_PARAMETER;
7063 break;
7064 }
7065 }
7066 }
7067 }
7068
7069 if (Status == STATUS_SUCCESS)
7070 {
7071 pCreateContext->hContext = pContext;
7072 pCreateContext->ContextInfo.DmaBufferSize = VBOXWDDM_C_DMA_BUFFER_SIZE;
7073 pCreateContext->ContextInfo.DmaBufferSegmentSet = 0;
7074 pCreateContext->ContextInfo.DmaBufferPrivateDataSize = VBOXWDDM_C_DMA_PRIVATEDATA_SIZE;
7075 pCreateContext->ContextInfo.AllocationListSize = VBOXWDDM_C_ALLOC_LIST_SIZE;
7076 pCreateContext->ContextInfo.PatchLocationListSize = VBOXWDDM_C_PATH_LOCATION_LIST_SIZE;
7077 //#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
7078 //# error port to Win7 DDI
7079 // //pCreateContext->ContextInfo.DmaBufferAllocationGroup = ???;
7080 //#endif // DXGKDDI_INTERFACE_VERSION
7081 }
7082 else
7083 vboxWddmMemFree(pContext);
7084 }
7085 else
7086 Status = STATUS_NO_MEMORY;
7087
7088 LOGF(("LEAVE, hDevice(0x%x)", hDevice));
7089
7090 return Status;
7091}
7092
7093NTSTATUS
7094APIENTRY
7095DxgkDdiDestroyContext(
7096 CONST HANDLE hContext)
7097{
7098 LOGF(("ENTER, hContext(0x%x)", hContext));
7099 vboxVDbgBreakFv();
7100 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
7101 PVBOXMP_DEVEXT pDevExt = pContext->pDevice->pAdapter;
7102 NTSTATUS Status = STATUS_SUCCESS;
7103
7104 switch(pContext->enmType)
7105 {
7106 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D:
7107 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_3D:
7108 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_GL:
7109 {
7110 uint32_t cContexts = ASMAtomicDecU32(&pDevExt->cContexts3D);
7111 Assert(cContexts < UINT32_MAX/2); NOREF(cContexts);
7112 break;
7113 }
7114 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D:
7115 {
7116 uint32_t cContexts = ASMAtomicDecU32(&pDevExt->cContexts2D);
7117 Assert(cContexts < UINT32_MAX/2); NOREF(cContexts);
7118 break;
7119 }
7120 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_RESIZE:
7121 {
7122 uint32_t cContexts = ASMAtomicDecU32(&pDevExt->cContextsDispIfResize);
7123 Assert(cContexts < UINT32_MAX/2);
7124 if (!cContexts)
7125 {
7126 if (pDevExt->fDisableTargetUpdate)
7127 {
7128 pDevExt->fDisableTargetUpdate = FALSE;
7129 vboxWddmGhDisplayCheckSetInfoEx(pDevExt, true);
7130 }
7131 }
7132 break;
7133 }
7134 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_SEAMLESS:
7135 {
7136 Status = vboxVideoCmCtxRemove(&pContext->pDevice->pAdapter->SeamlessCtxMgr, &pContext->CmContext);
7137 if (!NT_SUCCESS(Status))
7138 WARN(("vboxVideoCmCtxRemove failed, Status 0x%x", Status));
7139
7140 Assert(pContext->CmContext.pSession == NULL);
7141 break;
7142 }
7143 default:
7144 break;
7145 }
7146
7147#ifdef VBOX_WITH_CROGL
7148 if (pDevExt->enmHwType == VBOXVIDEO_HWTYPE_VBOX && pContext->u32CrConClientID)
7149 {
7150 VBoxMpCrCtlConDisconnect(pDevExt, &pDevExt->CrCtlCon, pContext->u32CrConClientID);
7151 }
7152#endif
7153
7154#ifdef VBOX_WITH_CROGL
7155 /* first terminate the swapchain, this will also ensure
7156 * all currently pending driver->user Cm commands
7157 * (i.e. visible regions commands) are completed */
7158 vboxWddmSwapchainCtxTerm(pDevExt, pContext);
7159#endif
7160
7161 Status = vboxVideoAMgrCtxDestroy(&pContext->AllocContext);
7162 if (NT_SUCCESS(Status))
7163 {
7164 Status = vboxVideoCmCtxRemove(&pContext->pDevice->pAdapter->CmMgr, &pContext->CmContext);
7165 if (NT_SUCCESS(Status))
7166 vboxWddmMemFree(pContext);
7167 else
7168 WARN(("vboxVideoCmCtxRemove failed, Status 0x%x", Status));
7169 }
7170 else
7171 WARN(("vboxVideoAMgrCtxDestroy failed, Status 0x%x", Status));
7172
7173 LOGF(("LEAVE, hContext(0x%x)", hContext));
7174
7175 return Status;
7176}
7177
7178NTSTATUS
7179APIENTRY
7180DxgkDdiLinkDevice(
7181 __in CONST PDEVICE_OBJECT PhysicalDeviceObject,
7182 __in CONST PVOID MiniportDeviceContext,
7183 __inout PLINKED_DEVICE LinkedDevice
7184 )
7185{
7186 RT_NOREF(PhysicalDeviceObject, MiniportDeviceContext, LinkedDevice);
7187 LOGF(("ENTER, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
7188 vboxVDbgBreakFv();
7189 AssertBreakpoint();
7190 LOGF(("LEAVE, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
7191 return STATUS_NOT_IMPLEMENTED;
7192}
7193
7194NTSTATUS
7195APIENTRY
7196DxgkDdiSetDisplayPrivateDriverFormat(
7197 CONST HANDLE hAdapter,
7198 /*CONST*/ DXGKARG_SETDISPLAYPRIVATEDRIVERFORMAT* pSetDisplayPrivateDriverFormat
7199 )
7200{
7201 RT_NOREF(hAdapter, pSetDisplayPrivateDriverFormat);
7202 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
7203 vboxVDbgBreakFv();
7204 AssertBreakpoint();
7205 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
7206 return STATUS_SUCCESS;
7207}
7208
7209NTSTATUS APIENTRY CALLBACK DxgkDdiRestartFromTimeout(IN_CONST_HANDLE hAdapter)
7210{
7211 RT_NOREF(hAdapter);
7212 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
7213 vboxVDbgBreakFv();
7214 AssertBreakpoint();
7215 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
7216 return STATUS_SUCCESS;
7217}
7218
7219static NTSTATUS APIENTRY DxgkDdiQueryVidPnHWCapability(
7220 __in const HANDLE hAdapter,
7221 __inout DXGKARG_QUERYVIDPNHWCAPABILITY *pVidPnHWCaps
7222 )
7223{
7224 RT_NOREF(hAdapter);
7225 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
7226 vboxVDbgBreakF();
7227 pVidPnHWCaps->VidPnHWCaps.DriverRotation = 0;
7228 pVidPnHWCaps->VidPnHWCaps.DriverScaling = 0;
7229 pVidPnHWCaps->VidPnHWCaps.DriverCloning = 0;
7230 pVidPnHWCaps->VidPnHWCaps.DriverColorConvert = 0;
7231 pVidPnHWCaps->VidPnHWCaps.DriverLinkedAdapaterOutput = 0;
7232 pVidPnHWCaps->VidPnHWCaps.DriverRemoteDisplay = 0;
7233 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
7234 return STATUS_SUCCESS;
7235}
7236
7237static NTSTATUS APIENTRY DxgkDdiPresentDisplayOnly(
7238 _In_ const HANDLE hAdapter,
7239 _In_ const DXGKARG_PRESENT_DISPLAYONLY *pPresentDisplayOnly
7240 )
7241{
7242 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
7243 vboxVDbgBreakFv();
7244
7245 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
7246 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pPresentDisplayOnly->VidPnSourceId];
7247 Assert(pSource->AllocData.Addr.SegmentId == 1);
7248 VBOXWDDM_ALLOC_DATA SrcAllocData;
7249 SrcAllocData.SurfDesc.width = pPresentDisplayOnly->Pitch * pPresentDisplayOnly->BytesPerPixel;
7250 SrcAllocData.SurfDesc.height = ~0UL;
7251 switch (pPresentDisplayOnly->BytesPerPixel)
7252 {
7253 case 4:
7254 SrcAllocData.SurfDesc.format = D3DDDIFMT_A8R8G8B8;
7255 break;
7256 case 3:
7257 SrcAllocData.SurfDesc.format = D3DDDIFMT_R8G8B8;
7258 break;
7259 case 2:
7260 SrcAllocData.SurfDesc.format = D3DDDIFMT_R5G6B5;
7261 break;
7262 case 1:
7263 SrcAllocData.SurfDesc.format = D3DDDIFMT_P8;
7264 break;
7265 default:
7266 WARN(("Unknown format"));
7267 SrcAllocData.SurfDesc.format = D3DDDIFMT_UNKNOWN;
7268 break;
7269 }
7270 SrcAllocData.SurfDesc.bpp = pPresentDisplayOnly->BytesPerPixel >> 3;
7271 SrcAllocData.SurfDesc.pitch = pPresentDisplayOnly->Pitch;
7272 SrcAllocData.SurfDesc.depth = 1;
7273 SrcAllocData.SurfDesc.slicePitch = pPresentDisplayOnly->Pitch;
7274 SrcAllocData.SurfDesc.cbSize = ~0UL;
7275 SrcAllocData.Addr.SegmentId = 0;
7276 SrcAllocData.Addr.pvMem = pPresentDisplayOnly->pSource;
7277 SrcAllocData.hostID = 0;
7278 SrcAllocData.pSwapchain = NULL;
7279
7280 RECT UpdateRect;
7281 RT_ZERO(UpdateRect);
7282 BOOLEAN bUpdateRectInited = FALSE;
7283
7284 for (UINT i = 0; i < pPresentDisplayOnly->NumMoves; ++i)
7285 {
7286 if (!bUpdateRectInited)
7287 {
7288 UpdateRect = pPresentDisplayOnly->pMoves[i].DestRect;
7289 bUpdateRectInited = TRUE;
7290 }
7291 else
7292 vboxWddmRectUnite(&UpdateRect, &pPresentDisplayOnly->pMoves[i].DestRect);
7293 vboxVdmaGgDmaBltPerform(pDevExt, &SrcAllocData, &pPresentDisplayOnly->pMoves[i].DestRect, &pSource->AllocData, &pPresentDisplayOnly->pMoves[i].DestRect);
7294 }
7295
7296 for (UINT i = 0; i < pPresentDisplayOnly->NumDirtyRects; ++i)
7297 {
7298 RECT *pDirtyRect = &pPresentDisplayOnly->pDirtyRect[i];
7299
7300 if (pDirtyRect->left >= pDirtyRect->right || pDirtyRect->top >= pDirtyRect->bottom)
7301 {
7302 WARN(("Wrong dirty rect (%d, %d)-(%d, %d)",
7303 pDirtyRect->left, pDirtyRect->top, pDirtyRect->right, pDirtyRect->bottom));
7304 continue;
7305 }
7306
7307 vboxVdmaGgDmaBltPerform(pDevExt, &SrcAllocData, pDirtyRect, &pSource->AllocData, pDirtyRect);
7308
7309 if (!bUpdateRectInited)
7310 {
7311 UpdateRect = *pDirtyRect;
7312 bUpdateRectInited = TRUE;
7313 }
7314 else
7315 vboxWddmRectUnite(&UpdateRect, pDirtyRect);
7316 }
7317
7318 if (bUpdateRectInited && pSource->bVisible)
7319 {
7320 VBOXVBVA_OP_WITHLOCK(ReportDirtyRect, pDevExt, pSource, &UpdateRect);
7321 }
7322
7323 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
7324 return STATUS_SUCCESS;
7325}
7326
7327static NTSTATUS DxgkDdiStopDeviceAndReleasePostDisplayOwnership(
7328 _In_ PVOID MiniportDeviceContext,
7329 _In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
7330 _Out_ PDXGK_DISPLAY_INFORMATION DisplayInfo
7331)
7332{
7333 RT_NOREF(MiniportDeviceContext, TargetId, DisplayInfo);
7334 LOGF(("ENTER, hAdapter(0x%x)", MiniportDeviceContext));
7335 vboxVDbgBreakFv();
7336 AssertBreakpoint();
7337 LOGF(("LEAVE, hAdapter(0x%x)", MiniportDeviceContext));
7338 return STATUS_NOT_SUPPORTED;
7339}
7340
7341static NTSTATUS DxgkDdiSystemDisplayEnable(
7342 _In_ PVOID MiniportDeviceContext,
7343 _In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
7344 _In_ PDXGKARG_SYSTEM_DISPLAY_ENABLE_FLAGS Flags,
7345 _Out_ UINT *Width,
7346 _Out_ UINT *Height,
7347 _Out_ D3DDDIFORMAT *ColorFormat
7348 )
7349{
7350 RT_NOREF(MiniportDeviceContext, TargetId, Flags, Width, Height, ColorFormat);
7351 LOGF(("ENTER, hAdapter(0x%x)", MiniportDeviceContext));
7352 vboxVDbgBreakFv();
7353 AssertBreakpoint();
7354 LOGF(("LEAVE, hAdapter(0x%x)", MiniportDeviceContext));
7355 return STATUS_NOT_SUPPORTED;
7356}
7357
7358static VOID DxgkDdiSystemDisplayWrite(
7359 _In_ PVOID MiniportDeviceContext,
7360 _In_ PVOID Source,
7361 _In_ UINT SourceWidth,
7362 _In_ UINT SourceHeight,
7363 _In_ UINT SourceStride,
7364 _In_ UINT PositionX,
7365 _In_ UINT PositionY
7366)
7367{
7368 RT_NOREF(MiniportDeviceContext, Source, SourceWidth, SourceHeight, SourceStride, PositionX, PositionY);
7369 LOGF(("ENTER, hAdapter(0x%x)", MiniportDeviceContext));
7370 vboxVDbgBreakFv();
7371 AssertBreakpoint();
7372 LOGF(("LEAVE, hAdapter(0x%x)", MiniportDeviceContext));
7373}
7374
7375static NTSTATUS DxgkDdiGetChildContainerId(
7376 _In_ PVOID MiniportDeviceContext,
7377 _In_ ULONG ChildUid,
7378 _Inout_ PDXGK_CHILD_CONTAINER_ID ContainerId
7379)
7380{
7381 RT_NOREF(MiniportDeviceContext, ChildUid, ContainerId);
7382 LOGF(("ENTER, hAdapter(0x%x)", MiniportDeviceContext));
7383 vboxVDbgBreakFv();
7384 AssertBreakpoint();
7385 LOGF(("LEAVE, hAdapter(0x%x)", MiniportDeviceContext));
7386 return STATUS_SUCCESS;
7387}
7388
7389static NTSTATUS APIENTRY DxgkDdiSetPowerComponentFState(
7390 _In_ const HANDLE DriverContext,
7391 UINT ComponentIndex,
7392 UINT FState
7393)
7394{
7395 RT_NOREF(DriverContext, ComponentIndex, FState);
7396 LOGF(("ENTER, DriverContext(0x%x)", DriverContext));
7397 vboxVDbgBreakFv();
7398 AssertBreakpoint();
7399 LOGF(("LEAVE, DriverContext(0x%x)", DriverContext));
7400 return STATUS_SUCCESS;
7401}
7402
7403static NTSTATUS APIENTRY DxgkDdiPowerRuntimeControlRequest(
7404 _In_ const HANDLE DriverContext,
7405 _In_ LPCGUID PowerControlCode,
7406 _In_opt_ PVOID InBuffer,
7407 _In_ SIZE_T InBufferSize,
7408 _Out_opt_ PVOID OutBuffer,
7409 _In_ SIZE_T OutBufferSize,
7410 _Out_opt_ PSIZE_T BytesReturned
7411)
7412{
7413 RT_NOREF(DriverContext, PowerControlCode, InBuffer, InBufferSize, OutBuffer, OutBufferSize, BytesReturned);
7414 LOGF(("ENTER, DriverContext(0x%x)", DriverContext));
7415 vboxVDbgBreakFv();
7416 AssertBreakpoint();
7417 LOGF(("LEAVE, DriverContext(0x%x)", DriverContext));
7418 return STATUS_SUCCESS;
7419}
7420
7421static NTSTATUS DxgkDdiNotifySurpriseRemoval(
7422 _In_ PVOID MiniportDeviceContext,
7423 _In_ DXGK_SURPRISE_REMOVAL_TYPE RemovalType
7424 )
7425{
7426 RT_NOREF(MiniportDeviceContext, RemovalType);
7427 LOGF(("ENTER, hAdapter(0x%x)", MiniportDeviceContext));
7428 vboxVDbgBreakFv();
7429 AssertBreakpoint();
7430 LOGF(("LEAVE, hAdapter(0x%x)", MiniportDeviceContext));
7431 return STATUS_SUCCESS;
7432}
7433
7434static NTSTATUS vboxWddmInitDisplayOnlyDriver(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)
7435{
7436 KMDDOD_INITIALIZATION_DATA DriverInitializationData = {'\0'};
7437
7438 DriverInitializationData.Version = DXGKDDI_INTERFACE_VERSION_WIN8;
7439
7440 DriverInitializationData.DxgkDdiAddDevice = DxgkDdiAddDevice;
7441 DriverInitializationData.DxgkDdiStartDevice = DxgkDdiStartDevice;
7442 DriverInitializationData.DxgkDdiStopDevice = DxgkDdiStopDevice;
7443 DriverInitializationData.DxgkDdiRemoveDevice = DxgkDdiRemoveDevice;
7444 DriverInitializationData.DxgkDdiDispatchIoRequest = DxgkDdiDispatchIoRequest;
7445 DriverInitializationData.DxgkDdiInterruptRoutine = DxgkDdiInterruptRoutineLegacy;
7446 DriverInitializationData.DxgkDdiDpcRoutine = DxgkDdiDpcRoutineLegacy;
7447 DriverInitializationData.DxgkDdiQueryChildRelations = DxgkDdiQueryChildRelations;
7448 DriverInitializationData.DxgkDdiQueryChildStatus = DxgkDdiQueryChildStatus;
7449 DriverInitializationData.DxgkDdiQueryDeviceDescriptor = DxgkDdiQueryDeviceDescriptor;
7450 DriverInitializationData.DxgkDdiSetPowerState = DxgkDdiSetPowerState;
7451 DriverInitializationData.DxgkDdiNotifyAcpiEvent = DxgkDdiNotifyAcpiEvent;
7452 DriverInitializationData.DxgkDdiResetDevice = DxgkDdiResetDevice;
7453 DriverInitializationData.DxgkDdiUnload = DxgkDdiUnload;
7454 DriverInitializationData.DxgkDdiQueryInterface = DxgkDdiQueryInterface;
7455 DriverInitializationData.DxgkDdiControlEtwLogging = DxgkDdiControlEtwLogging;
7456 DriverInitializationData.DxgkDdiQueryAdapterInfo = DxgkDdiQueryAdapterInfo;
7457 DriverInitializationData.DxgkDdiSetPalette = DxgkDdiSetPalette;
7458 DriverInitializationData.DxgkDdiSetPointerPosition = DxgkDdiSetPointerPosition;
7459 DriverInitializationData.DxgkDdiSetPointerShape = DxgkDdiSetPointerShape;
7460 DriverInitializationData.DxgkDdiEscape = DxgkDdiEscape;
7461 DriverInitializationData.DxgkDdiCollectDbgInfo = DxgkDdiCollectDbgInfo;
7462 DriverInitializationData.DxgkDdiIsSupportedVidPn = DxgkDdiIsSupportedVidPn;
7463 DriverInitializationData.DxgkDdiRecommendFunctionalVidPn = DxgkDdiRecommendFunctionalVidPn;
7464 DriverInitializationData.DxgkDdiEnumVidPnCofuncModality = DxgkDdiEnumVidPnCofuncModality;
7465 DriverInitializationData.DxgkDdiSetVidPnSourceVisibility = DxgkDdiSetVidPnSourceVisibility;
7466 DriverInitializationData.DxgkDdiCommitVidPn = DxgkDdiCommitVidPn;
7467 DriverInitializationData.DxgkDdiUpdateActiveVidPnPresentPath = DxgkDdiUpdateActiveVidPnPresentPath;
7468 DriverInitializationData.DxgkDdiRecommendMonitorModes = DxgkDdiRecommendMonitorModes;
7469 DriverInitializationData.DxgkDdiQueryVidPnHWCapability = DxgkDdiQueryVidPnHWCapability;
7470 DriverInitializationData.DxgkDdiPresentDisplayOnly = DxgkDdiPresentDisplayOnly;
7471 DriverInitializationData.DxgkDdiStopDeviceAndReleasePostDisplayOwnership = DxgkDdiStopDeviceAndReleasePostDisplayOwnership;
7472 DriverInitializationData.DxgkDdiSystemDisplayEnable = DxgkDdiSystemDisplayEnable;
7473 DriverInitializationData.DxgkDdiSystemDisplayWrite = DxgkDdiSystemDisplayWrite;
7474// DriverInitializationData.DxgkDdiGetChildContainerId = DxgkDdiGetChildContainerId;
7475// DriverInitializationData.DxgkDdiSetPowerComponentFState = DxgkDdiSetPowerComponentFState;
7476// DriverInitializationData.DxgkDdiPowerRuntimeControlRequest = DxgkDdiPowerRuntimeControlRequest;
7477// DriverInitializationData.DxgkDdiNotifySurpriseRemoval = DxgkDdiNotifySurpriseRemoval;
7478
7479 /* Display-only driver is not required to report VSYNC.
7480 * The Microsoft KMDOD driver sample does not implement DxgkDdiControlInterrupt and DxgkDdiGetScanLine.
7481 * The functions must be either both implemented or none implemented.
7482 * Windows 10 10586 guests had problems with VSYNC in display-only driver (#8228).
7483 * Therefore the driver does not implement DxgkDdiControlInterrupt and DxgkDdiGetScanLine.
7484 */
7485
7486 NTSTATUS Status = DxgkInitializeDisplayOnlyDriver(pDriverObject,
7487 pRegistryPath,
7488 &DriverInitializationData);
7489 if (!NT_SUCCESS(Status))
7490 {
7491 WARN(("DxgkInitializeDisplayOnlyDriver failed! Status 0x%x", Status));
7492 }
7493 return Status;
7494}
7495
7496static NTSTATUS vboxWddmInitFullGraphicsDriver(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath, BOOLEAN fCmdVbva)
7497{
7498#ifdef VBOX_WITH_CROGL
7499#define VBOXWDDM_CALLBACK_NAME(_base, _fCmdVbva) ((_fCmdVbva) ? _base##New : _base##Legacy)
7500#else
7501#define VBOXWDDM_CALLBACK_NAME(_base, _fCmdVbva) (_base##Legacy)
7502#endif
7503
7504 DRIVER_INITIALIZATION_DATA DriverInitializationData = {'\0'};
7505
7506 // Fill in the DriverInitializationData structure and call DxgkInitialize()
7507 if (VBoxQueryWinVersion() >= WINVERSION_8)
7508 DriverInitializationData.Version = DXGKDDI_INTERFACE_VERSION_WIN8;
7509 else
7510 DriverInitializationData.Version = DXGKDDI_INTERFACE_VERSION_VISTA_SP1;
7511
7512 DriverInitializationData.DxgkDdiAddDevice = DxgkDdiAddDevice;
7513 DriverInitializationData.DxgkDdiStartDevice = DxgkDdiStartDevice;
7514 DriverInitializationData.DxgkDdiStopDevice = DxgkDdiStopDevice;
7515 DriverInitializationData.DxgkDdiRemoveDevice = DxgkDdiRemoveDevice;
7516 DriverInitializationData.DxgkDdiDispatchIoRequest = DxgkDdiDispatchIoRequest;
7517 DriverInitializationData.DxgkDdiInterruptRoutine = VBOXWDDM_CALLBACK_NAME(DxgkDdiInterruptRoutine, fCmdVbva);
7518 DriverInitializationData.DxgkDdiDpcRoutine = VBOXWDDM_CALLBACK_NAME(DxgkDdiDpcRoutine, fCmdVbva);
7519 DriverInitializationData.DxgkDdiQueryChildRelations = DxgkDdiQueryChildRelations;
7520 DriverInitializationData.DxgkDdiQueryChildStatus = DxgkDdiQueryChildStatus;
7521 DriverInitializationData.DxgkDdiQueryDeviceDescriptor = DxgkDdiQueryDeviceDescriptor;
7522 DriverInitializationData.DxgkDdiSetPowerState = DxgkDdiSetPowerState;
7523 DriverInitializationData.DxgkDdiNotifyAcpiEvent = DxgkDdiNotifyAcpiEvent;
7524 DriverInitializationData.DxgkDdiResetDevice = DxgkDdiResetDevice;
7525 DriverInitializationData.DxgkDdiUnload = DxgkDdiUnload;
7526 DriverInitializationData.DxgkDdiQueryInterface = DxgkDdiQueryInterface;
7527 DriverInitializationData.DxgkDdiControlEtwLogging = DxgkDdiControlEtwLogging;
7528
7529 DriverInitializationData.DxgkDdiQueryAdapterInfo = DxgkDdiQueryAdapterInfo;
7530 DriverInitializationData.DxgkDdiCreateDevice = DxgkDdiCreateDevice;
7531 DriverInitializationData.DxgkDdiCreateAllocation = DxgkDdiCreateAllocation;
7532 DriverInitializationData.DxgkDdiDestroyAllocation = DxgkDdiDestroyAllocation;
7533 DriverInitializationData.DxgkDdiDescribeAllocation = DxgkDdiDescribeAllocation;
7534 DriverInitializationData.DxgkDdiGetStandardAllocationDriverData = DxgkDdiGetStandardAllocationDriverData;
7535 DriverInitializationData.DxgkDdiAcquireSwizzlingRange = DxgkDdiAcquireSwizzlingRange;
7536 DriverInitializationData.DxgkDdiReleaseSwizzlingRange = DxgkDdiReleaseSwizzlingRange;
7537 DriverInitializationData.DxgkDdiPatch = VBOXWDDM_CALLBACK_NAME(DxgkDdiPatch, fCmdVbva);
7538 DriverInitializationData.DxgkDdiSubmitCommand = VBOXWDDM_CALLBACK_NAME(DxgkDdiSubmitCommand, fCmdVbva);
7539 DriverInitializationData.DxgkDdiPreemptCommand = VBOXWDDM_CALLBACK_NAME(DxgkDdiPreemptCommand, fCmdVbva);
7540 DriverInitializationData.DxgkDdiBuildPagingBuffer = VBOXWDDM_CALLBACK_NAME(DxgkDdiBuildPagingBuffer, fCmdVbva);
7541 DriverInitializationData.DxgkDdiSetPalette = DxgkDdiSetPalette;
7542 DriverInitializationData.DxgkDdiSetPointerPosition = DxgkDdiSetPointerPosition;
7543 DriverInitializationData.DxgkDdiSetPointerShape = DxgkDdiSetPointerShape;
7544 DriverInitializationData.DxgkDdiResetFromTimeout = DxgkDdiResetFromTimeout;
7545 DriverInitializationData.DxgkDdiRestartFromTimeout = DxgkDdiRestartFromTimeout;
7546 DriverInitializationData.DxgkDdiEscape = DxgkDdiEscape;
7547 DriverInitializationData.DxgkDdiCollectDbgInfo = DxgkDdiCollectDbgInfo;
7548 DriverInitializationData.DxgkDdiQueryCurrentFence = VBOXWDDM_CALLBACK_NAME(DxgkDdiQueryCurrentFence, fCmdVbva);
7549 DriverInitializationData.DxgkDdiIsSupportedVidPn = DxgkDdiIsSupportedVidPn;
7550 DriverInitializationData.DxgkDdiRecommendFunctionalVidPn = DxgkDdiRecommendFunctionalVidPn;
7551 DriverInitializationData.DxgkDdiEnumVidPnCofuncModality = DxgkDdiEnumVidPnCofuncModality;
7552 DriverInitializationData.DxgkDdiSetVidPnSourceAddress = DxgkDdiSetVidPnSourceAddress;
7553 DriverInitializationData.DxgkDdiSetVidPnSourceVisibility = DxgkDdiSetVidPnSourceVisibility;
7554 DriverInitializationData.DxgkDdiCommitVidPn = DxgkDdiCommitVidPn;
7555 DriverInitializationData.DxgkDdiUpdateActiveVidPnPresentPath = DxgkDdiUpdateActiveVidPnPresentPath;
7556 DriverInitializationData.DxgkDdiRecommendMonitorModes = DxgkDdiRecommendMonitorModes;
7557 DriverInitializationData.DxgkDdiRecommendVidPnTopology = DxgkDdiRecommendVidPnTopology;
7558 DriverInitializationData.DxgkDdiGetScanLine = DxgkDdiGetScanLine;
7559 DriverInitializationData.DxgkDdiStopCapture = DxgkDdiStopCapture;
7560 DriverInitializationData.DxgkDdiControlInterrupt = DxgkDdiControlInterrupt;
7561 DriverInitializationData.DxgkDdiCreateOverlay = DxgkDdiCreateOverlay;
7562
7563 DriverInitializationData.DxgkDdiDestroyDevice = DxgkDdiDestroyDevice;
7564 DriverInitializationData.DxgkDdiOpenAllocation = DxgkDdiOpenAllocation;
7565 DriverInitializationData.DxgkDdiCloseAllocation = DxgkDdiCloseAllocation;
7566 DriverInitializationData.DxgkDdiRender = VBOXWDDM_CALLBACK_NAME(DxgkDdiRender, fCmdVbva);
7567 DriverInitializationData.DxgkDdiPresent = VBOXWDDM_CALLBACK_NAME(DxgkDdiPresent, fCmdVbva);
7568
7569 DriverInitializationData.DxgkDdiUpdateOverlay = DxgkDdiUpdateOverlay;
7570 DriverInitializationData.DxgkDdiFlipOverlay = DxgkDdiFlipOverlay;
7571 DriverInitializationData.DxgkDdiDestroyOverlay = DxgkDdiDestroyOverlay;
7572
7573 DriverInitializationData.DxgkDdiCreateContext = DxgkDdiCreateContext;
7574 DriverInitializationData.DxgkDdiDestroyContext = DxgkDdiDestroyContext;
7575
7576 DriverInitializationData.DxgkDdiLinkDevice = NULL; //DxgkDdiLinkDevice;
7577 DriverInitializationData.DxgkDdiSetDisplayPrivateDriverFormat = DxgkDdiSetDisplayPrivateDriverFormat;
7578//#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
7579//# error port to Win7 DDI
7580// DriverInitializationData.DxgkDdiRenderKm = DxgkDdiRenderKm;
7581// DriverInitializationData.DxgkDdiRestartFromTimeout = DxgkDdiRestartFromTimeout;
7582// DriverInitializationData.DxgkDdiSetVidPnSourceVisibility = DxgkDdiSetVidPnSourceVisibility;
7583// DriverInitializationData.DxgkDdiUpdateActiveVidPnPresentPath = DxgkDdiUpdateActiveVidPnPresentPath;
7584// DriverInitializationData.DxgkDdiQueryVidPnHWCapability = DxgkDdiQueryVidPnHWCapability;
7585//#endif
7586
7587 NTSTATUS Status = DxgkInitialize(pDriverObject,
7588 pRegistryPath,
7589 &DriverInitializationData);
7590 if (!NT_SUCCESS(Status))
7591 {
7592 WARN(("DxgkInitialize failed! Status 0x%x", Status));
7593 }
7594 return Status;
7595}
7596
7597NTSTATUS
7598DriverEntry(
7599 IN PDRIVER_OBJECT DriverObject,
7600 IN PUNICODE_STRING RegistryPath
7601 )
7602{
7603 PAGED_CODE();
7604
7605 vboxVDbgBreakFv();
7606
7607#if 0//def DEBUG_misha
7608 RTLogGroupSettings(0, "+default.e.l.f.l2.l3");
7609#endif
7610
7611 LOGREL(("VBox WDDM Driver for Windows %s version %d.%d.%dr%d, %d bit; Built %s %s",
7612 VBoxQueryWinVersion() >= WINVERSION_8 ? "8+" : "Vista and 7",
7613 VBOX_VERSION_MAJOR, VBOX_VERSION_MINOR, VBOX_VERSION_BUILD, VBOX_SVN_REV,
7614 (sizeof (void*) << 3), __DATE__, __TIME__));
7615
7616 if ( !ARGUMENT_PRESENT(DriverObject)
7617 || !ARGUMENT_PRESENT(RegistryPath))
7618 return STATUS_INVALID_PARAMETER;
7619
7620 vboxWddmDrvCfgInit(RegistryPath);
7621
7622 ULONG major, minor, build;
7623 BOOLEAN fCheckedBuild = PsGetVersion(&major, &minor, &build, NULL); NOREF(fCheckedBuild);
7624 BOOLEAN f3DRequired = FALSE;
7625
7626 LOGREL(("OsVersion(%d, %d, %d)", major, minor, build));
7627
7628 NTSTATUS Status = STATUS_SUCCESS;
7629 /* Initialize VBoxGuest library, which is used for requests which go through VMMDev. */
7630 int rc = VbglR0InitClient();
7631 if (RT_SUCCESS(rc))
7632 {
7633 /* Check whether 3D is required by the guest. */
7634 if (major > 6)
7635 {
7636 /* Windows 10 and newer. */
7637 f3DRequired = TRUE;
7638 }
7639 else if (major == 6)
7640 {
7641 if (minor >= 2)
7642 {
7643 /* Windows 8, 8.1 and 10 preview. */
7644 f3DRequired = TRUE;
7645 }
7646 else
7647 {
7648 f3DRequired = FALSE;
7649 }
7650 }
7651 else
7652 {
7653 WARN(("Unsupported OLDER win version, ignore and assume 3D is NOT required"));
7654 f3DRequired = FALSE;
7655 }
7656
7657 LOG(("3D is %srequired!", f3DRequired? "": "NOT "));
7658
7659 /* Check whether 3D is provided by the host. */
7660 VBOXVIDEO_HWTYPE enmHwType = VBOXVIDEO_HWTYPE_VBOX;
7661 BOOL f3DSupported = FALSE;
7662
7663 if (VBoxVGACfgAvailable())
7664 {
7665 /* New configuration query interface is available. */
7666 uint32_t u32;
7667 if (VBoxVGACfgQuery(VBE_DISPI_CFG_ID_VERSION, &u32, 0))
7668 {
7669 LOGREL(("WDDM: VGA configuration version %d", u32));
7670 }
7671
7672 VBoxVGACfgQuery(VBE_DISPI_CFG_ID_3D, &u32, 0);
7673 f3DSupported = RT_BOOL(u32);
7674
7675 VBoxVGACfgQuery(VBE_DISPI_CFG_ID_VMSVGA, &u32, 0);
7676 if (u32)
7677 {
7678 enmHwType = VBOXVIDEO_HWTYPE_VMSVGA;
7679 }
7680 LOGREL(("WDDM: VGA configuration: 3D %d, hardware type %d", f3DSupported, enmHwType));
7681 }
7682
7683 BOOL fCmdVbva = FALSE;
7684 if (enmHwType == VBOXVIDEO_HWTYPE_VBOX)
7685 {
7686 /* Try to establish connection to the host 3D service. */
7687#ifdef VBOX_WITH_CROGL
7688 VBoxMpCrCtlConInit();
7689
7690 /* always need to do the check to request host caps */
7691 LOG(("Doing the 3D check.."));
7692 f3DSupported = VBoxMpCrCtlConIs3DSupported();
7693
7694 fCmdVbva = RT_BOOL(VBoxMpCrGetHostCaps() & CR_VBOX_CAP_CMDVBVA);
7695#endif
7696 }
7697 else
7698 {
7699 /* No supported hardware, fallback to VBox 2D only. */
7700 enmHwType = VBOXVIDEO_HWTYPE_VBOX;
7701 f3DSupported = FALSE;
7702 }
7703
7704 LOGREL(("WDDM: 3D is %ssupported, hardware type %d", f3DSupported? "": "not ", enmHwType));
7705
7706 if (NT_SUCCESS(Status))
7707 {
7708 if (!f3DSupported)
7709 {
7710 /* No 3D support by the host. */
7711 if (VBoxQueryWinVersion() >= WINVERSION_8)
7712 {
7713 /* Use display only driver for Win8+. */
7714 g_VBoxDisplayOnly = 1;
7715
7716 /* Black list some builds. */
7717 if (major == 6 && minor == 4 && build == 9841)
7718 {
7719 /* W10 Technical preview crashes with display-only driver. */
7720 LOGREL(("3D is NOT supported by the host, fallback to the system video driver."));
7721 Status = STATUS_UNSUCCESSFUL;
7722 }
7723 else
7724 {
7725 LOGREL(("3D is NOT supported by the host, falling back to display-only mode.."));
7726 }
7727 }
7728 else
7729 {
7730 if (f3DRequired)
7731 {
7732 LOGREL(("3D is NOT supported by the host, but is required for the current guest version using this driver.."));
7733 Status = STATUS_UNSUCCESSFUL;
7734 }
7735 else
7736 LOGREL(("3D is NOT supported by the host, but is NOT required for the current guest version using this driver, continuing with Disabled 3D.."));
7737 }
7738 }
7739 }
7740
7741 if (NT_SUCCESS(Status))
7742 {
7743#ifdef VBOX_WITH_CROGL
7744 rc = VBoxVrInit();
7745 if (RT_SUCCESS(rc))
7746#endif
7747 {
7748 if (g_VBoxDisplayOnly)
7749 {
7750 Status = vboxWddmInitDisplayOnlyDriver(DriverObject, RegistryPath);
7751 }
7752 else
7753 {
7754 Status = vboxWddmInitFullGraphicsDriver(DriverObject, RegistryPath, fCmdVbva);
7755 }
7756
7757 if (NT_SUCCESS(Status))
7758 {
7759 /*
7760 * Successfully initialized the driver.
7761 */
7762 return Status;
7763 }
7764
7765 /*
7766 * Cleanup on failure.
7767 */
7768
7769#ifdef VBOX_WITH_CROGL
7770 VBoxVrTerm();
7771#endif
7772 }
7773#ifdef VBOX_WITH_CROGL
7774 else
7775 {
7776 WARN(("VBoxVrInit failed, rc(%d)", rc));
7777 Status = STATUS_UNSUCCESSFUL;
7778 }
7779#endif
7780 }
7781 else
7782 LOGREL(("Aborting the video driver load due to 3D support missing"));
7783
7784 VbglR0TerminateClient();
7785 }
7786 else
7787 {
7788 WARN(("VbglR0InitClient failed, rc(%d)", rc));
7789 Status = STATUS_UNSUCCESSFUL;
7790 }
7791
7792 AssertRelease(!NT_SUCCESS(Status));
7793
7794 PRTLOGGER pLogger = RTLogRelSetDefaultInstance(NULL);
7795 if (pLogger)
7796 {
7797 RTLogDestroy(pLogger);
7798 }
7799 pLogger = RTLogSetDefaultInstance(NULL);
7800 if (pLogger)
7801 {
7802 RTLogDestroy(pLogger);
7803 }
7804
7805 return Status;
7806}
7807
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