VirtualBox

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

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

VBoxGuestR0Lib: Function prefix and DECL macro cleanups.

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

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