VirtualBox

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

Last change on this file since 58178 was 58178, checked in by vboxsync, 9 years ago

VbglInit -> VbglInitPrimary & VbglInitClient. VBoxGuestLib/Init.cpp cleanups and positive thinking.

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