VirtualBox

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

Last change on this file since 51266 was 51266, checked in by vboxsync, 11 years ago

wddm: fix preemption

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