VirtualBox

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

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

bugref:8282: Additions/linux: submit DRM driver to the Linux kernel: move all graphics device-related header files to a separate sub-directory and add that to the include path where they are needed. The intention is too be able to remove the VBox/ include folder in the DRM driver package.

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

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