VirtualBox

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

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

3D: Skip the second VBOXCMDVBVA_RESIZE which hides disabled Virtual Displays, bugref:8387

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