VirtualBox

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

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

Reverted r99557 workaround: smaller buffer also works.

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