VirtualBox

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

Last change on this file since 53008 was 53008, checked in by vboxsync, 10 years ago

include,Additions: Windows 10 tweaks.

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