VirtualBox

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

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

Windows guest additions, VBVA: reverted part of r100972: host mouse cursor capability, other fixes remain.

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