VirtualBox

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

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

scm: cleaning up todos

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