VirtualBox

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

Last change on this file since 66572 was 66572, checked in by vboxsync, 8 years ago

3D: WDDM: Corrected sequence of handles assignment, bugref:8777

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