VirtualBox

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

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

scm --update-copyright-year

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

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