VirtualBox

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

Last change on this file since 74493 was 74493, checked in by vboxsync, 7 years ago

WDDM: union for context specific data. bugref:8893

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

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