VirtualBox

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

Last change on this file since 41374 was 41374, checked in by vboxsync, 13 years ago

wddm/3d/crogl: backdoor logging

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 245.3 KB
Line 
1/* $Id: VBoxMPWddm.cpp 41374 2012-05-21 18:04:03Z vboxsync $ */
2
3/** @file
4 * VBox WDDM Miniport driver
5 */
6
7/*
8 * Copyright (C) 2011 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#include "VBoxMPWddm.h"
20#include "common/VBoxMPCommon.h"
21#include "common/VBoxMPHGSMI.h"
22#include "VBoxMPVhwa.h"
23#include "VBoxMPVidPn.h"
24
25#include <iprt/asm.h>
26//#include <iprt/initterm.h>
27
28#include <VBox/VBoxGuestLib.h>
29#include <VBox/VBoxVideo.h>
30#include <wingdi.h> /* needed for RGNDATA definition */
31#include <VBoxDisplay.h> /* this is from Additions/WINNT/include/ to include escape codes */
32#include <VBox/Hardware/VBoxVideoVBE.h>
33
34DWORD g_VBoxLogUm = 0;
35
36#define VBOXWDDM_MEMTAG 'MDBV'
37PVOID vboxWddmMemAlloc(IN SIZE_T cbSize)
38{
39 return ExAllocatePoolWithTag(NonPagedPool, cbSize, VBOXWDDM_MEMTAG);
40}
41
42PVOID vboxWddmMemAllocZero(IN SIZE_T cbSize)
43{
44 PVOID pvMem = vboxWddmMemAlloc(cbSize);
45 memset(pvMem, 0, cbSize);
46 return pvMem;
47}
48
49
50VOID vboxWddmMemFree(PVOID pvMem)
51{
52 ExFreePool(pvMem);
53}
54
55DECLINLINE(void) VBoxWddmOaRelease(PVBOXWDDM_OPENALLOCATION pOa)
56{
57 PVBOXWDDM_ALLOCATION pAllocation = pOa->pAllocation;
58 KIRQL OldIrql;
59 KeAcquireSpinLock(&pAllocation->OpenLock, &OldIrql);
60 Assert(pAllocation->cOpens);
61 --pAllocation->cOpens;
62 uint32_t cOpens = --pOa->cOpens;
63 Assert(cOpens < UINT32_MAX/2);
64 if (!cOpens)
65 {
66 RemoveEntryList(&pOa->ListEntry);
67 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
68 vboxWddmMemFree(pOa);
69 }
70 else
71 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
72}
73
74DECLINLINE(PVBOXWDDM_OPENALLOCATION) VBoxWddmOaSearchLocked(PVBOXWDDM_DEVICE pDevice, PVBOXWDDM_ALLOCATION pAllocation)
75{
76 for (PLIST_ENTRY pCur = pAllocation->OpenList.Flink; pCur != &pAllocation->OpenList; pCur = pCur->Flink)
77 {
78 PVBOXWDDM_OPENALLOCATION pCurOa = CONTAINING_RECORD(pCur, VBOXWDDM_OPENALLOCATION, ListEntry);
79 if (pCurOa->pDevice == pDevice)
80 {
81 return pCurOa;
82 }
83 }
84 return NULL;
85}
86
87DECLINLINE(PVBOXWDDM_OPENALLOCATION) VBoxWddmOaSearch(PVBOXWDDM_DEVICE pDevice, PVBOXWDDM_ALLOCATION pAllocation)
88{
89 PVBOXWDDM_OPENALLOCATION pOa;
90 KIRQL OldIrql;
91 KeAcquireSpinLock(&pAllocation->OpenLock, &OldIrql);
92 pOa = VBoxWddmOaSearchLocked(pDevice, pAllocation);
93 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
94 return pOa;
95}
96
97DECLINLINE(PVBOXWDDM_ALLOCATION) vboxWddmGetAllocationFromHandle(PVBOXMP_DEVEXT pDevExt, D3DKMT_HANDLE hAllocation)
98{
99 DXGKARGCB_GETHANDLEDATA GhData;
100 GhData.hObject = hAllocation;
101 GhData.Type = DXGK_HANDLE_ALLOCATION;
102 GhData.Flags.Value = 0;
103 return (PVBOXWDDM_ALLOCATION)pDevExt->u.primary.DxgkInterface.DxgkCbGetHandleData(&GhData);
104}
105
106DECLINLINE(PVBOXWDDM_ALLOCATION) vboxWddmGetAllocationFromAllocList(PVBOXMP_DEVEXT pDevExt, DXGK_ALLOCATIONLIST *pAllocList)
107{
108 PVBOXWDDM_OPENALLOCATION pOa = (PVBOXWDDM_OPENALLOCATION)pAllocList->hDeviceSpecificAllocation;
109 return pOa->pAllocation;
110}
111
112static void vboxWddmPopulateDmaAllocInfo(PVBOXWDDM_DMA_ALLOCINFO pInfo, PVBOXWDDM_ALLOCATION pAlloc, DXGK_ALLOCATIONLIST *pDmaAlloc)
113{
114 pInfo->pAlloc = pAlloc;
115 if (pDmaAlloc->SegmentId)
116 {
117 pInfo->offAlloc = (VBOXVIDEOOFFSET)pDmaAlloc->PhysicalAddress.QuadPart;
118 pInfo->segmentIdAlloc = pDmaAlloc->SegmentId;
119 }
120 else
121 pInfo->segmentIdAlloc = 0;
122 pInfo->srcId = pAlloc->SurfDesc.VidPnSourceId;
123}
124
125static void vboxWddmPopulateDmaAllocInfoWithOffset(PVBOXWDDM_DMA_ALLOCINFO pInfo, PVBOXWDDM_ALLOCATION pAlloc, DXGK_ALLOCATIONLIST *pDmaAlloc, uint32_t offStart)
126{
127 pInfo->pAlloc = pAlloc;
128 if (pDmaAlloc->SegmentId)
129 {
130 pInfo->offAlloc = (VBOXVIDEOOFFSET)pDmaAlloc->PhysicalAddress.QuadPart + offStart;
131 pInfo->segmentIdAlloc = pDmaAlloc->SegmentId;
132 }
133 else
134 pInfo->segmentIdAlloc = 0;
135 pInfo->srcId = pAlloc->SurfDesc.VidPnSourceId;
136}
137
138VBOXVIDEOOFFSET vboxWddmValidatePrimary(PVBOXWDDM_ALLOCATION pAllocation)
139{
140 Assert(pAllocation);
141 if (!pAllocation)
142 {
143 WARN(("no allocation specified for Source"));
144 return VBOXVIDEOOFFSET_VOID;
145 }
146
147 Assert(pAllocation->SegmentId);
148 if (!pAllocation->SegmentId)
149 {
150 WARN(("allocation is not paged in"));
151 return VBOXVIDEOOFFSET_VOID;
152 }
153
154 VBOXVIDEOOFFSET offVram = pAllocation->offVram;
155 Assert(offVram != VBOXVIDEOOFFSET_VOID);
156 if (offVram == VBOXVIDEOOFFSET_VOID)
157 WARN(("VRAM pffset is not defined"));
158
159 return offVram;
160}
161
162NTSTATUS vboxWddmGhDisplayPostInfoScreenBySDesc (PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SURFACE_DESC pDesc, POINT * pVScreenPos, uint16_t fFlags)
163{
164 void *p = VBoxHGSMIBufferAlloc (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx,
165 sizeof (VBVAINFOSCREEN),
166 HGSMI_CH_VBVA,
167 VBVA_INFO_SCREEN);
168 Assert(p);
169 if (p)
170 {
171 VBVAINFOSCREEN *pScreen = (VBVAINFOSCREEN *)p;
172
173 pScreen->u32ViewIndex = pDesc->VidPnSourceId;
174 pScreen->i32OriginX = pVScreenPos->x;
175 pScreen->i32OriginY = pVScreenPos->y;
176 pScreen->u32StartOffset = 0; //(uint32_t)offVram; /* we pretend the view is located at the start of each framebuffer */
177 pScreen->u32LineSize = pDesc->pitch;
178 pScreen->u32Width = pDesc->width;
179 pScreen->u32Height = pDesc->height;
180 pScreen->u16BitsPerPixel = (uint16_t)pDesc->bpp;
181 pScreen->u16Flags = fFlags;
182
183 VBoxHGSMIBufferSubmit (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, p);
184
185 VBoxHGSMIBufferFree (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, p);
186 }
187
188 return STATUS_SUCCESS;
189
190}
191
192NTSTATUS vboxWddmGhDisplayPostInfoScreen(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pAllocation, POINT * pVScreenPos)
193{
194 NTSTATUS Status = vboxWddmGhDisplayPostInfoScreenBySDesc(pDevExt, &pAllocation->SurfDesc, pVScreenPos, VBVA_SCREEN_F_ACTIVE);
195 if (!NT_SUCCESS(Status))
196 WARN(("vboxWddmGhDisplayPostInfoScreenBySDesc failed Status 0x%x", Status));
197 return Status;
198}
199
200NTSTATUS vboxWddmGhDisplayHideScreen(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
201{
202 VBOXWDDM_SURFACE_DESC SurfDesc = {0};
203 POINT VScreenPos = {0};
204 SurfDesc.VidPnSourceId = VidPnTargetId;
205 NTSTATUS Status = vboxWddmGhDisplayPostInfoScreenBySDesc(pDevExt, &SurfDesc, &VScreenPos, VBVA_SCREEN_F_ACTIVE | VBVA_SCREEN_F_DISABLED);
206 if (!NT_SUCCESS(Status))
207 WARN(("vboxWddmGhDisplayPostInfoScreenBySDesc failed Status 0x%x", Status));
208 return Status;
209}
210
211NTSTATUS vboxWddmGhDisplayPostInfoView(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pAllocation)
212{
213 VBOXVIDEOOFFSET offVram = pAllocation->offVram;
214 Assert(offVram != VBOXVIDEOOFFSET_VOID);
215 if (offVram == VBOXVIDEOOFFSET_VOID)
216 return STATUS_INVALID_PARAMETER;
217
218 /* Issue the screen info command. */
219 void *p = VBoxHGSMIBufferAlloc (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx,
220 sizeof (VBVAINFOVIEW),
221 HGSMI_CH_VBVA,
222 VBVA_INFO_VIEW);
223 Assert(p);
224 if (p)
225 {
226 VBVAINFOVIEW *pView = (VBVAINFOVIEW *)p;
227
228 pView->u32ViewIndex = pAllocation->SurfDesc.VidPnSourceId;
229 pView->u32ViewOffset = (uint32_t)offVram; /* we pretend the view is located at the start of each framebuffer */
230 pView->u32ViewSize = vboxWddmVramCpuVisibleSegmentSize(pDevExt)/VBoxCommonFromDeviceExt(pDevExt)->cDisplays;
231
232 pView->u32MaxScreenSize = pView->u32ViewSize;
233
234 VBoxHGSMIBufferSubmit (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, p);
235
236 VBoxHGSMIBufferFree (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx, p);
237 }
238
239 return STATUS_SUCCESS;
240}
241
242NTSTATUS vboxWddmGhDisplaySetMode(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pAllocation)
243{
244// PVBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE pPrimaryInfo = VBOXWDDM_ALLOCATION_BODY(pAllocation, VBOXWDDM_ALLOCATION_SHAREDPRIMARYSURFACE);
245 if (/*pPrimaryInfo->*/pAllocation->SurfDesc.VidPnSourceId)
246 return STATUS_SUCCESS;
247
248 USHORT width = pAllocation->SurfDesc.width;
249 USHORT height = pAllocation->SurfDesc.height;
250 USHORT bpp = pAllocation->SurfDesc.bpp;
251 ULONG cbLine = VBOXWDDM_ROUNDBOUND(((width * bpp) + 7) / 8, 4);
252 ULONG yOffset = (ULONG)pAllocation->offVram / cbLine;
253 ULONG xOffset = (ULONG)pAllocation->offVram % cbLine;
254
255 if (bpp == 4)
256 {
257 xOffset <<= 1;
258 }
259 else
260 {
261 Assert(!(xOffset%((bpp + 7) >> 3)));
262 xOffset /= ((bpp + 7) >> 3);
263 }
264 Assert(xOffset <= 0xffff);
265 Assert(yOffset <= 0xffff);
266
267 VBoxVideoSetModeRegisters(width, height, width, bpp, 0, (uint16_t)xOffset, (uint16_t)yOffset);
268 /*@todo read back from port to check if mode switch was successful */
269
270 return STATUS_SUCCESS;
271}
272
273NTSTATUS vboxWddmGhDisplayUpdateScreenPos(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource, POINT *pVScreenPos)
274{
275 if (pSource->VScreenPos.x == pVScreenPos->x
276 && pSource->VScreenPos.y == pVScreenPos->y)
277 return STATUS_SUCCESS;
278
279 pSource->VScreenPos = *pVScreenPos;
280
281 PVBOXWDDM_ALLOCATION pAllocation = VBOXWDDM_FB_ALLOCATION(pDevExt, pSource);
282 NTSTATUS Status = vboxWddmGhDisplayPostInfoScreen(pDevExt, pAllocation, &pSource->VScreenPos);
283 Assert(Status == STATUS_SUCCESS);
284 return Status;
285}
286
287NTSTATUS vboxWddmGhDisplaySetInfo(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
288{
289 PVBOXWDDM_ALLOCATION pAllocation = VBOXWDDM_FB_ALLOCATION(pDevExt, pSource);
290 VBOXVIDEOOFFSET offVram = vboxWddmValidatePrimary(pAllocation);
291 Assert(offVram != VBOXVIDEOOFFSET_VOID);
292 if (offVram == VBOXVIDEOOFFSET_VOID)
293 return STATUS_INVALID_PARAMETER;
294
295 /*
296 * Set the current mode into the hardware.
297 */
298// NTSTATUS Status= vboxWddmDisplaySettingsQueryPos(pDevExt, VidPnSourceId, &pSource->VScreenPos);
299// Assert(Status == STATUS_SUCCESS);
300 NTSTATUS Status = vboxWddmGhDisplaySetMode(pDevExt, pAllocation);
301 Assert(Status == STATUS_SUCCESS);
302 if (Status == STATUS_SUCCESS)
303 {
304 Status = vboxWddmGhDisplayPostInfoView(pDevExt, pAllocation);
305 Assert(Status == STATUS_SUCCESS);
306 if (Status == STATUS_SUCCESS)
307 {
308 Status = vboxWddmGhDisplayPostInfoScreen(pDevExt, pAllocation, &pSource->VScreenPos);
309 Assert(Status == STATUS_SUCCESS);
310 if (Status != STATUS_SUCCESS)
311 WARN(("vboxWddmGhDisplayPostInfoScreen failed"));
312 }
313 else
314 WARN(("vboxWddmGhDisplayPostInfoView failed"));
315 }
316 else
317 WARN(("vboxWddmGhDisplaySetMode failed"));
318
319 return Status;
320}
321
322static VOID vboxWddmModeRenderFromShadowDisableOnSubmitCommand(PVBOXMP_DEVEXT pDevExt, BOOLEAN fDisable)
323{
324 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
325 {
326 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[i];
327 PVBOXWDDM_ALLOCATION pFromAllocation;
328 PVBOXWDDM_ALLOCATION pToAllocation;
329 if (fDisable)
330 {
331 pFromAllocation = pSource->pShadowAllocation;
332 pToAllocation = pSource->pPrimaryAllocation;
333 }
334 else
335 {
336 pToAllocation = pSource->pShadowAllocation;
337 pFromAllocation = pSource->pPrimaryAllocation;
338 }
339
340 Assert(pToAllocation->offVram != VBOXVIDEOOFFSET_VOID);
341 Assert(pFromAllocation->offVram != VBOXVIDEOOFFSET_VOID);
342 if (pToAllocation->offVram != VBOXVIDEOOFFSET_VOID
343 && pFromAllocation->offVram != VBOXVIDEOOFFSET_VOID)
344 {
345 RECT Rect;
346 Rect.left = 0;
347 Rect.top = 0;
348 Rect.right = pToAllocation->SurfDesc.width;
349 Rect.bottom = pToAllocation->SurfDesc.height;
350 vboxVdmaGgDmaBltPerform(pDevExt, pFromAllocation, &Rect,
351 pToAllocation, &Rect);
352 }
353
354 /* ensure we issue resize command on next update */
355 pSource->offVram = VBOXVIDEOOFFSET_VOID;
356 }
357}
358
359static BOOLEAN vboxWddmModeRenderFromShadowCheckOnSubmitCommand(PVBOXMP_DEVEXT pDevExt, BOOLEAN *pbSwitched)
360{
361 BOOLEAN fDisabled, fNeedSwitch;
362 uint32_t cCount = ASMAtomicUoReadU32(&pDevExt->cRenderFromShadowDisabledContexts);
363
364 fDisabled = !!cCount;
365 fNeedSwitch = (!fDisabled != !pDevExt->fRenderToShadowDisabled);
366
367 if (fNeedSwitch)
368 {
369 vboxWddmModeRenderFromShadowDisableOnSubmitCommand(pDevExt, fDisabled);
370 pDevExt->fRenderToShadowDisabled = fDisabled;
371 }
372
373 if (pbSwitched)
374 *pbSwitched = fNeedSwitch;
375
376 return fDisabled;
377}
378
379
380static VOID vboxWddmModeRenderFromShadowDisableRegister(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_CONTEXT *pContext)
381{
382 if (pContext->fRenderFromShadowDisabled)
383 return;
384 ASMAtomicIncU32(&pDevExt->cRenderFromShadowDisabledContexts);
385 pContext->fRenderFromShadowDisabled = TRUE;
386}
387
388static VOID vboxWddmModeRenderFromShadowDisableUnregister(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_CONTEXT *pContext)
389{
390 if (!pContext->fRenderFromShadowDisabled)
391 return;
392
393 uint32_t cCount = ASMAtomicDecU32(&pDevExt->cRenderFromShadowDisabledContexts);
394 Assert(cCount < UINT32_MAX);
395 pContext->fRenderFromShadowDisabled = FALSE;
396}
397
398DECLINLINE(VOID) vboxWddmAllocUpdateAddress(PVBOXWDDM_ALLOCATION pAllocation, UINT SegmentId, VBOXVIDEOOFFSET offVram)
399{
400 pAllocation->SegmentId = SegmentId;
401 pAllocation->offVram = offVram;
402}
403
404#ifdef VBOXWDDM_RENDER_FROM_SHADOW
405bool vboxWddmCheckUpdateFramebufferAddress(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_SOURCE pSource, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
406{
407 if (pSource->pPrimaryAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC)
408 {
409 Assert(pSource->offVram == VBOXVIDEOOFFSET_VOID);
410 return false;
411 }
412
413 PVBOXWDDM_ALLOCATION pAllocation = VBOXWDDM_FB_ALLOCATION(pDevExt, pSource);
414 Assert(VBOXVIDEOOFFSET_VOID != pAllocation->offVram);
415
416 if (pSource->offVram == pAllocation->offVram)
417 return false;
418 pSource->offVram = pAllocation->offVram;
419
420 NTSTATUS Status = vboxWddmGhDisplaySetInfo(pDevExt, pSource, VidPnSourceId);
421 if (Status != STATUS_SUCCESS)
422 WARN(("vboxWddmGhDisplaySetInfo failed, Status (0x%x)", Status));
423
424 return true;
425}
426#endif
427
428PVBOXSHGSMI vboxWddmHgsmiGetHeapFromCmdOffset(PVBOXMP_DEVEXT pDevExt, HGSMIOFFSET offCmd)
429{
430#ifdef VBOX_WITH_VDMA
431 if(HGSMIAreaContainsOffset(&pDevExt->u.primary.Vdma.CmdHeap.Heap.area, offCmd))
432 return &pDevExt->u.primary.Vdma.CmdHeap;
433#endif
434 if (HGSMIAreaContainsOffset(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx.Heap.area, offCmd))
435 return &VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx;
436 return NULL;
437}
438
439typedef enum
440{
441 VBOXWDDM_HGSMICMD_TYPE_UNDEFINED = 0,
442 VBOXWDDM_HGSMICMD_TYPE_CTL = 1,
443#ifdef VBOX_WITH_VDMA
444 VBOXWDDM_HGSMICMD_TYPE_DMACMD = 2
445#endif
446} VBOXWDDM_HGSMICMD_TYPE;
447
448VBOXWDDM_HGSMICMD_TYPE vboxWddmHgsmiGetCmdTypeFromOffset(PVBOXMP_DEVEXT pDevExt, HGSMIOFFSET offCmd)
449{
450#ifdef VBOX_WITH_VDMA
451 if(HGSMIAreaContainsOffset(&pDevExt->u.primary.Vdma.CmdHeap.Heap.area, offCmd))
452 return VBOXWDDM_HGSMICMD_TYPE_DMACMD;
453#endif
454 if (HGSMIAreaContainsOffset(&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx.Heap.area, offCmd))
455 return VBOXWDDM_HGSMICMD_TYPE_CTL;
456 return VBOXWDDM_HGSMICMD_TYPE_UNDEFINED;
457}
458
459static NTSTATUS vboxWddmChildStatusReportPerform(PVBOXMP_DEVEXT pDevExt, PVBOXVDMA_CHILD_STATUS pChildStatus, D3DDDI_VIDEO_PRESENT_TARGET_ID iChild)
460{
461 DXGK_CHILD_STATUS DdiChildStatus;
462 if (pChildStatus->fFlags & VBOXVDMA_CHILD_STATUS_F_DISCONNECTED)
463 {
464 /* report disconnected */
465 memset(&DdiChildStatus, 0, sizeof (DdiChildStatus));
466 DdiChildStatus.Type = StatusConnection;
467 if (iChild != D3DDDI_ID_UNINITIALIZED)
468 {
469 Assert(iChild < UINT32_MAX/2);
470 Assert(iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
471 DdiChildStatus.ChildUid = iChild;
472 }
473 else
474 {
475 Assert(pChildStatus->iChild < UINT32_MAX/2);
476 Assert(pChildStatus->iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
477 DdiChildStatus.ChildUid = pChildStatus->iChild;
478 }
479 DdiChildStatus.HotPlug.Connected = FALSE;
480 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbIndicateChildStatus(pDevExt->u.primary.DxgkInterface.DeviceHandle, &DdiChildStatus);
481 if (!NT_SUCCESS(Status))
482 {
483 WARN(("DxgkCbIndicateChildStatus failed with Status (0x%x)", Status));
484 return Status;
485 }
486 }
487
488 if (pChildStatus->fFlags & VBOXVDMA_CHILD_STATUS_F_CONNECTED)
489 {
490 /* report disconnected */
491 memset(&DdiChildStatus, 0, sizeof (DdiChildStatus));
492 DdiChildStatus.Type = StatusConnection;
493 if (iChild != D3DDDI_ID_UNINITIALIZED)
494 {
495 Assert(iChild < UINT32_MAX/2);
496 Assert(iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
497 DdiChildStatus.ChildUid = iChild;
498 }
499 else
500 {
501 Assert(pChildStatus->iChild < UINT32_MAX/2);
502 Assert(pChildStatus->iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
503 DdiChildStatus.ChildUid = pChildStatus->iChild;
504 }
505 DdiChildStatus.HotPlug.Connected = TRUE;
506 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbIndicateChildStatus(pDevExt->u.primary.DxgkInterface.DeviceHandle, &DdiChildStatus);
507 if (!NT_SUCCESS(Status))
508 {
509 WARN(("DxgkCbIndicateChildStatus failed with Status (0x%x)", Status));
510 return Status;
511 }
512 }
513
514 if (pChildStatus->fFlags & VBOXVDMA_CHILD_STATUS_F_ROTATED)
515 {
516 /* report disconnected */
517 memset(&DdiChildStatus, 0, sizeof (DdiChildStatus));
518 DdiChildStatus.Type = StatusRotation;
519 if (iChild != D3DDDI_ID_UNINITIALIZED)
520 {
521 Assert(iChild < UINT32_MAX/2);
522 Assert(iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
523 DdiChildStatus.ChildUid = iChild;
524 }
525 else
526 {
527 Assert(pChildStatus->iChild < UINT32_MAX/2);
528 Assert(pChildStatus->iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
529 DdiChildStatus.ChildUid = pChildStatus->iChild;
530 }
531 DdiChildStatus.Rotation.Angle = pChildStatus->u8RotationAngle;
532 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbIndicateChildStatus(pDevExt->u.primary.DxgkInterface.DeviceHandle, &DdiChildStatus);
533 if (!NT_SUCCESS(Status))
534 {
535 WARN(("DxgkCbIndicateChildStatus failed with Status (0x%x)", Status));
536 return Status;
537 }
538 }
539
540 return STATUS_SUCCESS;
541}
542
543typedef struct VBOXWDDMCHILDSTATUSCB
544{
545 PVBOXVDMACBUF_DR pDr;
546 PKEVENT pEvent;
547} VBOXWDDMCHILDSTATUSCB, *PVBOXWDDMCHILDSTATUSCB;
548
549static DECLCALLBACK(VOID) vboxWddmChildStatusReportCompletion(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext)
550{
551 /* we should be called from our DPC routine */
552 Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
553
554 PVBOXWDDMCHILDSTATUSCB pCtx = (PVBOXWDDMCHILDSTATUSCB)pvContext;
555 PVBOXVDMACBUF_DR pDr = pCtx->pDr;
556 PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
557 VBOXVDMACMD_CHILD_STATUS_IRQ *pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_CHILD_STATUS_IRQ);
558
559 for (UINT i = 0; i < pBody->cInfos; ++i)
560 {
561 PVBOXVDMA_CHILD_STATUS pInfo = &pBody->aInfos[i];
562 if (pBody->fFlags & VBOXVDMACMD_CHILD_STATUS_IRQ_F_APPLY_TO_ALL)
563 {
564 for (D3DDDI_VIDEO_PRESENT_TARGET_ID iChild = 0; iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++iChild)
565 {
566 NTSTATUS Status = vboxWddmChildStatusReportPerform(pDevExt, pInfo, iChild);
567 if (!NT_SUCCESS(Status))
568 {
569 WARN(("vboxWddmChildStatusReportPerform failed with Status (0x%x)", Status));
570 break;
571 }
572 }
573 }
574 else
575 {
576 NTSTATUS Status = vboxWddmChildStatusReportPerform(pDevExt, pInfo, D3DDDI_ID_UNINITIALIZED);
577 if (!NT_SUCCESS(Status))
578 {
579 WARN(("vboxWddmChildStatusReportPerform failed with Status (0x%x)", Status));
580 break;
581 }
582 }
583 }
584
585 vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
586
587 if (pCtx->pEvent)
588 {
589 KeSetEvent(pCtx->pEvent, 0, FALSE);
590 }
591}
592
593static NTSTATUS vboxWddmChildStatusReportReconnected(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_TARGET_ID idTarget)
594{
595 NTSTATUS Status = STATUS_UNSUCCESSFUL;
596 UINT cbCmd = VBOXVDMACMD_SIZE_FROMBODYSIZE(sizeof (VBOXVDMACMD_CHILD_STATUS_IRQ));
597
598 PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate(&pDevExt->u.primary.Vdma, cbCmd);
599 if (pDr)
600 {
601 // vboxVdmaCBufDrCreate zero initializes the pDr
602 /* the command data follows the descriptor */
603 pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR;
604 pDr->cbBuf = cbCmd;
605 pDr->rc = VERR_NOT_IMPLEMENTED;
606
607 PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
608 pHdr->enmType = VBOXVDMACMD_TYPE_CHILD_STATUS_IRQ;
609 pHdr->u32CmdSpecific = 0;
610 PVBOXVDMACMD_CHILD_STATUS_IRQ pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_CHILD_STATUS_IRQ);
611 pBody->cInfos = 1;
612 if (idTarget == D3DDDI_ID_ALL)
613 {
614 pBody->fFlags |= VBOXVDMACMD_CHILD_STATUS_IRQ_F_APPLY_TO_ALL;
615 }
616 pBody->aInfos[0].iChild = idTarget;
617 pBody->aInfos[0].fFlags = VBOXVDMA_CHILD_STATUS_F_DISCONNECTED | VBOXVDMA_CHILD_STATUS_F_CONNECTED;
618
619 /* we're going to KeWaitForSingleObject */
620 Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
621
622 PVBOXVDMADDI_CMD pDdiCmd = VBOXVDMADDI_CMD_FROM_BUF_DR(pDr);
623 VBOXWDDMCHILDSTATUSCB Ctx;
624 KEVENT Event;
625 KeInitializeEvent(&Event, NotificationEvent, FALSE);
626 Ctx.pDr = pDr;
627 Ctx.pEvent = &Event;
628 vboxVdmaDdiCmdInit(pDdiCmd, 0, 0, vboxWddmChildStatusReportCompletion, &Ctx);
629 /* mark command as submitted & invisible for the dx runtime since dx did not originate it */
630 vboxVdmaDdiCmdSubmittedNotDx(pDdiCmd);
631 int rc = vboxVdmaCBufDrSubmit(pDevExt, &pDevExt->u.primary.Vdma, pDr);
632 Assert(rc == VINF_SUCCESS);
633 if (RT_SUCCESS(rc))
634 {
635 Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
636 Assert(Status == STATUS_SUCCESS);
637 return STATUS_SUCCESS;
638 }
639
640 Status = STATUS_UNSUCCESSFUL;
641
642 vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
643 }
644 else
645 {
646 Assert(0);
647 /* @todo: try flushing.. */
648 LOGREL(("vboxVdmaCBufDrCreate returned NULL"));
649 Status = STATUS_INSUFFICIENT_RESOURCES;
650 }
651
652 return Status;
653}
654
655static NTSTATUS vboxWddmChildStatusCheck(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_VIDEOMODES_INFO paInfos)
656{
657 NTSTATUS Status = STATUS_SUCCESS;
658 bool bChanged[VBOX_VIDEO_MAX_SCREENS] = {0};
659 int i;
660
661 Assert(!bChanged[0]);
662 for (i = 1; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
663 {
664 /* @todo: check that we actually need the current source->target */
665 PVBOXWDDM_VIDEOMODES_INFO pInfo = &paInfos[i];
666 VIDEO_MODE_INFORMATION *pModeInfo = &pInfo->aModes[pInfo->iPreferredMode];
667 BOOLEAN fMatch = FALSE;
668 Status = vboxVidPnMatchMonitorModes(pDevExt, i, pInfo->aResolutions, pInfo->cResolutions, &fMatch);
669 if (!NT_SUCCESS(Status))
670 {
671 WARN(("vboxVidPnMatchMonitorModes failed Status(0x%x)", Status));
672 /* ignore the failures here, although we probably should not?? */
673 break;
674 }
675
676 bChanged[i] = !fMatch;
677
678 if (!fMatch)
679 {
680 Status = vboxWddmChildStatusReportReconnected(pDevExt, i);
681 if (!NT_SUCCESS(Status))
682 {
683 WARN(("vboxWddmChildStatusReportReconnected failed Status(0x%x)", Status));
684 /* ignore the failures here, although we probably should not?? */
685 break;
686 }
687 }
688 }
689
690 if (!NT_SUCCESS(Status))
691 {
692 WARN(("updating monitor modes failed, Status(0x%x)", Status));
693 return Status;
694 }
695
696 /* wait for the reconnected monitor data to be picked up */
697 CONST DXGK_MONITOR_INTERFACE *pMonitorInterface;
698 Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryMonitorInterface(pDevExt->u.primary.DxgkInterface.DeviceHandle, DXGK_MONITOR_INTERFACE_VERSION_V1, &pMonitorInterface);
699 if (!NT_SUCCESS(Status))
700 {
701 WARN(("DxgkCbQueryMonitorInterface failed, Status()0x%x", Status));
702 return Status;
703 }
704
705 for (i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
706 {
707 D3DKMDT_HMONITORSOURCEMODESET hMonitorSMS;
708 CONST DXGK_MONITORSOURCEMODESET_INTERFACE *pMonitorSMSIf;
709 if (!bChanged[i])
710 continue;
711
712 while (1)
713 {
714 Status = pMonitorInterface->pfnAcquireMonitorSourceModeSet(pDevExt->u.primary.DxgkInterface.DeviceHandle,
715 i,
716 &hMonitorSMS,
717 &pMonitorSMSIf);
718 if (NT_SUCCESS(Status))
719 {
720 NTSTATUS tmpStatus = pMonitorInterface->pfnReleaseMonitorSourceModeSet(pDevExt->u.primary.DxgkInterface.DeviceHandle, hMonitorSMS);
721 if (!NT_SUCCESS(tmpStatus))
722 {
723 WARN(("pfnReleaseMonitorSourceModeSet failed tmpStatus(0x%x)", tmpStatus));
724 }
725 break;
726 }
727
728 if (Status != STATUS_GRAPHICS_MONITOR_NOT_CONNECTED)
729 {
730 WARN(("DxgkCbQueryMonitorInterface failed, Status()0x%x", Status));
731 break;
732 }
733
734 Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
735
736 LARGE_INTEGER Interval;
737 Interval.QuadPart = -(int64_t) 2 /* ms */ * 10000;
738 NTSTATUS tmpStatus = KeDelayExecutionThread(KernelMode, FALSE, &Interval);
739 if (!NT_SUCCESS(tmpStatus))
740 {
741 WARN(("KeDelayExecutionThread failed tmpStatus(0x%x)", tmpStatus));
742 }
743 }
744 }
745
746 return STATUS_SUCCESS;
747}
748
749typedef struct VBOXWDDM_HWRESOURCES
750{
751 PHYSICAL_ADDRESS phVRAM;
752 ULONG cbVRAM;
753 ULONG ulApertureSize;
754} VBOXWDDM_HWRESOURCES, *PVBOXWDDM_HWRESOURCES;
755
756NTSTATUS vboxWddmPickResources(PVBOXMP_DEVEXT pDevExt, PDXGK_DEVICE_INFO pDeviceInfo, PVBOXWDDM_HWRESOURCES pHwResources)
757{
758 NTSTATUS Status = STATUS_SUCCESS;
759 USHORT DispiId;
760 memset(pHwResources, 0, sizeof (*pHwResources));
761 pHwResources->cbVRAM = VBE_DISPI_TOTAL_VIDEO_MEMORY_BYTES;
762
763 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_INDEX, VBE_DISPI_INDEX_ID);
764 VBoxVideoCmnPortWriteUshort(VBE_DISPI_IOPORT_DATA, VBE_DISPI_ID2);
765 DispiId = VBoxVideoCmnPortReadUshort(VBE_DISPI_IOPORT_DATA);
766 if (DispiId == VBE_DISPI_ID2)
767 {
768 LOGREL(("found the VBE card"));
769 /*
770 * Write some hardware information to registry, so that
771 * it's visible in Windows property dialog.
772 */
773
774 /*
775 * Query the adapter's memory size. It's a bit of a hack, we just read
776 * an ULONG from the data port without setting an index before.
777 */
778 pHwResources->cbVRAM = VBoxVideoCmnPortReadUlong(VBE_DISPI_IOPORT_DATA);
779 if (VBoxHGSMIIsSupported ())
780 {
781 PCM_RESOURCE_LIST pRcList = pDeviceInfo->TranslatedResourceList;
782 /* @todo: verify resources */
783 for (ULONG i = 0; i < pRcList->Count; ++i)
784 {
785 PCM_FULL_RESOURCE_DESCRIPTOR pFRc = &pRcList->List[i];
786 for (ULONG j = 0; j < pFRc->PartialResourceList.Count; ++j)
787 {
788 PCM_PARTIAL_RESOURCE_DESCRIPTOR pPRc = &pFRc->PartialResourceList.PartialDescriptors[j];
789 switch (pPRc->Type)
790 {
791 case CmResourceTypePort:
792 break;
793 case CmResourceTypeInterrupt:
794 break;
795 case CmResourceTypeMemory:
796 /* we assume there is one memory segment */
797 Assert(pHwResources->phVRAM.QuadPart == 0);
798 pHwResources->phVRAM = pPRc->u.Memory.Start;
799 Assert(pHwResources->phVRAM.QuadPart != 0);
800 pHwResources->ulApertureSize = pPRc->u.Memory.Length;
801 Assert(pHwResources->cbVRAM <= pHwResources->ulApertureSize);
802 break;
803 case CmResourceTypeDma:
804 break;
805 case CmResourceTypeDeviceSpecific:
806 break;
807 case CmResourceTypeBusNumber:
808 break;
809 default:
810 break;
811 }
812 }
813 }
814 }
815 else
816 {
817 LOGREL(("HGSMI unsupported, returning err"));
818 /* @todo: report a better status */
819 Status = STATUS_UNSUCCESSFUL;
820 }
821 }
822 else
823 {
824 LOGREL(("VBE card not found, returning err"));
825 Status = STATUS_UNSUCCESSFUL;
826 }
827
828
829 return Status;
830}
831
832static void vboxWddmDevExtZeroinit(PVBOXMP_DEVEXT pDevExt, CONST PDEVICE_OBJECT pPDO)
833{
834 memset(pDevExt, 0, sizeof (VBOXMP_DEVEXT));
835 pDevExt->pPDO = pPDO;
836 PWCHAR pName = (PWCHAR)(((uint8_t*)pDevExt) + VBOXWDDM_ROUNDBOUND(sizeof(VBOXMP_DEVEXT), 8));
837 RtlInitUnicodeString(&pDevExt->RegKeyName, pName);
838#ifdef VBOXWDDM_RENDER_FROM_SHADOW
839 for (int i = 0; i < RT_ELEMENTS(pDevExt->aSources); ++i)
840 {
841 pDevExt->aSources[i].offVram = VBOXVIDEOOFFSET_VOID;
842 }
843#endif
844}
845
846static void vboxWddmSetupDisplays(PVBOXMP_DEVEXT pDevExt)
847{
848 /* For WDDM, we simply store the number of monitors as we will deal with
849 * VidPN stuff later */
850 int rc = STATUS_SUCCESS;
851
852 if (VBoxCommonFromDeviceExt(pDevExt)->bHGSMI)
853 {
854 ULONG ulAvailable = VBoxCommonFromDeviceExt(pDevExt)->cbVRAM
855 - VBoxCommonFromDeviceExt(pDevExt)->cbMiniportHeap
856 - VBVA_ADAPTER_INFORMATION_SIZE;
857
858 ULONG ulSize;
859 ULONG offset;
860#ifdef VBOX_WITH_VDMA
861 ulSize = ulAvailable / 2;
862 if (ulSize > VBOXWDDM_C_VDMA_BUFFER_SIZE)
863 ulSize = VBOXWDDM_C_VDMA_BUFFER_SIZE;
864
865 /* Align down to 4096 bytes. */
866 ulSize &= ~0xFFF;
867 offset = ulAvailable - ulSize;
868
869 Assert(!(offset & 0xFFF));
870#else
871 offset = ulAvailable;
872#endif
873 rc = vboxVdmaCreate (pDevExt, &pDevExt->u.primary.Vdma
874#ifdef VBOX_WITH_VDMA
875 , offset, ulSize
876#endif
877 );
878 AssertRC(rc);
879 if (RT_SUCCESS(rc))
880 {
881 /* can enable it right away since the host does not need any screen/FB info
882 * for basic DMA functionality */
883 rc = vboxVdmaEnable(pDevExt, &pDevExt->u.primary.Vdma);
884 AssertRC(rc);
885 if (RT_FAILURE(rc))
886 vboxVdmaDestroy(pDevExt, &pDevExt->u.primary.Vdma);
887 }
888
889 ulAvailable = offset;
890 ulSize = ulAvailable/2;
891 offset = ulAvailable - ulSize;
892
893 NTSTATUS Status = vboxVideoAMgrCreate(pDevExt, &pDevExt->AllocMgr, offset, ulSize);
894 Assert(Status == STATUS_SUCCESS);
895 if (Status != STATUS_SUCCESS)
896 {
897 offset = ulAvailable;
898 }
899
900#ifdef VBOXWDDM_RENDER_FROM_SHADOW
901 if (RT_SUCCESS(rc))
902 {
903 ulAvailable = offset;
904 ulSize = ulAvailable / 2;
905 ulSize /= VBoxCommonFromDeviceExt(pDevExt)->cDisplays;
906 Assert(ulSize > VBVA_MIN_BUFFER_SIZE);
907 if (ulSize > VBVA_MIN_BUFFER_SIZE)
908 {
909 ULONG ulRatio = ulSize/VBVA_MIN_BUFFER_SIZE;
910 ulRatio >>= 4; /* /= 16; */
911 if (ulRatio)
912 ulSize = VBVA_MIN_BUFFER_SIZE * ulRatio;
913 else
914 ulSize = VBVA_MIN_BUFFER_SIZE;
915 }
916 else
917 {
918 /* todo: ?? */
919 }
920
921 ulSize &= ~0xFFF;
922 Assert(ulSize);
923
924 Assert(ulSize * VBoxCommonFromDeviceExt(pDevExt)->cDisplays < ulAvailable);
925
926 for (int i = VBoxCommonFromDeviceExt(pDevExt)->cDisplays-1; i >= 0; --i)
927 {
928 offset -= ulSize;
929 rc = vboxVbvaCreate(pDevExt, &pDevExt->aSources[i].Vbva, offset, ulSize, i);
930 AssertRC(rc);
931 if (RT_SUCCESS(rc))
932 {
933 rc = vboxVbvaEnable(pDevExt, &pDevExt->aSources[i].Vbva);
934 AssertRC(rc);
935 if (RT_FAILURE(rc))
936 {
937 /* @todo: de-initialize */
938 }
939 }
940 }
941 }
942#endif
943
944 rc = VBoxMPCmnMapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt), (void**)&pDevExt->pvVisibleVram,
945 0, vboxWddmVramCpuVisibleSize(pDevExt));
946 Assert(rc == VINF_SUCCESS);
947 if (rc != VINF_SUCCESS)
948 pDevExt->pvVisibleVram = NULL;
949
950 if (RT_FAILURE(rc))
951 VBoxCommonFromDeviceExt(pDevExt)->bHGSMI = FALSE;
952 }
953}
954
955static int vboxWddmFreeDisplays(PVBOXMP_DEVEXT pDevExt)
956{
957 int rc = VINF_SUCCESS;
958
959 Assert(pDevExt->pvVisibleVram);
960 if (pDevExt->pvVisibleVram)
961 VBoxMPCmnUnmapAdapterMemory(VBoxCommonFromDeviceExt(pDevExt), (void**)&pDevExt->pvVisibleVram);
962
963 for (int i = VBoxCommonFromDeviceExt(pDevExt)->cDisplays-1; i >= 0; --i)
964 {
965 rc = vboxVbvaDisable(pDevExt, &pDevExt->aSources[i].Vbva);
966 AssertRC(rc);
967 if (RT_SUCCESS(rc))
968 {
969 rc = vboxVbvaDestroy(pDevExt, &pDevExt->aSources[i].Vbva);
970 AssertRC(rc);
971 if (RT_FAILURE(rc))
972 {
973 /* @todo: */
974 }
975 }
976 }
977
978 vboxVideoAMgrDestroy(pDevExt, &pDevExt->AllocMgr);
979
980 rc = vboxVdmaDisable(pDevExt, &pDevExt->u.primary.Vdma);
981 AssertRC(rc);
982 if (RT_SUCCESS(rc))
983 {
984 rc = vboxVdmaDestroy(pDevExt, &pDevExt->u.primary.Vdma);
985 AssertRC(rc);
986 }
987 return rc;
988}
989
990
991/* driver callbacks */
992NTSTATUS DxgkDdiAddDevice(
993 IN CONST PDEVICE_OBJECT PhysicalDeviceObject,
994 OUT PVOID *MiniportDeviceContext
995 )
996{
997 /* The DxgkDdiAddDevice function should be made pageable. */
998 PAGED_CODE();
999
1000 LOGF(("ENTER, pdo(0x%x)", PhysicalDeviceObject));
1001
1002 vboxVDbgBreakFv();
1003
1004 NTSTATUS Status = STATUS_SUCCESS;
1005 PVBOXMP_DEVEXT pDevExt;
1006
1007 WCHAR RegKeyBuf[512];
1008 ULONG cbRegKeyBuf = sizeof (RegKeyBuf);
1009
1010 Status = IoGetDeviceProperty (PhysicalDeviceObject,
1011 DevicePropertyDriverKeyName,
1012 cbRegKeyBuf,
1013 RegKeyBuf,
1014 &cbRegKeyBuf);
1015 Assert(Status == STATUS_SUCCESS);
1016 if (Status == STATUS_SUCCESS)
1017 {
1018 pDevExt = (PVBOXMP_DEVEXT)vboxWddmMemAllocZero(VBOXWDDM_ROUNDBOUND(sizeof(VBOXMP_DEVEXT), 8) + cbRegKeyBuf);
1019 if (pDevExt)
1020 {
1021 PWCHAR pName = (PWCHAR)(((uint8_t*)pDevExt) + VBOXWDDM_ROUNDBOUND(sizeof(VBOXMP_DEVEXT), 8));
1022 memcpy(pName, RegKeyBuf, cbRegKeyBuf);
1023 vboxWddmDevExtZeroinit(pDevExt, PhysicalDeviceObject);
1024 *MiniportDeviceContext = pDevExt;
1025 }
1026 else
1027 {
1028 Status = STATUS_NO_MEMORY;
1029 LOGREL(("ERROR, failed to create context"));
1030 }
1031 }
1032
1033 LOGF(("LEAVE, Status(0x%x), pDevExt(0x%x)", Status, pDevExt));
1034
1035 return Status;
1036}
1037
1038NTSTATUS DxgkDdiStartDevice(
1039 IN CONST PVOID MiniportDeviceContext,
1040 IN PDXGK_START_INFO DxgkStartInfo,
1041 IN PDXGKRNL_INTERFACE DxgkInterface,
1042 OUT PULONG NumberOfVideoPresentSources,
1043 OUT PULONG NumberOfChildren
1044 )
1045{
1046 /* The DxgkDdiStartDevice function should be made pageable. */
1047 PAGED_CODE();
1048
1049 NTSTATUS Status;
1050
1051 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
1052
1053 vboxVDbgBreakFv();
1054
1055 if ( ARGUMENT_PRESENT(MiniportDeviceContext) &&
1056 ARGUMENT_PRESENT(DxgkInterface) &&
1057 ARGUMENT_PRESENT(DxgkStartInfo) &&
1058 ARGUMENT_PRESENT(NumberOfVideoPresentSources),
1059 ARGUMENT_PRESENT(NumberOfChildren)
1060 )
1061 {
1062 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1063
1064 vboxWddmVGuidGet(pDevExt);
1065
1066 /* Save DeviceHandle and function pointers supplied by the DXGKRNL_INTERFACE structure passed to DxgkInterface. */
1067 memcpy(&pDevExt->u.primary.DxgkInterface, DxgkInterface, sizeof (DXGKRNL_INTERFACE));
1068
1069 /* 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)
1070 * of the DXGK_DEVICE_INFO structure in the context block represented by MiniportDeviceContext. */
1071 DXGK_DEVICE_INFO DeviceInfo;
1072 Status = pDevExt->u.primary.DxgkInterface.DxgkCbGetDeviceInformation (pDevExt->u.primary.DxgkInterface.DeviceHandle, &DeviceInfo);
1073 if (Status == STATUS_SUCCESS)
1074 {
1075 VBOXWDDM_HWRESOURCES HwRc;
1076 Status = vboxWddmPickResources(pDevExt, &DeviceInfo, &HwRc);
1077 if (Status == STATUS_SUCCESS)
1078 {
1079 /* Guest supports only HGSMI, the old VBVA via VMMDev is not supported.
1080 * The host will however support both old and new interface to keep compatibility
1081 * with old guest additions.
1082 */
1083 VBoxSetupDisplaysHGSMI(VBoxCommonFromDeviceExt(pDevExt),
1084 HwRc.phVRAM, HwRc.ulApertureSize, HwRc.cbVRAM,
1085 VBVACAPS_COMPLETEGCMD_BY_IOREAD | VBVACAPS_IRQ);
1086 if (VBoxCommonFromDeviceExt(pDevExt)->bHGSMI)
1087 {
1088 vboxWddmSetupDisplays(pDevExt);
1089 if (!VBoxCommonFromDeviceExt(pDevExt)->bHGSMI)
1090 VBoxFreeDisplaysHGSMI(VBoxCommonFromDeviceExt(pDevExt));
1091 }
1092 if (VBoxCommonFromDeviceExt(pDevExt)->bHGSMI)
1093 {
1094 LOGREL(("using HGSMI"));
1095 *NumberOfVideoPresentSources = VBoxCommonFromDeviceExt(pDevExt)->cDisplays;
1096 *NumberOfChildren = VBoxCommonFromDeviceExt(pDevExt)->cDisplays;
1097 LOG(("sources(%d), children(%d)", *NumberOfVideoPresentSources, *NumberOfChildren));
1098
1099 vboxVdmaDdiNodesInit(pDevExt);
1100 vboxVideoCmInit(&pDevExt->CmMgr);
1101 InitializeListHead(&pDevExt->SwapchainList3D);
1102 pDevExt->cContexts3D = 0;
1103 pDevExt->cContexts2D = 0;
1104 pDevExt->cUnlockedVBVADisabled = 0;
1105 ExInitializeFastMutex(&pDevExt->ContextMutex);
1106 KeInitializeSpinLock(&pDevExt->SynchLock);
1107
1108 VBoxMPCmnInitCustomVideoModes(pDevExt);
1109 VBoxWddmInvalidateVideoModesInfo(pDevExt);
1110#if 0
1111 vboxShRcTreeInit(pDevExt);
1112#endif
1113
1114#ifdef VBOX_WITH_VIDEOHWACCEL
1115 vboxVhwaInit(pDevExt);
1116#endif
1117 }
1118 else
1119 {
1120 LOGREL(("HGSMI failed to initialize, returning err"));
1121
1122 /* @todo: report a better status */
1123 Status = STATUS_UNSUCCESSFUL;
1124 }
1125 }
1126 else
1127 {
1128 LOGREL(("vboxWddmPickResources failed Status(0x%x), returning err", Status));
1129 Status = STATUS_UNSUCCESSFUL;
1130 }
1131 }
1132 else
1133 {
1134 LOGREL(("DxgkCbGetDeviceInformation failed Status(0x%x), returning err", Status));
1135 }
1136 }
1137 else
1138 {
1139 LOGREL(("invalid parameter, returning err"));
1140 Status = STATUS_INVALID_PARAMETER;
1141 }
1142
1143 LOGF(("LEAVE, status(0x%x)", Status));
1144
1145 return Status;
1146}
1147
1148NTSTATUS DxgkDdiStopDevice(
1149 IN CONST PVOID MiniportDeviceContext
1150 )
1151{
1152 /* The DxgkDdiStopDevice function should be made pageable. */
1153 PAGED_CODE();
1154
1155 LOGF(("ENTER, context(0x%p)", MiniportDeviceContext));
1156
1157 vboxVDbgBreakFv();
1158
1159 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1160 NTSTATUS Status = STATUS_SUCCESS;
1161
1162 vboxVideoCmTerm(&pDevExt->CmMgr);
1163
1164 /* do everything we did on DxgkDdiStartDevice in the reverse order */
1165#ifdef VBOX_WITH_VIDEOHWACCEL
1166 vboxVhwaFree(pDevExt);
1167#endif
1168#if 0
1169 vboxShRcTreeTerm(pDevExt);
1170#endif
1171
1172 int rc = vboxWddmFreeDisplays(pDevExt);
1173 if (RT_SUCCESS(rc))
1174 VBoxFreeDisplaysHGSMI(VBoxCommonFromDeviceExt(pDevExt));
1175 AssertRC(rc);
1176 if (RT_SUCCESS(rc))
1177 {
1178 vboxWddmVGuidFree(pDevExt);
1179
1180 /* revert back to the state we were right after the DxgkDdiAddDevice */
1181 vboxWddmDevExtZeroinit(pDevExt, pDevExt->pPDO);
1182 }
1183 else
1184 Status = STATUS_UNSUCCESSFUL;
1185
1186 return Status;
1187}
1188
1189NTSTATUS DxgkDdiRemoveDevice(
1190 IN CONST PVOID MiniportDeviceContext
1191 )
1192{
1193 /* DxgkDdiRemoveDevice should be made pageable. */
1194 PAGED_CODE();
1195
1196 LOGF(("ENTER, context(0x%p)", MiniportDeviceContext));
1197
1198 vboxVDbgBreakFv();
1199
1200 vboxWddmMemFree(MiniportDeviceContext);
1201
1202 LOGF(("LEAVE, context(0x%p)", MiniportDeviceContext));
1203
1204 return STATUS_SUCCESS;
1205}
1206
1207NTSTATUS DxgkDdiDispatchIoRequest(
1208 IN CONST PVOID MiniportDeviceContext,
1209 IN ULONG VidPnSourceId,
1210 IN PVIDEO_REQUEST_PACKET VideoRequestPacket
1211 )
1212{
1213 LOGF(("ENTER, context(0x%p), ctl(0x%x)", MiniportDeviceContext, VideoRequestPacket->IoControlCode));
1214
1215 AssertBreakpoint();
1216#if 0
1217 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1218
1219 switch (VideoRequestPacket->IoControlCode)
1220 {
1221 case IOCTL_VIDEO_QUERY_COLOR_CAPABILITIES:
1222 {
1223 if (VideoRequestPacket->OutputBufferLength < sizeof(VIDEO_COLOR_CAPABILITIES))
1224 {
1225 AssertBreakpoint();
1226 VideoRequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1227 return TRUE;
1228 }
1229 VIDEO_COLOR_CAPABILITIES *pCaps = (VIDEO_COLOR_CAPABILITIES*)VideoRequestPacket->OutputBuffer;
1230
1231 pCaps->Length = sizeof (VIDEO_COLOR_CAPABILITIES);
1232 pCaps->AttributeFlags = VIDEO_DEVICE_COLOR;
1233 pCaps->RedPhosphoreDecay = 0;
1234 pCaps->GreenPhosphoreDecay = 0;
1235 pCaps->BluePhosphoreDecay = 0;
1236 pCaps->WhiteChromaticity_x = 3127;
1237 pCaps->WhiteChromaticity_y = 3290;
1238 pCaps->WhiteChromaticity_Y = 0;
1239 pCaps->RedChromaticity_x = 6700;
1240 pCaps->RedChromaticity_y = 3300;
1241 pCaps->GreenChromaticity_x = 2100;
1242 pCaps->GreenChromaticity_y = 7100;
1243 pCaps->BlueChromaticity_x = 1400;
1244 pCaps->BlueChromaticity_y = 800;
1245 pCaps->WhiteGamma = 0;
1246 pCaps->RedGamma = 20000;
1247 pCaps->GreenGamma = 20000;
1248 pCaps->BlueGamma = 20000;
1249
1250 VideoRequestPacket->StatusBlock->Status = NO_ERROR;
1251 VideoRequestPacket->StatusBlock->Information = sizeof (VIDEO_COLOR_CAPABILITIES);
1252 break;
1253 }
1254#if 0
1255 case IOCTL_VIDEO_HANDLE_VIDEOPARAMETERS:
1256 {
1257 if (VideoRequestPacket->OutputBufferLength < sizeof(VIDEOPARAMETERS)
1258 || VideoRequestPacket->InputBufferLength < sizeof(VIDEOPARAMETERS))
1259 {
1260 AssertBreakpoint();
1261 VideoRequestPacket->StatusBlock->Status = ERROR_INSUFFICIENT_BUFFER;
1262 return TRUE;
1263 }
1264
1265 Result = VBoxVideoResetDevice((PVBOXMP_DEVEXT)HwDeviceExtension,
1266 RequestPacket->StatusBlock);
1267 break;
1268 }
1269#endif
1270 default:
1271 AssertBreakpoint();
1272 VideoRequestPacket->StatusBlock->Status = ERROR_INVALID_FUNCTION;
1273 VideoRequestPacket->StatusBlock->Information = 0;
1274 }
1275#endif
1276 LOGF(("LEAVE, context(0x%p), ctl(0x%x)", MiniportDeviceContext, VideoRequestPacket->IoControlCode));
1277
1278 return STATUS_SUCCESS;
1279}
1280
1281BOOLEAN DxgkDdiInterruptRoutine(
1282 IN CONST PVOID MiniportDeviceContext,
1283 IN ULONG MessageNumber
1284 )
1285{
1286// LOGF(("ENTER, context(0x%p), msg(0x%x)", MiniportDeviceContext, MessageNumber));
1287
1288 vboxVDbgBreakFv();
1289
1290 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1291 BOOLEAN bOur = FALSE;
1292 BOOLEAN bNeedDpc = FALSE;
1293 if (VBoxCommonFromDeviceExt(pDevExt)->hostCtx.pfHostFlags) /* If HGSMI is enabled at all. */
1294 {
1295 VBOXVTLIST CtlList;
1296#ifdef VBOX_WITH_VDMA
1297 VBOXVTLIST DmaCmdList;
1298#endif
1299 vboxVtListInit(&CtlList);
1300#ifdef VBOX_WITH_VDMA
1301 vboxVtListInit(&DmaCmdList);
1302#endif
1303
1304#ifdef VBOX_WITH_VIDEOHWACCEL
1305 VBOXVTLIST VhwaCmdList;
1306 vboxVtListInit(&VhwaCmdList);
1307#endif
1308
1309 uint32_t flags = VBoxCommonFromDeviceExt(pDevExt)->hostCtx.pfHostFlags->u32HostFlags;
1310 bOur = (flags & HGSMIHOSTFLAGS_IRQ);
1311 do
1312 {
1313 if (flags & HGSMIHOSTFLAGS_GCOMMAND_COMPLETED)
1314 {
1315 /* read the command offset */
1316 HGSMIOFFSET offCmd = VBoxVideoCmnPortReadUlong(VBoxCommonFromDeviceExt(pDevExt)->guestCtx.port);
1317 Assert(offCmd != HGSMIOFFSET_VOID);
1318 if (offCmd != HGSMIOFFSET_VOID)
1319 {
1320 VBOXWDDM_HGSMICMD_TYPE enmType = vboxWddmHgsmiGetCmdTypeFromOffset(pDevExt, offCmd);
1321 PVBOXVTLIST pList;
1322 PVBOXSHGSMI pHeap = NULL;
1323 switch (enmType)
1324 {
1325#ifdef VBOX_WITH_VDMA
1326 case VBOXWDDM_HGSMICMD_TYPE_DMACMD:
1327 pList = &DmaCmdList;
1328 pHeap = &pDevExt->u.primary.Vdma.CmdHeap;
1329 break;
1330#endif
1331 case VBOXWDDM_HGSMICMD_TYPE_CTL:
1332 pList = &CtlList;
1333 pHeap = &VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx;
1334 break;
1335 default:
1336 AssertBreakpoint();
1337 }
1338
1339 if (pHeap)
1340 {
1341 uint16_t chInfo;
1342 uint8_t *pvCmd = HGSMIBufferDataAndChInfoFromOffset (&pHeap->Heap.area, offCmd, &chInfo);
1343 Assert(pvCmd);
1344 if (pvCmd)
1345 {
1346 switch (chInfo)
1347 {
1348#ifdef VBOX_WITH_VDMA
1349 case VBVA_VDMA_CMD:
1350 case VBVA_VDMA_CTL:
1351 {
1352 int rc = VBoxSHGSMICommandProcessCompletion (pHeap, (VBOXSHGSMIHEADER*)pvCmd, TRUE /*bool bIrq*/ , pList);
1353 AssertRC(rc);
1354 break;
1355 }
1356#endif
1357#ifdef VBOX_WITH_VIDEOHWACCEL
1358 case VBVA_VHWA_CMD:
1359 {
1360 vboxVhwaPutList(&VhwaCmdList, (VBOXVHWACMD*)pvCmd);
1361 break;
1362 }
1363#endif /* # ifdef VBOX_WITH_VIDEOHWACCEL */
1364 default:
1365 AssertBreakpoint();
1366 }
1367 }
1368 }
1369 }
1370 }
1371 else if (flags & HGSMIHOSTFLAGS_COMMANDS_PENDING)
1372 {
1373 AssertBreakpoint();
1374 /* @todo: FIXME: implement !!! */
1375 }
1376 else
1377 break;
1378
1379 flags = VBoxCommonFromDeviceExt(pDevExt)->hostCtx.pfHostFlags->u32HostFlags;
1380 } while (1);
1381
1382 if (!vboxVtListIsEmpty(&CtlList))
1383 {
1384 vboxVtListCat(&pDevExt->CtlList, &CtlList);
1385 bNeedDpc = TRUE;
1386 }
1387#ifdef VBOX_WITH_VDMA
1388 if (!vboxVtListIsEmpty(&DmaCmdList))
1389 {
1390 vboxVtListCat(&pDevExt->DmaCmdList, &DmaCmdList);
1391 bNeedDpc = TRUE;
1392 }
1393#endif
1394 if (!vboxVtListIsEmpty(&VhwaCmdList))
1395 {
1396 vboxVtListCat(&pDevExt->VhwaCmdList, &VhwaCmdList);
1397 bNeedDpc = TRUE;
1398 }
1399
1400 bNeedDpc |= !vboxVdmaDdiCmdIsCompletedListEmptyIsr(pDevExt);
1401
1402 if (pDevExt->bNotifyDxDpc)
1403 {
1404// Assert(bNeedDpc == TRUE);
1405// pDevExt->bNotifyDxDpc = TRUE;
1406// pDevExt->bSetNotifyDxDpc = FALSE;
1407 bNeedDpc = TRUE;
1408 }
1409
1410 if (bOur)
1411 {
1412 VBoxHGSMIClearIrq(&VBoxCommonFromDeviceExt(pDevExt)->hostCtx);
1413#if 0 //def DEBUG_misha
1414 /* this is not entirely correct since host may concurrently complete some commands and raise a new IRQ while we are here,
1415 * still this allows to check that the host flags are correctly cleared after the ISR */
1416 Assert(VBoxCommonFromDeviceExt(pDevExt)->hostCtx.pfHostFlags);
1417 uint32_t flags = VBoxCommonFromDeviceExt(pDevExt)->hostCtx.pfHostFlags->u32HostFlags;
1418 Assert(flags == 0);
1419#endif
1420 }
1421
1422 if (bNeedDpc)
1423 {
1424 pDevExt->u.primary.DxgkInterface.DxgkCbQueueDpc(pDevExt->u.primary.DxgkInterface.DeviceHandle);
1425 }
1426 }
1427
1428// LOGF(("LEAVE, context(0x%p), bOur(0x%x)", MiniportDeviceContext, (ULONG)bOur));
1429
1430 return bOur;
1431}
1432
1433
1434typedef struct VBOXWDDM_DPCDATA
1435{
1436 VBOXVTLIST CtlList;
1437#ifdef VBOX_WITH_VDMA
1438 VBOXVTLIST DmaCmdList;
1439#endif
1440#ifdef VBOX_WITH_VIDEOHWACCEL
1441 VBOXVTLIST VhwaCmdList;
1442#endif
1443 LIST_ENTRY CompletedDdiCmdQueue;
1444 BOOL bNotifyDpc;
1445} VBOXWDDM_DPCDATA, *PVBOXWDDM_DPCDATA;
1446
1447typedef struct VBOXWDDM_GETDPCDATA_CONTEXT
1448{
1449 PVBOXMP_DEVEXT pDevExt;
1450 VBOXWDDM_DPCDATA data;
1451} VBOXWDDM_GETDPCDATA_CONTEXT, *PVBOXWDDM_GETDPCDATA_CONTEXT;
1452
1453BOOLEAN vboxWddmGetDPCDataCallback(PVOID Context)
1454{
1455 PVBOXWDDM_GETDPCDATA_CONTEXT pdc = (PVBOXWDDM_GETDPCDATA_CONTEXT)Context;
1456
1457 vboxVtListDetach2List(&pdc->pDevExt->CtlList, &pdc->data.CtlList);
1458#ifdef VBOX_WITH_VDMA
1459 vboxVtListDetach2List(&pdc->pDevExt->DmaCmdList, &pdc->data.DmaCmdList);
1460#endif
1461#ifdef VBOX_WITH_VIDEOHWACCEL
1462 vboxVtListDetach2List(&pdc->pDevExt->VhwaCmdList, &pdc->data.VhwaCmdList);
1463#endif
1464 vboxVdmaDdiCmdGetCompletedListIsr(pdc->pDevExt, &pdc->data.CompletedDdiCmdQueue);
1465
1466 pdc->data.bNotifyDpc = pdc->pDevExt->bNotifyDxDpc;
1467 pdc->pDevExt->bNotifyDxDpc = FALSE;
1468 return TRUE;
1469}
1470
1471VOID DxgkDdiDpcRoutine(
1472 IN CONST PVOID MiniportDeviceContext
1473 )
1474{
1475// LOGF(("ENTER, context(0x%p)", MiniportDeviceContext));
1476
1477 vboxVDbgBreakFv();
1478
1479 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1480
1481 VBOXWDDM_GETDPCDATA_CONTEXT context = {0};
1482 BOOLEAN bRet;
1483
1484 context.pDevExt = pDevExt;
1485
1486 /* get DPC data at IRQL */
1487 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
1488 pDevExt->u.primary.DxgkInterface.DeviceHandle,
1489 vboxWddmGetDPCDataCallback,
1490 &context,
1491 0, /* IN ULONG MessageNumber */
1492 &bRet);
1493 Assert(Status == STATUS_SUCCESS);
1494
1495 if (context.data.bNotifyDpc)
1496 pDevExt->u.primary.DxgkInterface.DxgkCbNotifyDpc(pDevExt->u.primary.DxgkInterface.DeviceHandle);
1497
1498 if (!vboxVtListIsEmpty(&context.data.CtlList))
1499 {
1500 int rc = VBoxSHGSMICommandPostprocessCompletion (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, &context.data.CtlList);
1501 AssertRC(rc);
1502 }
1503#ifdef VBOX_WITH_VDMA
1504 if (!vboxVtListIsEmpty(&context.data.DmaCmdList))
1505 {
1506 int rc = VBoxSHGSMICommandPostprocessCompletion (&pDevExt->u.primary.Vdma.CmdHeap, &context.data.DmaCmdList);
1507 AssertRC(rc);
1508 }
1509#endif
1510#ifdef VBOX_WITH_VIDEOHWACCEL
1511 if (!vboxVtListIsEmpty(&context.data.VhwaCmdList))
1512 {
1513 vboxVhwaCompletionListProcess(pDevExt, &context.data.VhwaCmdList);
1514 }
1515#endif
1516
1517 vboxVdmaDdiCmdHandleCompletedList(pDevExt, &context.data.CompletedDdiCmdQueue);
1518
1519// LOGF(("LEAVE, context(0x%p)", MiniportDeviceContext));
1520}
1521
1522NTSTATUS DxgkDdiQueryChildRelations(
1523 IN CONST PVOID MiniportDeviceContext,
1524 IN OUT PDXGK_CHILD_DESCRIPTOR ChildRelations,
1525 IN ULONG ChildRelationsSize
1526 )
1527{
1528 /* The DxgkDdiQueryChildRelations function should be made pageable. */
1529 PAGED_CODE();
1530
1531 vboxVDbgBreakFv();
1532
1533 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1534
1535 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
1536 Assert(ChildRelationsSize == (VBoxCommonFromDeviceExt(pDevExt)->cDisplays + 1)*sizeof(DXGK_CHILD_DESCRIPTOR));
1537 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
1538 {
1539 ChildRelations[i].ChildDeviceType = TypeVideoOutput;
1540 ChildRelations[i].ChildCapabilities.Type.VideoOutput.InterfaceTechnology = D3DKMDT_VOT_HD15; /* VGA */
1541 ChildRelations[i].ChildCapabilities.Type.VideoOutput.MonitorOrientationAwareness = D3DKMDT_MOA_INTERRUPTIBLE; /* ?? D3DKMDT_MOA_NONE*/
1542 ChildRelations[i].ChildCapabilities.Type.VideoOutput.SupportsSdtvModes = FALSE;
1543 ChildRelations[i].ChildCapabilities.HpdAwareness = HpdAwarenessInterruptible; /* ?? HpdAwarenessAlwaysConnected; */
1544 ChildRelations[i].AcpiUid = 0; /* */
1545 ChildRelations[i].ChildUid = i; /* should be == target id */
1546 }
1547 LOGF(("LEAVE, context(0x%x)", MiniportDeviceContext));
1548 return STATUS_SUCCESS;
1549}
1550
1551NTSTATUS DxgkDdiQueryChildStatus(
1552 IN CONST PVOID MiniportDeviceContext,
1553 IN PDXGK_CHILD_STATUS ChildStatus,
1554 IN BOOLEAN NonDestructiveOnly
1555 )
1556{
1557 /* The DxgkDdiQueryChildStatus should be made pageable. */
1558 PAGED_CODE();
1559
1560 vboxVDbgBreakFv();
1561
1562 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
1563
1564 NTSTATUS Status = STATUS_SUCCESS;
1565 switch (ChildStatus->Type)
1566 {
1567 case StatusConnection:
1568 ChildStatus->HotPlug.Connected = TRUE;
1569 LOGF(("StatusConnection"));
1570 break;
1571 case StatusRotation:
1572 ChildStatus->Rotation.Angle = 0;
1573 LOGF(("StatusRotation"));
1574 break;
1575 default:
1576 LOGREL(("ERROR: status type: %d", ChildStatus->Type));
1577 AssertBreakpoint();
1578 Status = STATUS_INVALID_PARAMETER;
1579 break;
1580 }
1581
1582 LOGF(("LEAVE, context(0x%x)", MiniportDeviceContext));
1583
1584 return Status;
1585}
1586
1587NTSTATUS DxgkDdiQueryDeviceDescriptor(
1588 IN CONST PVOID MiniportDeviceContext,
1589 IN ULONG ChildUid,
1590 IN OUT PDXGK_DEVICE_DESCRIPTOR DeviceDescriptor
1591 )
1592{
1593 /* The DxgkDdiQueryDeviceDescriptor should be made pageable. */
1594 PAGED_CODE();
1595
1596 vboxVDbgBreakFv();
1597
1598 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
1599
1600 LOGF(("LEAVE, context(0x%x)", MiniportDeviceContext));
1601
1602 /* we do not support EDID */
1603 return STATUS_MONITOR_NO_DESCRIPTOR;
1604}
1605
1606NTSTATUS DxgkDdiSetPowerState(
1607 IN CONST PVOID MiniportDeviceContext,
1608 IN ULONG DeviceUid,
1609 IN DEVICE_POWER_STATE DevicePowerState,
1610 IN POWER_ACTION ActionType
1611 )
1612{
1613 /* The DxgkDdiSetPowerState function should be made pageable. */
1614 PAGED_CODE();
1615
1616 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
1617
1618 vboxVDbgBreakFv();
1619
1620 LOGF(("LEAVE, context(0x%x)", MiniportDeviceContext));
1621
1622 return STATUS_SUCCESS;
1623}
1624
1625NTSTATUS DxgkDdiNotifyAcpiEvent(
1626 IN CONST PVOID MiniportDeviceContext,
1627 IN DXGK_EVENT_TYPE EventType,
1628 IN ULONG Event,
1629 IN PVOID Argument,
1630 OUT PULONG AcpiFlags
1631 )
1632{
1633 LOGF(("ENTER, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
1634
1635 vboxVDbgBreakF();
1636
1637 LOGF(("LEAVE, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
1638
1639 return STATUS_SUCCESS;
1640}
1641
1642VOID DxgkDdiResetDevice(
1643 IN CONST PVOID MiniportDeviceContext
1644 )
1645{
1646 /* DxgkDdiResetDevice can be called at any IRQL, so it must be in nonpageable memory. */
1647 vboxVDbgBreakF();
1648
1649
1650
1651 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
1652 LOGF(("LEAVE, context(0x%x)", MiniportDeviceContext));
1653}
1654
1655VOID DxgkDdiUnload(
1656 VOID
1657 )
1658{
1659 /* DxgkDdiUnload should be made pageable. */
1660 PAGED_CODE();
1661 LOGF((": unloading"));
1662
1663 vboxVDbgBreakFv();
1664
1665 VbglTerminate();
1666
1667 VBoxWddmVrTerm();
1668
1669 PRTLOGGER pLogger = RTLogRelSetDefaultInstance(NULL);
1670 if (pLogger)
1671 {
1672 RTLogDestroy(pLogger);
1673 }
1674 pLogger = RTLogSetDefaultInstance(NULL);
1675 if (pLogger)
1676 {
1677 RTLogDestroy(pLogger);
1678 }
1679}
1680
1681NTSTATUS DxgkDdiQueryInterface(
1682 IN CONST PVOID MiniportDeviceContext,
1683 IN PQUERY_INTERFACE QueryInterface
1684 )
1685{
1686 LOGF(("ENTER, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
1687
1688 vboxVDbgBreakFv();
1689
1690 LOGF(("LEAVE, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
1691
1692 return STATUS_NOT_SUPPORTED;
1693}
1694
1695VOID DxgkDdiControlEtwLogging(
1696 IN BOOLEAN Enable,
1697 IN ULONG Flags,
1698 IN UCHAR Level
1699 )
1700{
1701 LOGF(("ENTER"));
1702
1703 vboxVDbgBreakF();
1704
1705 LOGF(("LEAVE"));
1706}
1707
1708/**
1709 * DxgkDdiQueryAdapterInfo
1710 */
1711NTSTATUS APIENTRY DxgkDdiQueryAdapterInfo(
1712 CONST HANDLE hAdapter,
1713 CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo)
1714{
1715 /* The DxgkDdiQueryAdapterInfo should be made pageable. */
1716 PAGED_CODE();
1717
1718 LOGF(("ENTER, context(0x%x), Query type (%d)", hAdapter, pQueryAdapterInfo->Type));
1719 NTSTATUS Status = STATUS_SUCCESS;
1720 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
1721
1722 vboxVDbgBreakFv();
1723
1724 switch (pQueryAdapterInfo->Type)
1725 {
1726 case DXGKQAITYPE_DRIVERCAPS:
1727 {
1728 DXGK_DRIVERCAPS *pCaps = (DXGK_DRIVERCAPS*)pQueryAdapterInfo->pOutputData;
1729
1730 pCaps->HighestAcceptableAddress.QuadPart = ~((uintptr_t)0);
1731 pCaps->MaxAllocationListSlotId = 16;
1732 pCaps->ApertureSegmentCommitLimit = 0;
1733 pCaps->MaxPointerWidth = VBOXWDDM_C_POINTER_MAX_WIDTH;
1734 pCaps->MaxPointerHeight = VBOXWDDM_C_POINTER_MAX_HEIGHT;
1735 pCaps->PointerCaps.Value = 3; /* Monochrome , Color*/ /* MaskedColor == Value | 4, dosable for now */
1736 pCaps->InterruptMessageNumber = 0;
1737 pCaps->NumberOfSwizzlingRanges = 0;
1738 pCaps->MaxOverlays = 0;
1739#ifdef VBOX_WITH_VIDEOHWACCEL
1740 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
1741 {
1742 if ( pDevExt->aSources[i].Vhwa.Settings.fFlags & VBOXVHWA_F_ENABLED)
1743 pCaps->MaxOverlays += pDevExt->aSources[i].Vhwa.Settings.cOverlaysSupported;
1744 }
1745#endif
1746 pCaps->GammaRampCaps.Value = 0;
1747 pCaps->PresentationCaps.Value = 0;
1748 pCaps->PresentationCaps.NoScreenToScreenBlt = 1;
1749 pCaps->PresentationCaps.NoOverlapScreenBlt = 1;
1750 pCaps->MaxQueuedFlipOnVSync = 0; /* do we need it? */
1751 pCaps->FlipCaps.Value = 0;
1752 /* ? pCaps->FlipCaps.FlipOnVSyncWithNoWait = 1; */
1753 pCaps->SchedulingCaps.Value = 0;
1754 /* we might need it for Aero.
1755 * Setting this flag means we support DeviceContext, i.e.
1756 * DxgkDdiCreateContext and DxgkDdiDestroyContext
1757 */
1758 pCaps->SchedulingCaps.MultiEngineAware = 1;
1759 pCaps->MemoryManagementCaps.Value = 0;
1760 /* @todo: this correlates with pCaps->SchedulingCaps.MultiEngineAware */
1761 pCaps->MemoryManagementCaps.PagingNode = 0;
1762 /* @todo: this correlates with pCaps->SchedulingCaps.MultiEngineAware */
1763 pCaps->GpuEngineTopology.NbAsymetricProcessingNodes = VBOXWDDM_NUM_NODES;
1764
1765 break;
1766 }
1767 case DXGKQAITYPE_QUERYSEGMENT:
1768 {
1769 /* no need for DXGK_QUERYSEGMENTIN as it contains AGP aperture info, which (AGP aperture) we do not support
1770 * DXGK_QUERYSEGMENTIN *pQsIn = (DXGK_QUERYSEGMENTIN*)pQueryAdapterInfo->pInputData; */
1771 DXGK_QUERYSEGMENTOUT *pQsOut = (DXGK_QUERYSEGMENTOUT*)pQueryAdapterInfo->pOutputData;
1772#ifdef VBOXWDDM_RENDER_FROM_SHADOW
1773# define VBOXWDDM_SEGMENTS_COUNT 2
1774#else
1775# define VBOXWDDM_SEGMENTS_COUNT 1
1776#endif
1777 if (!pQsOut->pSegmentDescriptor)
1778 {
1779 /* we are requested to provide the number of segments we support */
1780 pQsOut->NbSegment = VBOXWDDM_SEGMENTS_COUNT;
1781 }
1782 else if (pQsOut->NbSegment != VBOXWDDM_SEGMENTS_COUNT)
1783 {
1784 AssertBreakpoint();
1785 LOGREL(("NbSegment (%d) != 1", pQsOut->NbSegment));
1786 Status = STATUS_INVALID_PARAMETER;
1787 }
1788 else
1789 {
1790 DXGK_SEGMENTDESCRIPTOR* pDr = pQsOut->pSegmentDescriptor;
1791 /* we are requested to provide segment information */
1792 pDr->BaseAddress.QuadPart = 0;
1793 pDr->CpuTranslatedAddress = VBoxCommonFromDeviceExt(pDevExt)->phVRAM;
1794 /* make sure the size is page aligned */
1795 /* @todo: need to setup VBVA buffers and adjust the mem size here */
1796 pDr->Size = vboxWddmVramCpuVisibleSegmentSize(pDevExt);
1797 pDr->NbOfBanks = 0;
1798 pDr->pBankRangeTable = 0;
1799 pDr->CommitLimit = pDr->Size;
1800 pDr->Flags.Value = 0;
1801 pDr->Flags.CpuVisible = 1;
1802#ifdef VBOXWDDM_RENDER_FROM_SHADOW
1803 ++pDr;
1804 /* create cpu-invisible segment of the same size */
1805 pDr->BaseAddress.QuadPart = 0;
1806 pDr->CpuTranslatedAddress.QuadPart = 0;
1807 /* make sure the size is page aligned */
1808 /* @todo: need to setup VBVA buffers and adjust the mem size here */
1809 pDr->Size = vboxWddmVramCpuInvisibleSegmentSize(pDevExt);
1810 pDr->NbOfBanks = 0;
1811 pDr->pBankRangeTable = 0;
1812 pDr->CommitLimit = pDr->Size;
1813 pDr->Flags.Value = 0;
1814#endif
1815
1816 pQsOut->PagingBufferSegmentId = 0;
1817 pQsOut->PagingBufferSize = 1024;
1818 pQsOut->PagingBufferPrivateDataSize = 0; /* @todo: do we need a private buffer ? */
1819 }
1820 break;
1821 }
1822 case DXGKQAITYPE_UMDRIVERPRIVATE:
1823 Assert (pQueryAdapterInfo->OutputDataSize >= sizeof (VBOXWDDM_QI));
1824 if (pQueryAdapterInfo->OutputDataSize >= sizeof (VBOXWDDM_QI))
1825 {
1826 VBOXWDDM_QI * pQi = (VBOXWDDM_QI*)pQueryAdapterInfo->pOutputData;
1827 memset (pQi, 0, sizeof (VBOXWDDM_QI));
1828 pQi->u32Version = VBOXVIDEOIF_VERSION;
1829 pQi->cInfos = VBoxCommonFromDeviceExt(pDevExt)->cDisplays;
1830#ifdef VBOX_WITH_VIDEOHWACCEL
1831 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
1832 {
1833 pQi->aInfos[i] = pDevExt->aSources[i].Vhwa.Settings;
1834 }
1835#endif
1836 }
1837 else
1838 {
1839 LOGREL(("buffer too small"));
1840 Status = STATUS_BUFFER_TOO_SMALL;
1841 }
1842 break;
1843 default:
1844 LOGREL(("unsupported Type (%d)", pQueryAdapterInfo->Type));
1845 AssertBreakpoint();
1846 Status = STATUS_NOT_SUPPORTED;
1847 break;
1848 }
1849 LOGF(("LEAVE, context(0x%x), Status(0x%x)", hAdapter, Status));
1850 return Status;
1851}
1852
1853/**
1854 * DxgkDdiCreateDevice
1855 */
1856NTSTATUS APIENTRY DxgkDdiCreateDevice(
1857 CONST HANDLE hAdapter,
1858 DXGKARG_CREATEDEVICE* pCreateDevice)
1859{
1860 /* DxgkDdiCreateDevice should be made pageable. */
1861 PAGED_CODE();
1862
1863 LOGF(("ENTER, context(0x%x)", hAdapter));
1864 NTSTATUS Status = STATUS_SUCCESS;
1865 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
1866
1867 vboxVDbgBreakFv();
1868
1869 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)vboxWddmMemAllocZero(sizeof (VBOXWDDM_DEVICE));
1870 pCreateDevice->hDevice = pDevice;
1871 if (pCreateDevice->Flags.SystemDevice)
1872 pDevice->enmType = VBOXWDDM_DEVICE_TYPE_SYSTEM;
1873
1874 pDevice->pAdapter = pDevExt;
1875 pDevice->hDevice = pCreateDevice->hDevice;
1876
1877 pCreateDevice->hDevice = pDevice;
1878 pCreateDevice->pInfo = NULL;
1879
1880 LOGF(("LEAVE, context(0x%x), Status(0x%x)", hAdapter, Status));
1881
1882 return Status;
1883}
1884
1885PVBOXWDDM_RESOURCE vboxWddmResourceCreate(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_RCINFO pRcInfo)
1886{
1887 PVBOXWDDM_RESOURCE pResource = (PVBOXWDDM_RESOURCE)vboxWddmMemAllocZero(RT_OFFSETOF(VBOXWDDM_RESOURCE, aAllocations[pRcInfo->cAllocInfos]));
1888 if (!pResource)
1889 {
1890 AssertFailed();
1891 return NULL;
1892 }
1893 pResource->cRefs = 1;
1894 pResource->cAllocations = pRcInfo->cAllocInfos;
1895 pResource->fFlags = pRcInfo->fFlags;
1896 pResource->RcDesc = pRcInfo->RcDesc;
1897 return pResource;
1898}
1899
1900VOID vboxWddmResourceRetain(PVBOXWDDM_RESOURCE pResource)
1901{
1902 ASMAtomicIncU32(&pResource->cRefs);
1903}
1904
1905static VOID vboxWddmResourceDestroy(PVBOXWDDM_RESOURCE pResource)
1906{
1907 vboxWddmMemFree(pResource);
1908}
1909
1910VOID vboxWddmResourceWaitDereference(PVBOXWDDM_RESOURCE pResource)
1911{
1912 vboxWddmCounterU32Wait(&pResource->cRefs, 1);
1913}
1914
1915VOID vboxWddmResourceRelease(PVBOXWDDM_RESOURCE pResource)
1916{
1917 uint32_t cRefs = ASMAtomicDecU32(&pResource->cRefs);
1918 Assert(cRefs < UINT32_MAX/2);
1919 if (!cRefs)
1920 {
1921 vboxWddmResourceDestroy(pResource);
1922 }
1923}
1924
1925void vboxWddmAllocationDeleteFromResource(PVBOXWDDM_RESOURCE pResource, PVBOXWDDM_ALLOCATION pAllocation)
1926{
1927 Assert(pAllocation->pResource == pResource);
1928 if (pResource)
1929 {
1930 Assert(&pResource->aAllocations[pAllocation->iIndex] == pAllocation);
1931 vboxWddmResourceRelease(pResource);
1932 }
1933 else
1934 {
1935 vboxWddmMemFree(pAllocation);
1936 }
1937}
1938
1939VOID vboxWddmAllocationCleanup(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pAllocation)
1940{
1941 switch (pAllocation->enmType)
1942 {
1943 case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
1944 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
1945 {
1946 if (pAllocation->bAssigned)
1947 {
1948 /* @todo: do we need to notify host? */
1949 vboxWddmAssignPrimary(pDevExt, &pDevExt->aSources[pAllocation->SurfDesc.VidPnSourceId], NULL, pAllocation->SurfDesc.VidPnSourceId);
1950 }
1951
1952#if 0
1953 if (pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC)
1954 {
1955 if (pAllocation->hSharedHandle)
1956 {
1957 vboxShRcTreeRemove(pDevExt, pAllocation);
1958 }
1959 }
1960#endif
1961 break;
1962 }
1963#ifdef VBOXWDDM_RENDER_FROM_SHADOW
1964 case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
1965 {
1966 if (pAllocation->bAssigned)
1967 {
1968 Assert(pAllocation->SurfDesc.VidPnSourceId != D3DDDI_ID_UNINITIALIZED);
1969 /* @todo: do we need to notify host? */
1970 vboxWddmAssignShadow(pDevExt, &pDevExt->aSources[pAllocation->SurfDesc.VidPnSourceId], NULL, pAllocation->SurfDesc.VidPnSourceId);
1971 }
1972 break;
1973 }
1974#endif
1975 case VBOXWDDM_ALLOC_TYPE_UMD_HGSMI_BUFFER:
1976 {
1977 if (pAllocation->pSynchEvent)
1978 ObDereferenceObject(pAllocation->pSynchEvent);
1979 break;
1980 }
1981 default:
1982 break;
1983 }
1984
1985 PVBOXWDDM_SWAPCHAIN pSwapchain = vboxWddmSwapchainRetainByAlloc(pDevExt, pAllocation);
1986 if (pSwapchain)
1987 {
1988 vboxWddmSwapchainAllocRemove(pDevExt, pSwapchain, pAllocation);
1989 vboxWddmSwapchainRelease(pSwapchain);
1990 }
1991}
1992
1993VOID vboxWddmAllocationDestroy(PVBOXWDDM_ALLOCATION pAllocation)
1994{
1995 PAGED_CODE();
1996
1997 vboxWddmAllocationDeleteFromResource(pAllocation->pResource, pAllocation);
1998}
1999
2000PVBOXWDDM_ALLOCATION vboxWddmAllocationCreateFromResource(PVBOXWDDM_RESOURCE pResource, uint32_t iIndex)
2001{
2002 PVBOXWDDM_ALLOCATION pAllocation = NULL;
2003 if (pResource)
2004 {
2005 Assert(iIndex < pResource->cAllocations);
2006 if (iIndex < pResource->cAllocations)
2007 {
2008 pAllocation = &pResource->aAllocations[iIndex];
2009 memset(pAllocation, 0, sizeof (VBOXWDDM_ALLOCATION));
2010 }
2011 vboxWddmResourceRetain(pResource);
2012 }
2013 else
2014 pAllocation = (PVBOXWDDM_ALLOCATION)vboxWddmMemAllocZero(sizeof (VBOXWDDM_ALLOCATION));
2015
2016 if (pAllocation)
2017 {
2018 if (pResource)
2019 {
2020 pAllocation->pResource = pResource;
2021 pAllocation->iIndex = iIndex;
2022 }
2023 }
2024
2025 return pAllocation;
2026}
2027
2028VOID vboxWddmAllocationWaitDereference(PVBOXWDDM_ALLOCATION pAllocation)
2029{
2030 vboxWddmCounterU32Wait(&pAllocation->cRefs, 1);
2031}
2032
2033
2034NTSTATUS vboxWddmAllocationCreate(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_RESOURCE pResource, uint32_t iIndex, DXGK_ALLOCATIONINFO* pAllocationInfo)
2035{
2036 PAGED_CODE();
2037
2038 NTSTATUS Status = STATUS_SUCCESS;
2039
2040 Assert(pAllocationInfo->PrivateDriverDataSize == sizeof (VBOXWDDM_ALLOCINFO));
2041 if (pAllocationInfo->PrivateDriverDataSize >= sizeof (VBOXWDDM_ALLOCINFO))
2042 {
2043 PVBOXWDDM_ALLOCINFO pAllocInfo = (PVBOXWDDM_ALLOCINFO)pAllocationInfo->pPrivateDriverData;
2044 PVBOXWDDM_ALLOCATION pAllocation = vboxWddmAllocationCreateFromResource(pResource, iIndex);
2045 Assert(pAllocation);
2046 if (pAllocation)
2047 {
2048 pAllocationInfo->pPrivateDriverData = NULL;
2049 pAllocationInfo->PrivateDriverDataSize = 0;
2050 pAllocationInfo->Alignment = 0;
2051 pAllocationInfo->PitchAlignedSize = 0;
2052 pAllocationInfo->HintedBank.Value = 0;
2053 pAllocationInfo->PreferredSegment.Value = 0;
2054 pAllocationInfo->SupportedReadSegmentSet = 1;
2055 pAllocationInfo->SupportedWriteSegmentSet = 1;
2056 pAllocationInfo->EvictionSegmentSet = 0;
2057 pAllocationInfo->MaximumRenamingListLength = 0;
2058 pAllocationInfo->hAllocation = pAllocation;
2059 pAllocationInfo->Flags.Value = 0;
2060 pAllocationInfo->pAllocationUsageHint = NULL;
2061 pAllocationInfo->AllocationPriority = D3DDDI_ALLOCATIONPRIORITY_NORMAL;
2062
2063 pAllocation->enmType = pAllocInfo->enmType;
2064 pAllocation->offVram = VBOXVIDEOOFFSET_VOID;
2065 pAllocation->cRefs = 1;
2066 pAllocation->bVisible = FALSE;
2067 pAllocation->bAssigned = FALSE;
2068 KeInitializeSpinLock(&pAllocation->OpenLock);
2069 InitializeListHead(&pAllocation->OpenList);
2070
2071 switch (pAllocInfo->enmType)
2072 {
2073 case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
2074 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
2075 case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
2076 case VBOXWDDM_ALLOC_TYPE_STD_STAGINGSURFACE:
2077 {
2078 pAllocation->fRcFlags = pAllocInfo->fFlags;
2079 pAllocation->SurfDesc = pAllocInfo->SurfDesc;
2080
2081 pAllocationInfo->Size = pAllocInfo->SurfDesc.cbSize;
2082
2083 switch (pAllocInfo->enmType)
2084 {
2085 case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
2086#if 0 //defined(VBOXWDDM_RENDER_FROM_SHADOW)
2087 pAllocationInfo->SupportedReadSegmentSet = 2;
2088 pAllocationInfo->SupportedWriteSegmentSet = 2;
2089#endif
2090#ifndef VBOXWDDM_RENDER_FROM_SHADOW
2091 pAllocationInfo->Flags.CpuVisible = 1;
2092#endif
2093 break;
2094 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
2095#ifdef VBOX_WITH_VIDEOHWACCEL
2096 if (pAllocInfo->fFlags.Overlay)
2097 {
2098 /* actually we can not "properly" issue create overlay commands to the host here
2099 * because we do not know source VidPn id here, i.e.
2100 * the primary which is supposed to be overlayed,
2101 * however we need to get some info like pitch & size from the host here */
2102 int rc = vboxVhwaHlpGetSurfInfo(pDevExt, pAllocation);
2103 AssertRC(rc);
2104 if (RT_SUCCESS(rc))
2105 {
2106 pAllocationInfo->Flags.Overlay = 1;
2107 pAllocationInfo->Flags.CpuVisible = 1;
2108 pAllocationInfo->Size = pAllocation->SurfDesc.cbSize;
2109
2110 pAllocationInfo->AllocationPriority = D3DDDI_ALLOCATIONPRIORITY_HIGH;
2111 }
2112 else
2113 Status = STATUS_UNSUCCESSFUL;
2114 }
2115 else
2116#endif
2117 {
2118 Assert(pAllocation->SurfDesc.bpp);
2119 Assert(pAllocation->SurfDesc.pitch);
2120 Assert(pAllocation->SurfDesc.cbSize);
2121 if (!pAllocInfo->fFlags.SharedResource)
2122 {
2123 pAllocationInfo->Flags.CpuVisible = 1;
2124 }
2125 else
2126 {
2127 pAllocation->hSharedHandle = (HANDLE)pAllocInfo->hSharedHandle;
2128#if 0
2129 if (pAllocation->hSharedHandle)
2130 {
2131 vboxShRcTreePut(pDevExt, pAllocation);
2132 }
2133#endif
2134 }
2135 }
2136 break;
2137 case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
2138 case VBOXWDDM_ALLOC_TYPE_STD_STAGINGSURFACE:
2139 pAllocationInfo->Flags.CpuVisible = 1;
2140 break;
2141 }
2142
2143 if (Status == STATUS_SUCCESS)
2144 {
2145 pAllocation->UsageHint.Version = 0;
2146 pAllocation->UsageHint.v1.Flags.Value = 0;
2147 pAllocation->UsageHint.v1.Format = pAllocInfo->SurfDesc.format;
2148 pAllocation->UsageHint.v1.SwizzledFormat = 0;
2149 pAllocation->UsageHint.v1.ByteOffset = 0;
2150 pAllocation->UsageHint.v1.Width = pAllocation->SurfDesc.width;
2151 pAllocation->UsageHint.v1.Height = pAllocation->SurfDesc.height;
2152 pAllocation->UsageHint.v1.Pitch = pAllocation->SurfDesc.pitch;
2153 pAllocation->UsageHint.v1.Depth = 0;
2154 pAllocation->UsageHint.v1.SlicePitch = 0;
2155
2156 Assert(!pAllocationInfo->pAllocationUsageHint);
2157 pAllocationInfo->pAllocationUsageHint = &pAllocation->UsageHint;
2158 }
2159
2160 break;
2161 }
2162 case VBOXWDDM_ALLOC_TYPE_UMD_HGSMI_BUFFER:
2163 {
2164 pAllocationInfo->Size = pAllocInfo->cbBuffer;
2165 pAllocation->fUhgsmiType = pAllocInfo->fUhgsmiType;
2166 pAllocation->SurfDesc.cbSize = pAllocInfo->cbBuffer;
2167 pAllocationInfo->Flags.CpuVisible = 1;
2168// pAllocationInfo->Flags.SynchronousPaging = 1;
2169 pAllocationInfo->AllocationPriority = D3DDDI_ALLOCATIONPRIORITY_MAXIMUM;
2170 if (pAllocInfo->hSynch)
2171 {
2172 Status = ObReferenceObjectByHandle((HANDLE)pAllocInfo->hSynch, EVENT_MODIFY_STATE, *ExEventObjectType, UserMode,
2173 (PVOID*)&pAllocation->pSynchEvent,
2174 NULL);
2175 Assert(Status == STATUS_SUCCESS);
2176 }
2177 break;
2178 }
2179
2180 default:
2181 LOGREL(("ERROR: invalid alloc info type(%d)", pAllocInfo->enmType));
2182 AssertBreakpoint();
2183 Status = STATUS_INVALID_PARAMETER;
2184 break;
2185
2186 }
2187
2188 if (Status != STATUS_SUCCESS)
2189 vboxWddmAllocationDeleteFromResource(pResource, pAllocation);
2190 }
2191 else
2192 {
2193 LOGREL(("ERROR: failed to create allocation description"));
2194 Status = STATUS_NO_MEMORY;
2195 }
2196
2197 }
2198 else
2199 {
2200 LOGREL(("ERROR: PrivateDriverDataSize(%d) less than header size(%d)", pAllocationInfo->PrivateDriverDataSize, sizeof (VBOXWDDM_ALLOCINFO)));
2201 Status = STATUS_INVALID_PARAMETER;
2202 }
2203
2204 return Status;
2205}
2206
2207NTSTATUS APIENTRY DxgkDdiCreateAllocation(
2208 CONST HANDLE hAdapter,
2209 DXGKARG_CREATEALLOCATION* pCreateAllocation)
2210{
2211 /* DxgkDdiCreateAllocation should be made pageable. */
2212 PAGED_CODE();
2213
2214 LOGF(("ENTER, context(0x%x)", hAdapter));
2215
2216 vboxVDbgBreakFv();
2217
2218 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
2219 NTSTATUS Status = STATUS_SUCCESS;
2220 PVBOXWDDM_RESOURCE pResource = NULL;
2221
2222 if (pCreateAllocation->PrivateDriverDataSize)
2223 {
2224 Assert(pCreateAllocation->PrivateDriverDataSize == sizeof (VBOXWDDM_RCINFO));
2225 Assert(pCreateAllocation->pPrivateDriverData);
2226 if (pCreateAllocation->PrivateDriverDataSize < sizeof (VBOXWDDM_RCINFO))
2227 {
2228 WARN(("invalid private data size (%d)", pCreateAllocation->PrivateDriverDataSize));
2229 return STATUS_INVALID_PARAMETER;
2230 }
2231
2232 PVBOXWDDM_RCINFO pRcInfo = (PVBOXWDDM_RCINFO)pCreateAllocation->pPrivateDriverData;
2233// Assert(pRcInfo->RcDesc.VidPnSourceId < VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
2234 if (pRcInfo->cAllocInfos != pCreateAllocation->NumAllocations)
2235 {
2236 WARN(("invalid number of allocations passed in, (%d), expected (%d)", pRcInfo->cAllocInfos, pCreateAllocation->NumAllocations));
2237 return STATUS_INVALID_PARAMETER;
2238 }
2239
2240 /* a check to ensure we do not get the allocation size which is too big to overflow the 32bit value */
2241 if (VBOXWDDM_TRAILARRAY_MAXELEMENTSU32(VBOXWDDM_RESOURCE, aAllocations) < pRcInfo->cAllocInfos)
2242 {
2243 WARN(("number of allocations passed too big (%d), max is (%d)", pRcInfo->cAllocInfos, VBOXWDDM_TRAILARRAY_MAXELEMENTSU32(VBOXWDDM_RESOURCE, aAllocations)));
2244 return STATUS_INVALID_PARAMETER;
2245 }
2246
2247 pResource = (PVBOXWDDM_RESOURCE)vboxWddmMemAllocZero(RT_OFFSETOF(VBOXWDDM_RESOURCE, aAllocations[pRcInfo->cAllocInfos]));
2248 if (!pResource)
2249 {
2250 WARN(("vboxWddmMemAllocZero failed for (%d) allocations", pRcInfo->cAllocInfos));
2251 return STATUS_NO_MEMORY;
2252 }
2253
2254 pResource->cRefs = 1;
2255 pResource->cAllocations = pRcInfo->cAllocInfos;
2256 pResource->fFlags = pRcInfo->fFlags;
2257 pResource->RcDesc = pRcInfo->RcDesc;
2258 }
2259
2260
2261 for (UINT i = 0; i < pCreateAllocation->NumAllocations; ++i)
2262 {
2263 Status = vboxWddmAllocationCreate(pDevExt, pResource, i, &pCreateAllocation->pAllocationInfo[i]);
2264 if (Status != STATUS_SUCCESS)
2265 {
2266 WARN(("vboxWddmAllocationCreate(%d) failed, Status(0x%x)", i, Status));
2267 /* note: i-th allocation is expected to be cleared in a fail handling code above */
2268 for (UINT j = 0; j < i; ++j)
2269 {
2270 vboxWddmAllocationCleanup(pDevExt, (PVBOXWDDM_ALLOCATION)pCreateAllocation->pAllocationInfo[j].hAllocation);
2271 vboxWddmAllocationRelease((PVBOXWDDM_ALLOCATION)pCreateAllocation->pAllocationInfo[j].hAllocation);
2272 }
2273 }
2274 }
2275
2276 pCreateAllocation->hResource = pResource;
2277 if (pResource && Status != STATUS_SUCCESS)
2278 vboxWddmResourceRelease(pResource);
2279
2280 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
2281
2282 return Status;
2283}
2284
2285NTSTATUS
2286APIENTRY
2287DxgkDdiDestroyAllocation(
2288 CONST HANDLE hAdapter,
2289 CONST DXGKARG_DESTROYALLOCATION* pDestroyAllocation)
2290{
2291 /* DxgkDdiDestroyAllocation should be made pageable. */
2292 PAGED_CODE();
2293
2294 LOGF(("ENTER, context(0x%x)", hAdapter));
2295
2296 vboxVDbgBreakFv();
2297
2298 NTSTATUS Status = STATUS_SUCCESS;
2299
2300 PVBOXWDDM_RESOURCE pRc = (PVBOXWDDM_RESOURCE)pDestroyAllocation->hResource;
2301 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
2302
2303 if (pRc)
2304 {
2305 Assert(pRc->cAllocations == pDestroyAllocation->NumAllocations);
2306 }
2307
2308 for (UINT i = 0; i < pDestroyAllocation->NumAllocations; ++i)
2309 {
2310 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pDestroyAllocation->pAllocationList[i];
2311 Assert(pAlloc->pResource == pRc);
2312 /* wait for all current allocation-related ops are completed */
2313 vboxWddmAllocationWaitDereference(pAlloc);
2314 vboxWddmAllocationCleanup(pDevExt, pAlloc);
2315 vboxWddmAllocationRelease(pAlloc);
2316 }
2317
2318 if (pRc)
2319 {
2320 /* wait for all current resource-related ops are completed */
2321 vboxWddmResourceWaitDereference(pRc);
2322 vboxWddmResourceRelease(pRc);
2323 }
2324
2325 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
2326
2327 return Status;
2328}
2329
2330/**
2331 * DxgkDdiDescribeAllocation
2332 */
2333NTSTATUS
2334APIENTRY
2335DxgkDdiDescribeAllocation(
2336 CONST HANDLE hAdapter,
2337 DXGKARG_DESCRIBEALLOCATION* pDescribeAllocation)
2338{
2339// LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
2340
2341 vboxVDbgBreakFv();
2342
2343 PVBOXWDDM_ALLOCATION pAllocation = (PVBOXWDDM_ALLOCATION)pDescribeAllocation->hAllocation;
2344 pDescribeAllocation->Width = pAllocation->SurfDesc.width;
2345 pDescribeAllocation->Height = pAllocation->SurfDesc.height;
2346 pDescribeAllocation->Format = pAllocation->SurfDesc.format;
2347 memset (&pDescribeAllocation->MultisampleMethod, 0, sizeof (pDescribeAllocation->MultisampleMethod));
2348 pDescribeAllocation->RefreshRate.Numerator = 60000;
2349 pDescribeAllocation->RefreshRate.Denominator = 1000;
2350 pDescribeAllocation->PrivateDriverFormatAttribute = 0;
2351
2352// LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
2353
2354 return STATUS_SUCCESS;
2355}
2356
2357/**
2358 * DxgkDdiGetStandardAllocationDriverData
2359 */
2360NTSTATUS
2361APIENTRY
2362DxgkDdiGetStandardAllocationDriverData(
2363 CONST HANDLE hAdapter,
2364 DXGKARG_GETSTANDARDALLOCATIONDRIVERDATA* pGetStandardAllocationDriverData)
2365{
2366 /* DxgkDdiGetStandardAllocationDriverData should be made pageable. */
2367 PAGED_CODE();
2368
2369 LOGF(("ENTER, context(0x%x)", hAdapter));
2370
2371 vboxVDbgBreakFv();
2372
2373 NTSTATUS Status = STATUS_SUCCESS;
2374 PVBOXWDDM_ALLOCINFO pAllocInfo = NULL;
2375
2376 switch (pGetStandardAllocationDriverData->StandardAllocationType)
2377 {
2378 case D3DKMDT_STANDARDALLOCATION_SHAREDPRIMARYSURFACE:
2379 {
2380 LOGF(("D3DKMDT_STANDARDALLOCATION_SHAREDPRIMARYSURFACE"));
2381 if(pGetStandardAllocationDriverData->pAllocationPrivateDriverData)
2382 {
2383 pAllocInfo = (PVBOXWDDM_ALLOCINFO)pGetStandardAllocationDriverData->pAllocationPrivateDriverData;
2384 memset (pAllocInfo, 0, sizeof (VBOXWDDM_ALLOCINFO));
2385 pAllocInfo->enmType = VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE;
2386 pAllocInfo->SurfDesc.width = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Width;
2387 pAllocInfo->SurfDesc.height = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Height;
2388 pAllocInfo->SurfDesc.format = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Format;
2389 pAllocInfo->SurfDesc.bpp = vboxWddmCalcBitsPerPixel(pAllocInfo->SurfDesc.format);
2390 pAllocInfo->SurfDesc.pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Width, pAllocInfo->SurfDesc.format);
2391 pAllocInfo->SurfDesc.cbSize = vboxWddmCalcSize(pAllocInfo->SurfDesc.pitch, pAllocInfo->SurfDesc.height, pAllocInfo->SurfDesc.format);
2392 pAllocInfo->SurfDesc.depth = 0;
2393 pAllocInfo->SurfDesc.slicePitch = 0;
2394 pAllocInfo->SurfDesc.RefreshRate = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->RefreshRate;
2395 pAllocInfo->SurfDesc.VidPnSourceId = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->VidPnSourceId;
2396 }
2397 pGetStandardAllocationDriverData->AllocationPrivateDriverDataSize = sizeof (VBOXWDDM_ALLOCINFO);
2398
2399 pGetStandardAllocationDriverData->ResourcePrivateDriverDataSize = 0;
2400 break;
2401 }
2402 case D3DKMDT_STANDARDALLOCATION_SHADOWSURFACE:
2403 {
2404 LOGF(("D3DKMDT_STANDARDALLOCATION_SHADOWSURFACE"));
2405 UINT bpp = vboxWddmCalcBitsPerPixel(pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format);
2406 Assert(bpp);
2407 if (bpp != 0)
2408 {
2409 UINT Pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Width, pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format);
2410 pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Pitch = Pitch;
2411
2412 /* @todo: need [d/q]word align?? */
2413
2414 if (pGetStandardAllocationDriverData->pAllocationPrivateDriverData)
2415 {
2416 pAllocInfo = (PVBOXWDDM_ALLOCINFO)pGetStandardAllocationDriverData->pAllocationPrivateDriverData;
2417 pAllocInfo->enmType = VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE;
2418 pAllocInfo->SurfDesc.width = pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Width;
2419 pAllocInfo->SurfDesc.height = pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Height;
2420 pAllocInfo->SurfDesc.format = pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format;
2421 pAllocInfo->SurfDesc.bpp = vboxWddmCalcBitsPerPixel(pAllocInfo->SurfDesc.format);
2422 pAllocInfo->SurfDesc.pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Width, pAllocInfo->SurfDesc.format);
2423 pAllocInfo->SurfDesc.cbSize = vboxWddmCalcSize(pAllocInfo->SurfDesc.pitch, pAllocInfo->SurfDesc.height, pAllocInfo->SurfDesc.format);
2424 pAllocInfo->SurfDesc.depth = 0;
2425 pAllocInfo->SurfDesc.slicePitch = 0;
2426 pAllocInfo->SurfDesc.RefreshRate.Numerator = 0;
2427 pAllocInfo->SurfDesc.RefreshRate.Denominator = 1000;
2428 pAllocInfo->SurfDesc.VidPnSourceId = D3DDDI_ID_UNINITIALIZED;
2429
2430 pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Pitch = pAllocInfo->SurfDesc.pitch;
2431 }
2432 pGetStandardAllocationDriverData->AllocationPrivateDriverDataSize = sizeof (VBOXWDDM_ALLOCINFO);
2433
2434 pGetStandardAllocationDriverData->ResourcePrivateDriverDataSize = 0;
2435 }
2436 else
2437 {
2438 LOGREL(("Invalid format (%d)", pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format));
2439 Status = STATUS_INVALID_PARAMETER;
2440 }
2441 break;
2442 }
2443 case D3DKMDT_STANDARDALLOCATION_STAGINGSURFACE:
2444 {
2445 LOGF(("D3DKMDT_STANDARDALLOCATION_STAGINGSURFACE"));
2446 if(pGetStandardAllocationDriverData->pAllocationPrivateDriverData)
2447 {
2448 pAllocInfo = (PVBOXWDDM_ALLOCINFO)pGetStandardAllocationDriverData->pAllocationPrivateDriverData;
2449 pAllocInfo->enmType = VBOXWDDM_ALLOC_TYPE_STD_STAGINGSURFACE;
2450 pAllocInfo->SurfDesc.width = pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Width;
2451 pAllocInfo->SurfDesc.height = pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Height;
2452 pAllocInfo->SurfDesc.format = D3DDDIFMT_X8R8G8B8; /* staging has always always D3DDDIFMT_X8R8G8B8 */
2453 pAllocInfo->SurfDesc.bpp = vboxWddmCalcBitsPerPixel(pAllocInfo->SurfDesc.format);
2454 pAllocInfo->SurfDesc.pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Width, pAllocInfo->SurfDesc.format);
2455 pAllocInfo->SurfDesc.cbSize = vboxWddmCalcSize(pAllocInfo->SurfDesc.pitch, pAllocInfo->SurfDesc.height, pAllocInfo->SurfDesc.format);
2456 pAllocInfo->SurfDesc.depth = 0;
2457 pAllocInfo->SurfDesc.slicePitch = 0;
2458 pAllocInfo->SurfDesc.RefreshRate.Numerator = 0;
2459 pAllocInfo->SurfDesc.RefreshRate.Denominator = 1000;
2460 pAllocInfo->SurfDesc.VidPnSourceId = D3DDDI_ID_UNINITIALIZED;
2461
2462 pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Pitch = pAllocInfo->SurfDesc.pitch;
2463 }
2464 pGetStandardAllocationDriverData->AllocationPrivateDriverDataSize = sizeof (VBOXWDDM_ALLOCINFO);
2465
2466 pGetStandardAllocationDriverData->ResourcePrivateDriverDataSize = 0;
2467 break;
2468 }
2469//#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
2470// case D3DKMDT_STANDARDALLOCATION_GDISURFACE:
2471//# error port to Win7 DDI
2472// break;
2473//#endif
2474 default:
2475 LOGREL(("Invalid allocation type (%d)", pGetStandardAllocationDriverData->StandardAllocationType));
2476 Status = STATUS_INVALID_PARAMETER;
2477 break;
2478 }
2479
2480 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
2481
2482 return Status;
2483}
2484
2485NTSTATUS
2486APIENTRY
2487DxgkDdiAcquireSwizzlingRange(
2488 CONST HANDLE hAdapter,
2489 DXGKARG_ACQUIRESWIZZLINGRANGE* pAcquireSwizzlingRange)
2490{
2491 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
2492
2493 AssertBreakpoint();
2494
2495 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
2496
2497 return STATUS_SUCCESS;
2498}
2499
2500NTSTATUS
2501APIENTRY
2502DxgkDdiReleaseSwizzlingRange(
2503 CONST HANDLE hAdapter,
2504 CONST DXGKARG_RELEASESWIZZLINGRANGE* pReleaseSwizzlingRange)
2505{
2506 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
2507
2508 AssertBreakpoint();
2509
2510 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
2511
2512 return STATUS_SUCCESS;
2513}
2514
2515NTSTATUS
2516APIENTRY
2517DxgkDdiPatch(
2518 CONST HANDLE hAdapter,
2519 CONST DXGKARG_PATCH* pPatch)
2520{
2521 /* DxgkDdiPatch should be made pageable. */
2522 PAGED_CODE();
2523
2524 NTSTATUS Status = STATUS_SUCCESS;
2525
2526 LOGF(("ENTER, context(0x%x)", hAdapter));
2527
2528 vboxVDbgBreakFv();
2529
2530 /* Value == 2 is Present
2531 * Value == 4 is RedirectedPresent
2532 * we do not expect any other flags to be set here */
2533// Assert(pPatch->Flags.Value == 2 || pPatch->Flags.Value == 4);
2534 if (pPatch->DmaBufferPrivateDataSubmissionEndOffset - pPatch->DmaBufferPrivateDataSubmissionStartOffset >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
2535 {
2536 Assert(pPatch->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR));
2537 VBOXWDDM_DMA_PRIVATEDATA_BASEHDR *pPrivateDataBase = (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR*)((uint8_t*)pPatch->pDmaBufferPrivateData + pPatch->DmaBufferPrivateDataSubmissionStartOffset);
2538 switch (pPrivateDataBase->enmCmd)
2539 {
2540 case VBOXVDMACMD_TYPE_DMA_PRESENT_SHADOW2PRIMARY:
2541 {
2542 PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY pS2P = (PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY)pPrivateDataBase;
2543 Assert(pPatch->PatchLocationListSubmissionLength == 2);
2544 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart];
2545 Assert(pPatchList->AllocationIndex == DXGK_PRESENT_SOURCE_INDEX);
2546 Assert(pPatchList->PatchOffset == 0);
2547 const DXGK_ALLOCATIONLIST *pSrcAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2548 Assert(pSrcAllocationList->SegmentId);
2549 pS2P->Shadow2Primary.ShadowAlloc.segmentIdAlloc = pSrcAllocationList->SegmentId;
2550 pS2P->Shadow2Primary.ShadowAlloc.offAlloc = (VBOXVIDEOOFFSET)pSrcAllocationList->PhysicalAddress.QuadPart;
2551//
2552// pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart + 1];
2553// Assert(pPatchList->AllocationIndex == DXGK_PRESENT_DESTINATION_INDEX);
2554// Assert(pPatchList->PatchOffset == 4);
2555// const DXGK_ALLOCATIONLIST *pDstAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2556// Assert(pDstAllocationList->SegmentId);
2557// pPrivateData->DstAllocInfo.segmentIdAlloc = pDstAllocationList->SegmentId;
2558// pPrivateData->DstAllocInfo.offAlloc = (VBOXVIDEOOFFSET)pDstAllocationList->PhysicalAddress.QuadPart;
2559 break;
2560 }
2561 case VBOXVDMACMD_TYPE_DMA_PRESENT_BLT:
2562 {
2563 PVBOXWDDM_DMA_PRIVATEDATA_BLT pBlt = (PVBOXWDDM_DMA_PRIVATEDATA_BLT)pPrivateDataBase;
2564 Assert(pPatch->PatchLocationListSubmissionLength == 2);
2565 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart];
2566 Assert(pPatchList->AllocationIndex == DXGK_PRESENT_SOURCE_INDEX);
2567 Assert(pPatchList->PatchOffset == 0);
2568 const DXGK_ALLOCATIONLIST *pSrcAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2569 Assert(pSrcAllocationList->SegmentId);
2570 pBlt->Blt.SrcAlloc.segmentIdAlloc = pSrcAllocationList->SegmentId;
2571 pBlt->Blt.SrcAlloc.offAlloc = (VBOXVIDEOOFFSET)pSrcAllocationList->PhysicalAddress.QuadPart;
2572
2573 pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart + 1];
2574 Assert(pPatchList->AllocationIndex == DXGK_PRESENT_DESTINATION_INDEX);
2575 Assert(pPatchList->PatchOffset == 4);
2576 const DXGK_ALLOCATIONLIST *pDstAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2577 Assert(pDstAllocationList->SegmentId);
2578 pBlt->Blt.DstAlloc.segmentIdAlloc = pDstAllocationList->SegmentId;
2579 pBlt->Blt.DstAlloc.offAlloc = (VBOXVIDEOOFFSET)pDstAllocationList->PhysicalAddress.QuadPart;
2580 break;
2581 }
2582 case VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP:
2583 {
2584 PVBOXWDDM_DMA_PRIVATEDATA_FLIP pFlip = (PVBOXWDDM_DMA_PRIVATEDATA_FLIP)pPrivateDataBase;
2585 Assert(pPatch->PatchLocationListSubmissionLength == 1);
2586 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart];
2587 Assert(pPatchList->AllocationIndex == DXGK_PRESENT_SOURCE_INDEX);
2588 Assert(pPatchList->PatchOffset == 0);
2589 const DXGK_ALLOCATIONLIST *pSrcAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2590 Assert(pSrcAllocationList->SegmentId);
2591 pFlip->Flip.Alloc.segmentIdAlloc = pSrcAllocationList->SegmentId;
2592 pFlip->Flip.Alloc.offAlloc = (VBOXVIDEOOFFSET)pSrcAllocationList->PhysicalAddress.QuadPart;
2593 break;
2594 }
2595 case VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL:
2596 {
2597 PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL pCF = (PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL)pPrivateDataBase;
2598 Assert(pPatch->PatchLocationListSubmissionLength == 1);
2599 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart];
2600 Assert(pPatchList->AllocationIndex == DXGK_PRESENT_DESTINATION_INDEX);
2601 Assert(pPatchList->PatchOffset == 0);
2602 const DXGK_ALLOCATIONLIST *pDstAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2603 Assert(pDstAllocationList->SegmentId);
2604 pCF->ClrFill.Alloc.segmentIdAlloc = pDstAllocationList->SegmentId;
2605 pCF->ClrFill.Alloc.offAlloc = (VBOXVIDEOOFFSET)pDstAllocationList->PhysicalAddress.QuadPart;
2606 break;
2607 }
2608 case VBOXVDMACMD_TYPE_DMA_NOP:
2609 break;
2610 case VBOXVDMACMD_TYPE_CHROMIUM_CMD:
2611 {
2612 uint8_t * pPrivateBuf = (uint8_t*)pPrivateDataBase;
2613 for (UINT i = pPatch->PatchLocationListSubmissionStart; i < pPatch->PatchLocationListSubmissionLength; ++i)
2614 {
2615 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[i];
2616 Assert(pPatchList->AllocationIndex < pPatch->AllocationListSize);
2617 const DXGK_ALLOCATIONLIST *pAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2618 Assert(pAllocationList->SegmentId);
2619 if (pAllocationList->SegmentId)
2620 {
2621 DXGK_ALLOCATIONLIST *pAllocation2Patch = (DXGK_ALLOCATIONLIST*)(pPrivateBuf + pPatchList->PatchOffset);
2622 pAllocation2Patch->SegmentId = pAllocationList->SegmentId;
2623 pAllocation2Patch->PhysicalAddress.QuadPart = pAllocationList->PhysicalAddress.QuadPart + pPatchList->AllocationOffset;
2624 Assert(!(pAllocationList->PhysicalAddress.QuadPart & 0xfffUL)); /* <- just a check to ensure allocation offset does not go here */
2625 }
2626 }
2627 break;
2628 }
2629 default:
2630 {
2631 AssertBreakpoint();
2632 uint8_t *pBuf = ((uint8_t *)pPatch->pDmaBuffer) + pPatch->DmaBufferSubmissionStartOffset;
2633 for (UINT i = pPatch->PatchLocationListSubmissionStart; i < pPatch->PatchLocationListSubmissionLength; ++i)
2634 {
2635 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[i];
2636 Assert(pPatchList->AllocationIndex < pPatch->AllocationListSize);
2637 const DXGK_ALLOCATIONLIST *pAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2638 if (pAllocationList->SegmentId)
2639 {
2640 Assert(pPatchList->PatchOffset < (pPatch->DmaBufferSubmissionEndOffset - pPatch->DmaBufferSubmissionStartOffset));
2641 *((VBOXVIDEOOFFSET*)(pBuf+pPatchList->PatchOffset)) = (VBOXVIDEOOFFSET)pAllocationList->PhysicalAddress.QuadPart;
2642 }
2643 else
2644 {
2645 /* sanity */
2646 if (pPatch->Flags.Value == 2 || pPatch->Flags.Value == 4)
2647 Assert(i == 0);
2648 }
2649 }
2650 break;
2651 }
2652 }
2653 }
2654 else if (pPatch->DmaBufferPrivateDataSubmissionEndOffset == pPatch->DmaBufferPrivateDataSubmissionStartOffset)
2655 {
2656 /* this is a NOP, just return success */
2657 WARN(("null data size, treating as NOP"));
2658 return STATUS_SUCCESS;
2659 }
2660 else
2661 {
2662 WARN(("DmaBufferPrivateDataSubmissionEndOffset (%d) - DmaBufferPrivateDataSubmissionStartOffset (%d) < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR) (%d)",
2663 pPatch->DmaBufferPrivateDataSubmissionEndOffset,
2664 pPatch->DmaBufferPrivateDataSubmissionStartOffset,
2665 sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
2666 return STATUS_INVALID_PARAMETER;
2667 }
2668
2669 LOGF(("LEAVE, context(0x%x)", hAdapter));
2670
2671 return Status;
2672}
2673
2674typedef struct VBOXWDDM_CALL_ISR
2675{
2676 PVBOXMP_DEVEXT pDevExt;
2677 ULONG MessageNumber;
2678} VBOXWDDM_CALL_ISR, *PVBOXWDDM_CALL_ISR;
2679
2680static BOOLEAN vboxWddmCallIsrCb(PVOID Context)
2681{
2682 PVBOXWDDM_CALL_ISR pdc = (PVBOXWDDM_CALL_ISR)Context;
2683 return DxgkDdiInterruptRoutine(pdc->pDevExt, pdc->MessageNumber);
2684}
2685
2686NTSTATUS vboxWddmCallIsr(PVBOXMP_DEVEXT pDevExt)
2687{
2688 VBOXWDDM_CALL_ISR context;
2689 context.pDevExt = pDevExt;
2690 context.MessageNumber = 0;
2691 BOOLEAN bRet;
2692 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
2693 pDevExt->u.primary.DxgkInterface.DeviceHandle,
2694 vboxWddmCallIsrCb,
2695 &context,
2696 0, /* IN ULONG MessageNumber */
2697 &bRet);
2698 Assert(Status == STATUS_SUCCESS);
2699 return Status;
2700}
2701
2702static NTSTATUS vboxWddmSubmitCmd(PVBOXMP_DEVEXT pDevExt, VBOXVDMAPIPE_CMD_DMACMD *pCmd)
2703{
2704 NTSTATUS Status = vboxVdmaGgCmdDmaNotifySubmitted(pDevExt, pCmd);
2705 Assert(Status == STATUS_SUCCESS);
2706 if (Status == STATUS_SUCCESS)
2707 {
2708 NTSTATUS submStatus = vboxVdmaGgCmdSubmit(pDevExt, &pCmd->Hdr);
2709 Assert(submStatus == STATUS_SUCCESS);
2710 if (submStatus != STATUS_SUCCESS)
2711 {
2712 vboxVdmaGgCmdDmaNotifyCompleted(pDevExt, pCmd, DXGK_INTERRUPT_DMA_FAULTED);
2713 }
2714 }
2715 else
2716 {
2717 vboxVdmaGgCmdRelease(pDevExt, &pCmd->Hdr);
2718 }
2719 return Status;
2720}
2721
2722static NTSTATUS vboxWddmSubmitBltCmd(PVBOXMP_DEVEXT pDevExt, VBOXWDDM_CONTEXT *pContext, UINT u32FenceId, PVBOXWDDM_DMA_PRIVATEDATA_BLT pBlt, VBOXVDMAPIPE_FLAGS_DMACMD fBltFlags)
2723{
2724 NTSTATUS Status = STATUS_SUCCESS;
2725 PVBOXVDMAPIPE_CMD_DMACMD_BLT pBltCmd = (PVBOXVDMAPIPE_CMD_DMACMD_BLT)vboxVdmaGgCmdCreate(pDevExt, VBOXVDMAPIPE_CMD_TYPE_DMACMD, RT_OFFSETOF(VBOXVDMAPIPE_CMD_DMACMD_BLT, Blt.DstRects.UpdateRects.aRects[pBlt->Blt.DstRects.UpdateRects.cRects]));
2726 Assert(pBltCmd);
2727 if (pBltCmd)
2728 {
2729 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pBlt->Blt.DstAlloc.srcId];
2730 vboxVdmaGgCmdDmaNotifyInit(&pBltCmd->Hdr, pContext->NodeOrdinal, u32FenceId, vboxVdmaGgDdiCmdRelease, pBltCmd);
2731 pBltCmd->Hdr.fFlags = fBltFlags;
2732 pBltCmd->Hdr.pContext = pContext;
2733 pBltCmd->Hdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
2734 memcpy(&pBltCmd->Blt, &pBlt->Blt, RT_OFFSETOF(VBOXVDMA_BLT, DstRects.UpdateRects.aRects[pBlt->Blt.DstRects.UpdateRects.cRects]));
2735 Status = vboxWddmSubmitCmd(pDevExt, &pBltCmd->Hdr);
2736 if (Status != STATUS_SUCCESS)
2737 {
2738 WARN(("vboxWddmSubmitCmd failed, Status 0x%x", Status));
2739 Status = STATUS_SUCCESS;
2740 }
2741 vboxVdmaGgCmdRelease(pDevExt, &pBltCmd->Hdr.Hdr);
2742 }
2743 else
2744 {
2745 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, u32FenceId, DXGK_INTERRUPT_DMA_FAULTED);
2746 }
2747 return Status;
2748}
2749
2750#ifdef VBOX_WITH_CRHGSMI
2751DECLCALLBACK(VOID) vboxWddmDmaCompleteChromiumCmd(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext)
2752{
2753 PVBOXVDMACBUF_DR pDr = (PVBOXVDMACBUF_DR)pvContext;
2754 PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
2755 VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_CHROMIUM_CMD);
2756 UINT cBufs = pBody->cBuffers;
2757 for (UINT i = 0; i < cBufs; ++i)
2758 {
2759 VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[i];
2760 if (!pBufCmd->u32GuestData)
2761 {
2762 /* signal completion */
2763 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pBufCmd->u64GuestData;
2764 if (pAlloc->pSynchEvent)
2765 KeSetEvent(pAlloc->pSynchEvent, 3, FALSE);
2766 }
2767 }
2768
2769 vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
2770}
2771#endif
2772
2773NTSTATUS
2774APIENTRY
2775DxgkDdiSubmitCommand(
2776 CONST HANDLE hAdapter,
2777 CONST DXGKARG_SUBMITCOMMAND* pSubmitCommand)
2778{
2779 /* DxgkDdiSubmitCommand runs at dispatch, should not be pageable. */
2780 NTSTATUS Status = STATUS_SUCCESS;
2781
2782// LOGF(("ENTER, context(0x%x)", hAdapter));
2783
2784 vboxVDbgBreakFv();
2785
2786 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
2787 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pSubmitCommand->hContext;
2788 PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR pPrivateDataBase = NULL;
2789 VBOXVDMACMD_TYPE enmCmd = VBOXVDMACMD_TYPE_UNDEFINED;
2790 Assert(pContext);
2791 Assert(pContext->pDevice);
2792 Assert(pContext->pDevice->pAdapter == pDevExt);
2793 Assert(!pSubmitCommand->DmaBufferSegmentId);
2794
2795 /* the DMA command buffer is located in system RAM, the host will need to pick it from there */
2796 //BufInfo.fFlags = 0; /* see VBOXVDMACBUF_FLAG_xx */
2797 if (pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset - pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
2798 {
2799 pPrivateDataBase = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)((uint8_t*)pSubmitCommand->pDmaBufferPrivateData + pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset);
2800 Assert(pPrivateDataBase);
2801 enmCmd = pPrivateDataBase->enmCmd;
2802 }
2803 else if (pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset == pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset)
2804 {
2805 WARN(("null data size, treating as NOP"));
2806 enmCmd = VBOXVDMACMD_TYPE_DMA_NOP;
2807 }
2808 else
2809 {
2810 WARN(("DmaBufferPrivateDataSubmissionEndOffset (%d) - DmaBufferPrivateDataSubmissionStartOffset (%d) < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR) (%d)",
2811 pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset,
2812 pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset,
2813 sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
2814 return STATUS_INVALID_PARAMETER;
2815 }
2816
2817 if (pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D)
2818 vboxWddmModeRenderFromShadowDisableRegister(pDevExt, pContext);
2819
2820 BOOLEAN fRenderFromSharedDisabled = pDevExt->fRenderToShadowDisabled;
2821
2822 switch (enmCmd)
2823 {
2824#ifdef VBOXWDDM_RENDER_FROM_SHADOW
2825 case VBOXVDMACMD_TYPE_DMA_PRESENT_SHADOW2PRIMARY:
2826 {
2827 PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY pS2P = (PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY)pPrivateDataBase;
2828 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pS2P->Shadow2Primary.VidPnSourceId];
2829 PVBOXWDDM_ALLOCATION pSrcAlloc = pS2P->Shadow2Primary.ShadowAlloc.pAlloc;
2830 vboxWddmAssignShadow(pDevExt, pSource, pSrcAlloc, pS2P->Shadow2Primary.VidPnSourceId);
2831 vboxWddmAllocUpdateAddress(pSrcAlloc, pS2P->Shadow2Primary.ShadowAlloc.segmentIdAlloc, pS2P->Shadow2Primary.ShadowAlloc.offAlloc);
2832 fRenderFromSharedDisabled = vboxWddmModeRenderFromShadowCheckOnSubmitCommand(pDevExt, NULL);
2833 vboxWddmCheckUpdateFramebufferAddress(pDevExt, pSource, pS2P->Shadow2Primary.VidPnSourceId);
2834 uint32_t cUnlockedVBVADisabled = ASMAtomicReadU32(&pDevExt->cUnlockedVBVADisabled);
2835 if (!cUnlockedVBVADisabled)
2836 VBOXVBVA_OP(ReportDirtyRect, pDevExt, pSource, &pS2P->Shadow2Primary.SrcRect);
2837 else
2838 {
2839 Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
2840 VBOXVBVA_OP_WITHLOCK_ATDPC(ReportDirtyRect, pDevExt, pSource, &pS2P->Shadow2Primary.SrcRect);
2841 }
2842 /* get DPC data at IRQL */
2843
2844 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_COMPLETED);
2845 break;
2846 }
2847#endif
2848 case VBOXVDMACMD_TYPE_DMA_PRESENT_BLT:
2849 {
2850 VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR *pPrivateData = (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR*)pPrivateDataBase;
2851 PVBOXWDDM_DMA_PRIVATEDATA_BLT pBlt = (PVBOXWDDM_DMA_PRIVATEDATA_BLT)pPrivateData;
2852 PVBOXWDDM_ALLOCATION pDstAlloc = pBlt->Blt.DstAlloc.pAlloc;
2853 PVBOXWDDM_ALLOCATION pSrcAlloc = pBlt->Blt.SrcAlloc.pAlloc;
2854 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pDstAlloc->SurfDesc.VidPnSourceId];
2855
2856 Assert(pDstAlloc->SurfDesc.VidPnSourceId < VBOX_VIDEO_MAX_SCREENS);
2857
2858 vboxWddmAllocUpdateAddress(pDstAlloc, pBlt->Blt.DstAlloc.segmentIdAlloc, pBlt->Blt.DstAlloc.offAlloc);
2859 vboxWddmAllocUpdateAddress(pSrcAlloc, pBlt->Blt.SrcAlloc.segmentIdAlloc, pBlt->Blt.SrcAlloc.offAlloc);
2860
2861 uint32_t cContexts3D = ASMAtomicReadU32(&pDevExt->cContexts3D);
2862
2863 VBOXVDMAPIPE_FLAGS_DMACMD fBltFlags;
2864 fBltFlags.Value = 0;
2865
2866 if (pDstAlloc->bAssigned &&
2867 (pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
2868 || pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE)
2869 )
2870 {
2871 if (pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE)
2872 vboxWddmAssignShadow(pDevExt, pSource, pSrcAlloc, pDstAlloc->SurfDesc.VidPnSourceId);
2873 fRenderFromSharedDisabled = vboxWddmModeRenderFromShadowCheckOnSubmitCommand(pDevExt, NULL);
2874 if(pContext->enmType != VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D
2875 || pDstAlloc->enmType !=VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC)
2876 vboxWddmCheckUpdateFramebufferAddress(pDevExt, pSource, pDstAlloc->SurfDesc.VidPnSourceId);
2877 }
2878 else if (pSrcAlloc->bAssigned &&
2879 (pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
2880 || pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE)
2881 )
2882 {
2883 if (pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE)
2884 vboxWddmAssignShadow(pDevExt, pSource, pDstAlloc, pSrcAlloc->SurfDesc.VidPnSourceId);
2885 fRenderFromSharedDisabled = vboxWddmModeRenderFromShadowCheckOnSubmitCommand(pDevExt, NULL);
2886 if(pContext->enmType != VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D
2887 || pSrcAlloc->enmType !=VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC)
2888 vboxWddmCheckUpdateFramebufferAddress(pDevExt, pSource, pSrcAlloc->SurfDesc.VidPnSourceId);
2889 }
2890
2891 if (pContext->enmType != VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D && fRenderFromSharedDisabled)
2892 fBltFlags.fRealOp = 1;
2893
2894 switch (pDstAlloc->enmType)
2895 {
2896 case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
2897 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
2898 {
2899 if (pDstAlloc->bAssigned)
2900 {
2901 Assert(pSource->pPrimaryAllocation == pDstAlloc);
2902
2903 switch (pSrcAlloc->enmType)
2904 {
2905 case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
2906 {
2907 fBltFlags.fVisibleRegions = !!cContexts3D;
2908 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM);
2909
2910 if (!fRenderFromSharedDisabled)
2911 {
2912 RECT rect;
2913 if (pBlt->Blt.DstRects.UpdateRects.cRects)
2914 {
2915 rect = pBlt->Blt.DstRects.UpdateRects.aRects[0];
2916 for (UINT i = 1; i < pBlt->Blt.DstRects.UpdateRects.cRects; ++i)
2917 {
2918 vboxWddmRectUnited(&rect, &rect, &pBlt->Blt.DstRects.UpdateRects.aRects[i]);
2919 }
2920 }
2921 else
2922 rect = pBlt->Blt.DstRects.ContextRect;
2923
2924 uint32_t cUnlockedVBVADisabled = ASMAtomicReadU32(&pDevExt->cUnlockedVBVADisabled);
2925 if (!cUnlockedVBVADisabled)
2926 {
2927 VBOXVBVA_OP(ReportDirtyRect, pDevExt, pSource, &rect);
2928 }
2929 else
2930 {
2931 VBOXVBVA_OP_WITHLOCK_ATDPC(ReportDirtyRect, pDevExt, pSource, &rect);
2932 }
2933 }
2934
2935 break;
2936 }
2937 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
2938 {
2939 if(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D)
2940 {
2941 Assert(pSrcAlloc->fRcFlags.RenderTarget);
2942 if (pSrcAlloc->fRcFlags.RenderTarget)
2943 fBltFlags.fVisibleRegions = 1;
2944 }
2945 break;
2946 }
2947 default:
2948 {
2949 AssertBreakpoint();
2950 break;
2951 }
2952 }
2953 }
2954
2955 break;
2956 }
2957 case VBOXWDDM_ALLOC_TYPE_STD_STAGINGSURFACE:
2958 {
2959// Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D);
2960 Assert(pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC);
2961 Assert(pSrcAlloc->fRcFlags.RenderTarget);
2962 Assert(vboxWddmRectIsEqual(&pBlt->Blt.SrcRect, &pBlt->Blt.DstRects.ContextRect));
2963 Assert(pBlt->Blt.DstRects.UpdateRects.cRects == 1);
2964 Assert(vboxWddmRectIsEqual(&pBlt->Blt.SrcRect, pBlt->Blt.DstRects.UpdateRects.aRects));
2965 break;
2966 }
2967 case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
2968 {
2969 Assert(pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE);
2970 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM);
2971 break;
2972 }
2973 default:
2974 AssertBreakpoint();
2975 break;
2976 }
2977
2978 if (fBltFlags.Value)
2979 {
2980 Status = vboxWddmSubmitBltCmd(pDevExt, pContext, pSubmitCommand->SubmissionFenceId, pBlt, fBltFlags);
2981 }
2982 else
2983 {
2984 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_COMPLETED);
2985 }
2986 break;
2987 }
2988 case VBOXVDMACMD_TYPE_CHROMIUM_CMD:
2989 {
2990#ifdef VBOX_WITH_CRHGSMI
2991 VBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD *pChromiumCmd = (VBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD*)pPrivateDataBase;
2992 UINT cbCmd = VBOXVDMACMD_SIZE_FROMBODYSIZE(RT_OFFSETOF(VBOXVDMACMD_CHROMIUM_CMD, aBuffers[pChromiumCmd->Base.u32CmdReserved]));
2993
2994 PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate (&pDevExt->u.primary.Vdma, cbCmd);
2995 if (!pDr)
2996 {
2997 /* @todo: try flushing.. */
2998 LOGREL(("vboxVdmaCBufDrCreate returned NULL"));
2999 return STATUS_INSUFFICIENT_RESOURCES;
3000 }
3001 // vboxVdmaCBufDrCreate zero initializes the pDr
3002 pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR;
3003 pDr->cbBuf = cbCmd;
3004 pDr->rc = VERR_NOT_IMPLEMENTED;
3005
3006 PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
3007 pHdr->enmType = VBOXVDMACMD_TYPE_CHROMIUM_CMD;
3008 pHdr->u32CmdSpecific = 0;
3009 VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_CHROMIUM_CMD);
3010 pBody->cBuffers = pChromiumCmd->Base.u32CmdReserved;
3011 for (UINT i = 0; i < pChromiumCmd->Base.u32CmdReserved; ++i)
3012 {
3013 VBOXVDMACMD_CHROMIUM_BUFFER *pBufCmd = &pBody->aBuffers[i];
3014 VBOXWDDM_UHGSMI_BUFFER_SUBMIT_INFO *pBufInfo = &pChromiumCmd->aBufInfos[i];
3015
3016 pBufCmd->offBuffer = pBufInfo->Alloc.offAlloc;
3017 pBufCmd->cbBuffer = pBufInfo->cbData;
3018 pBufCmd->u32GuestData = pBufInfo->bDoNotSignalCompletion;
3019 pBufCmd->u64GuestData = (uint64_t)pBufInfo->Alloc.pAlloc;
3020 }
3021
3022 PVBOXVDMADDI_CMD pDdiCmd = VBOXVDMADDI_CMD_FROM_BUF_DR(pDr);
3023 vboxVdmaDdiCmdInit(pDdiCmd, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, vboxWddmDmaCompleteChromiumCmd, pDr);
3024 NTSTATUS Status = vboxVdmaDdiCmdSubmitted(pDevExt, pDdiCmd);
3025 Assert(Status == STATUS_SUCCESS);
3026 if (Status == STATUS_SUCCESS)
3027 {
3028 int rc = vboxVdmaCBufDrSubmit(pDevExt, &pDevExt->u.primary.Vdma, pDr);
3029 Assert(rc == VINF_SUCCESS);
3030 }
3031 else
3032 {
3033 vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
3034 }
3035#else
3036 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_COMPLETED);
3037 Assert(Status == STATUS_SUCCESS);
3038#endif
3039 break;
3040 }
3041 case VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP:
3042 {
3043 VBOXWDDM_DMA_PRIVATEDATA_FLIP *pFlip = (VBOXWDDM_DMA_PRIVATEDATA_FLIP*)pPrivateDataBase;
3044 PVBOXVDMAPIPE_CMD_DMACMD_FLIP pFlipCmd = (PVBOXVDMAPIPE_CMD_DMACMD_FLIP)vboxVdmaGgCmdCreate(pDevExt,
3045 VBOXVDMAPIPE_CMD_TYPE_DMACMD, sizeof (VBOXVDMAPIPE_CMD_DMACMD_FLIP));
3046 Assert(pFlipCmd);
3047 if (pFlipCmd)
3048 {
3049 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pFlip->Flip.Alloc.srcId];
3050 vboxVdmaGgCmdDmaNotifyInit(&pFlipCmd->Hdr, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, vboxVdmaGgDdiCmdRelease, pFlipCmd);
3051 pFlipCmd->Hdr.fFlags.Value = 0;
3052 pFlipCmd->Hdr.fFlags.fVisibleRegions = 1;
3053 pFlipCmd->Hdr.pContext = pContext;
3054 pFlipCmd->Hdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP;
3055 memcpy(&pFlipCmd->Flip, &pFlip->Flip, sizeof (pFlipCmd->Flip));
3056 Status = vboxWddmSubmitCmd(pDevExt, &pFlipCmd->Hdr);
3057 if (Status != STATUS_SUCCESS)
3058 WARN(("vboxWddmSubmitCmd failed, Status 0x%x", Status));
3059 vboxVdmaGgCmdRelease(pDevExt, &pFlipCmd->Hdr.Hdr);
3060 }
3061 else
3062 {
3063 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_FAULTED);
3064 Assert(Status == STATUS_SUCCESS);
3065 }
3066 break;
3067 }
3068 case VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL:
3069 {
3070 PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL pCF = (PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL)pPrivateDataBase;
3071 PVBOXVDMAPIPE_CMD_DMACMD_CLRFILL pCFCmd = (PVBOXVDMAPIPE_CMD_DMACMD_CLRFILL)vboxVdmaGgCmdCreate(pDevExt,
3072 VBOXVDMAPIPE_CMD_TYPE_DMACMD, RT_OFFSETOF(VBOXVDMAPIPE_CMD_DMACMD_CLRFILL, ClrFill.Rects.aRects[pCF->ClrFill.Rects.cRects]));
3073 Assert(pCFCmd);
3074 if (pCFCmd)
3075 {
3076 vboxVdmaGgCmdDmaNotifyInit(&pCFCmd->Hdr, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, vboxVdmaGgDdiCmdRelease, pCFCmd);
3077 pCFCmd->Hdr.fFlags.Value = 0;
3078 pCFCmd->Hdr.fFlags.fRealOp = 1;
3079 pCFCmd->Hdr.pContext = pContext;
3080 pCFCmd->Hdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL;
3081 memcpy(&pCFCmd->ClrFill, &pCF->ClrFill, RT_OFFSETOF(VBOXVDMA_CLRFILL, Rects.aRects[pCF->ClrFill.Rects.cRects]));
3082 Status = vboxWddmSubmitCmd(pDevExt, &pCFCmd->Hdr);
3083 if (Status != STATUS_SUCCESS)
3084 WARN(("vboxWddmSubmitCmd failed, Status 0x%x", Status));
3085 vboxVdmaGgCmdRelease(pDevExt, &pCFCmd->Hdr.Hdr);
3086
3087 }
3088 else
3089 {
3090 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_FAULTED);
3091 Assert(Status == STATUS_SUCCESS);
3092 }
3093
3094 break;
3095 }
3096 case VBOXVDMACMD_TYPE_DMA_NOP:
3097 {
3098 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_COMPLETED);
3099 Assert(Status == STATUS_SUCCESS);
3100 break;
3101 }
3102 default:
3103 {
3104 WARN(("unexpected command %d", enmCmd));
3105#if 0 //def VBOX_WITH_VDMA
3106 VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR *pPrivateData = (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR*)pPrivateDataBase;
3107 PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate (&pDevExt->u.primary.Vdma, 0);
3108 if (!pDr)
3109 {
3110 /* @todo: try flushing.. */
3111 LOGREL(("vboxVdmaCBufDrCreate returned NULL"));
3112 return STATUS_INSUFFICIENT_RESOURCES;
3113 }
3114 // vboxVdmaCBufDrCreate zero initializes the pDr
3115 //pDr->fFlags = 0;
3116 pDr->cbBuf = pSubmitCommand->DmaBufferSubmissionEndOffset - pSubmitCommand->DmaBufferSubmissionStartOffset;
3117 pDr->u32FenceId = pSubmitCommand->SubmissionFenceId;
3118 pDr->rc = VERR_NOT_IMPLEMENTED;
3119 if (pPrivateData)
3120 pDr->u64GuestContext = (uint64_t)pPrivateData->pContext;
3121 // else // vboxVdmaCBufDrCreate zero initializes the pDr
3122 // pDr->u64GuestContext = NULL;
3123 pDr->Location.phBuf = pSubmitCommand->DmaBufferPhysicalAddress.QuadPart + pSubmitCommand->DmaBufferSubmissionStartOffset;
3124
3125 vboxVdmaCBufDrSubmit(pDevExt, &pDevExt->u.primary.Vdma, pDr);
3126#endif
3127 break;
3128 }
3129 }
3130// LOGF(("LEAVE, context(0x%x)", hAdapter));
3131
3132 return Status;
3133}
3134
3135NTSTATUS
3136APIENTRY
3137DxgkDdiPreemptCommand(
3138 CONST HANDLE hAdapter,
3139 CONST DXGKARG_PREEMPTCOMMAND* pPreemptCommand)
3140{
3141 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3142
3143 AssertFailed();
3144 /* @todo: fixme: implement */
3145
3146 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3147
3148 return STATUS_SUCCESS;
3149}
3150
3151#if 0
3152static uint32_t vboxWddmSysMemElBuild(PVBOXVDMACMD_SYSMEMEL pEl, PMDL pMdl, uint32_t iPfn, uint32_t cPages, uint32_t cbBuffer, uint32_t *pcPagesRemaining)
3153{
3154 uint32_t cbInitialBuffer = cbBuffer;
3155 if (cbBuf >= sizeof (*pEl))
3156 {
3157 PFN_NUMBER cur = MmGetMdlPfnArray(pMdl)[iPfn];
3158 uint32_t cbEl = sizeof (*pEl);
3159 uint32_t cBufs = 1;
3160 pEl->phBuf[0] = (cur << 12);
3161 --cPages;
3162 cbBuffer -= sizeof (*pEl);
3163 bool bArrayMode = false;
3164 while (cPages)
3165 {
3166 PFN_NUMBER next = MmGetMdlPfnArray(pMdl)[iPfn+cBufs];
3167 if (!bArrayMode)
3168 {
3169 if (next == cur+1)
3170 {
3171 cur = next;
3172 ++cBufs;
3173 --cPages;
3174 }
3175 else if (cBufs > 1)
3176 {
3177 break;
3178 }
3179 else
3180 {
3181 bArrayMode = true;
3182 }
3183 }
3184
3185 /* array mode */
3186 if (cbBuffer < sizeof (pEl->phBuf[0]))
3187 {
3188 break;
3189 }
3190
3191 pEl->phBuf[cBufs] = (next << 12);
3192 cbBuffer -= sizeof (pEl->phBuf[0]);
3193 ++cBufs;
3194 --cPages;
3195 }
3196
3197 pEl->cPages = cPages;
3198 if (bArrayMode)
3199 pEl->fFlags = VBOXVDMACMD_SYSMEMEL_F_PAGELIST;
3200 else
3201 pEl->fFlags = 0;
3202 }
3203 else
3204 {
3205 Assert(0);
3206 }
3207
3208 *pcPagesRemaining = cPages;
3209 return cbInitialBuffer - cbBuffer;
3210}
3211
3212static uint32_t vboxWddmBpbTransferVRamSysBuildEls(PVBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS pCmd, PMDL pMdl, uint32_t iPfn, uint32_t cPages, uint32_t cbBuffer, uint32_t *pcPagesRemaining)
3213{
3214 uint32_t cInitPages = cPages;
3215 uint32_t cbBufferUsed = vboxWddmSysMemElBuild(&pCmd->FirstEl, pMdl, iPfn, cPages, cbBuffer, &cPages);
3216 if (cbBufferUsed)
3217 {
3218 uint32_t cEls = 1;
3219 PVBOXVDMACMD_SYSMEMEL pEl = &pCmd->FirstEl;
3220 while (cPages)
3221 {
3222 PVBOXVDMACMD_SYSMEMEL pEl = VBOXVDMACMD_SYSMEMEL_NEXT(pEl);
3223 cbBufferUsed = vboxWddmSysMemElBuild(pEl, pMdl, iPfn + cInitPages - cPages, cPages, cbBuffer - cbBufferUsed, &cPages);
3224 if (cbBufferUsed)
3225 {
3226 ++cEls;
3227 }
3228 else
3229 break;
3230 }
3231 }
3232 else
3233 {
3234 Assert(0);
3235 }
3236
3237 pCmd->cTransferPages = (cInitPages - cPages);
3238 *pcPagesRemaining = cPages;
3239 return cbBufferUsed;
3240}
3241#endif
3242/*
3243 * DxgkDdiBuildPagingBuffer
3244 */
3245NTSTATUS
3246APIENTRY
3247DxgkDdiBuildPagingBuffer(
3248 CONST HANDLE hAdapter,
3249 DXGKARG_BUILDPAGINGBUFFER* pBuildPagingBuffer)
3250{
3251 /* DxgkDdiBuildPagingBuffer should be made pageable. */
3252 PAGED_CODE();
3253
3254 vboxVDbgBreakFv();
3255
3256 NTSTATUS Status = STATUS_SUCCESS;
3257 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3258
3259 LOGF(("ENTER, context(0x%x)", hAdapter));
3260
3261 /* @todo: */
3262 switch (pBuildPagingBuffer->Operation)
3263 {
3264 case DXGK_OPERATION_TRANSFER:
3265 {
3266#ifdef VBOX_WITH_VDMA
3267#if 0
3268 if ((!pBuildPagingBuffer->Transfer.Source.SegmentId) != (!pBuildPagingBuffer->Transfer.Destination.SegmentId))
3269 {
3270 PVBOXVDMACMD pCmd = (PVBOXVDMACMD)pBuildPagingBuffer->pDmaBuffer;
3271 pCmd->enmType = VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER_VRAMSYS;
3272 pCmd->u32CmdSpecific = 0;
3273 PVBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS pBody = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS);
3274 PMDL pMdl;
3275 uint32_t cPages = (pBuildPagingBuffer->Transfer.TransferSize + 0xfff) >> 12;
3276 cPages -= pBuildPagingBuffer->MultipassOffset;
3277 uint32_t iFirstPage = pBuildPagingBuffer->Transfer.MdlOffset + pBuildPagingBuffer->MultipassOffset;
3278 uint32_t cPagesRemaining;
3279 if (pBuildPagingBuffer->Transfer.Source.SegmentId)
3280 {
3281 uint64_t off = pBuildPagingBuffer->Transfer.Source.SegmentAddress.QuadPart;
3282 off += pBuildPagingBuffer->Transfer.TransferOffset + (pBuildPagingBuffer->MultipassOffset << 12);
3283 pBody->offVramBuf = off;
3284 pMdl = pBuildPagingBuffer->Transfer.Source.pMdl;
3285 pBody->fFlags = 0;//VBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS_SYS2VRAM
3286 }
3287 else
3288 {
3289 uint64_t off = pBuildPagingBuffer->Transfer.Destination.SegmentAddress.QuadPart;
3290 off += pBuildPagingBuffer->Transfer.TransferOffset + (pBuildPagingBuffer->MultipassOffset << 12);
3291 pBody->offVramBuf = off;
3292 pMdl = pBuildPagingBuffer->Transfer.Destination.pMdl;
3293 pBody->fFlags = VBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS_SYS2VRAM;
3294 }
3295
3296 uint32_t sbBufferUsed = vboxWddmBpbTransferVRamSysBuildEls(pBody, pMdl, iFirstPage, cPages, pBuildPagingBuffer->DmaSize, &cPagesRemaining);
3297 Assert(sbBufferUsed);
3298 }
3299
3300#else
3301 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pBuildPagingBuffer->Transfer.hAllocation;
3302 Assert(pAlloc);
3303 if (pAlloc
3304 && !pAlloc->fRcFlags.Overlay /* overlay surfaces actually contain a valid data */
3305 && pAlloc->enmType != VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE /* shadow primary - also */
3306 && pAlloc->enmType != VBOXWDDM_ALLOC_TYPE_UMD_HGSMI_BUFFER /* hgsmi buffer - also */
3307 )
3308 {
3309 /* we do not care about the others for now */
3310 Status = STATUS_SUCCESS;
3311 break;
3312 }
3313 UINT cbCmd = VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_BPB_TRANSFER);
3314 PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate (&pDevExt->u.primary.Vdma, cbCmd);
3315 Assert(pDr);
3316 if (pDr)
3317 {
3318 SIZE_T cbTransfered = 0;
3319 SIZE_T cbTransferSize = pBuildPagingBuffer->Transfer.TransferSize;
3320 PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
3321 do
3322 {
3323 // vboxVdmaCBufDrCreate zero initializes the pDr
3324 pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR;
3325 pDr->cbBuf = cbCmd;
3326 pDr->rc = VERR_NOT_IMPLEMENTED;
3327
3328 pHdr->enmType = VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER;
3329 pHdr->u32CmdSpecific = 0;
3330 VBOXVDMACMD_DMA_BPB_TRANSFER *pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_DMA_BPB_TRANSFER);
3331// pBody->cbTransferSize = (uint32_t)pBuildPagingBuffer->Transfer.TransferSize;
3332 pBody->fFlags = 0;
3333 SIZE_T cSrcPages = (cbTransferSize + 0xfff ) >> 12;
3334 SIZE_T cDstPages = cSrcPages;
3335
3336 if (pBuildPagingBuffer->Transfer.Source.SegmentId)
3337 {
3338 uint64_t off = pBuildPagingBuffer->Transfer.Source.SegmentAddress.QuadPart;
3339 off += pBuildPagingBuffer->Transfer.TransferOffset + cbTransfered;
3340 pBody->Src.offVramBuf = off;
3341 pBody->fFlags |= VBOXVDMACMD_DMA_BPB_TRANSFER_F_SRC_VRAMOFFSET;
3342 }
3343 else
3344 {
3345 UINT index = pBuildPagingBuffer->Transfer.MdlOffset + (UINT)(cbTransfered>>12);
3346 pBody->Src.phBuf = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Source.pMdl)[index] << 12;
3347 PFN_NUMBER num = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Source.pMdl)[index];
3348 cSrcPages = 1;
3349 for (UINT i = 1; i < ((cbTransferSize - cbTransfered + 0xfff) >> 12); ++i)
3350 {
3351 PFN_NUMBER cur = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Source.pMdl)[index+i];
3352 if(cur != ++num)
3353 {
3354 cSrcPages+= i-1;
3355 break;
3356 }
3357 }
3358 }
3359
3360 if (pBuildPagingBuffer->Transfer.Destination.SegmentId)
3361 {
3362 uint64_t off = pBuildPagingBuffer->Transfer.Destination.SegmentAddress.QuadPart;
3363 off += pBuildPagingBuffer->Transfer.TransferOffset;
3364 pBody->Dst.offVramBuf = off + cbTransfered;
3365 pBody->fFlags |= VBOXVDMACMD_DMA_BPB_TRANSFER_F_DST_VRAMOFFSET;
3366 }
3367 else
3368 {
3369 UINT index = pBuildPagingBuffer->Transfer.MdlOffset + (UINT)(cbTransfered>>12);
3370 pBody->Dst.phBuf = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Destination.pMdl)[index] << 12;
3371 PFN_NUMBER num = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Destination.pMdl)[index];
3372 cDstPages = 1;
3373 for (UINT i = 1; i < ((cbTransferSize - cbTransfered + 0xfff) >> 12); ++i)
3374 {
3375 PFN_NUMBER cur = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Destination.pMdl)[index+i];
3376 if(cur != ++num)
3377 {
3378 cDstPages+= i-1;
3379 break;
3380 }
3381 }
3382 }
3383
3384 SIZE_T cbCurTransfer;
3385 cbCurTransfer = RT_MIN(cbTransferSize - cbTransfered, cSrcPages << 12);
3386 cbCurTransfer = RT_MIN(cbCurTransfer, cDstPages << 12);
3387
3388 pBody->cbTransferSize = (UINT)cbCurTransfer;
3389 Assert(!(cbCurTransfer & 0xfff));
3390
3391 int rc = vboxVdmaCBufDrSubmitSynch(pDevExt, &pDevExt->u.primary.Vdma, pDr);
3392 AssertRC(rc);
3393 if (RT_SUCCESS(rc))
3394 {
3395 Status = STATUS_SUCCESS;
3396 cbTransfered += cbCurTransfer;
3397 }
3398 else
3399 Status = STATUS_UNSUCCESSFUL;
3400 } while (cbTransfered < cbTransferSize);
3401 Assert(cbTransfered == cbTransferSize);
3402 vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
3403 }
3404 else
3405 {
3406 /* @todo: try flushing.. */
3407 LOGREL(("vboxVdmaCBufDrCreate returned NULL"));
3408 Status = STATUS_INSUFFICIENT_RESOURCES;
3409 }
3410#endif
3411#endif /* #ifdef VBOX_WITH_VDMA */
3412 break;
3413 }
3414 case DXGK_OPERATION_FILL:
3415 {
3416 Assert(pBuildPagingBuffer->Fill.FillPattern == 0);
3417 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pBuildPagingBuffer->Fill.hAllocation;
3418// pBuildPagingBuffer->pDmaBuffer = (uint8_t*)pBuildPagingBuffer->pDmaBuffer + VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_BPB_FILL);
3419 break;
3420 }
3421 case DXGK_OPERATION_DISCARD_CONTENT:
3422 {
3423// AssertBreakpoint();
3424 break;
3425 }
3426 default:
3427 {
3428 LOGREL(("unsupported op (%d)", pBuildPagingBuffer->Operation));
3429 AssertBreakpoint();
3430 break;
3431 }
3432 }
3433
3434 LOGF(("LEAVE, context(0x%x)", hAdapter));
3435
3436 return Status;
3437
3438}
3439
3440NTSTATUS
3441APIENTRY
3442DxgkDdiSetPalette(
3443 CONST HANDLE hAdapter,
3444 CONST DXGKARG_SETPALETTE* pSetPalette
3445 )
3446{
3447 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3448
3449 AssertBreakpoint();
3450 /* @todo: fixme: implement */
3451
3452 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3453
3454 return STATUS_SUCCESS;
3455}
3456
3457BOOL vboxWddmPointerCopyColorData(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVIDEO_POINTER_ATTRIBUTES pPointerAttributes)
3458{
3459 ULONG srcMaskW, srcMaskH;
3460 ULONG dstBytesPerLine;
3461 ULONG x, y;
3462 BYTE *pSrc, *pDst, bit;
3463
3464 srcMaskW = pSetPointerShape->Width;
3465 srcMaskH = pSetPointerShape->Height;
3466
3467 /* truncate masks if we exceed supported size */
3468 pPointerAttributes->Width = min(srcMaskW, VBOXWDDM_C_POINTER_MAX_WIDTH);
3469 pPointerAttributes->Height = min(srcMaskH, VBOXWDDM_C_POINTER_MAX_HEIGHT);
3470 pPointerAttributes->WidthInBytes = pPointerAttributes->Width * 4;
3471
3472 /* cnstruct and mask from alpha color channel */
3473 pSrc = (PBYTE)pSetPointerShape->pPixels;
3474 pDst = pPointerAttributes->Pixels;
3475 dstBytesPerLine = (pPointerAttributes->Width+7)/8;
3476
3477 /* sanity check */
3478 uint32_t cbData = RT_ALIGN_T(dstBytesPerLine*pPointerAttributes->Height, 4, ULONG)+
3479 pPointerAttributes->Height*pPointerAttributes->WidthInBytes;
3480 uint32_t cbPointerAttributes = RT_OFFSETOF(VIDEO_POINTER_ATTRIBUTES, Pixels[cbData]);
3481 Assert(VBOXWDDM_POINTER_ATTRIBUTES_SIZE >= cbPointerAttributes);
3482 if (VBOXWDDM_POINTER_ATTRIBUTES_SIZE < cbPointerAttributes)
3483 {
3484 LOGREL(("VBOXWDDM_POINTER_ATTRIBUTES_SIZE(%d) < cbPointerAttributes(%d)", VBOXWDDM_POINTER_ATTRIBUTES_SIZE, cbPointerAttributes));
3485 return FALSE;
3486 }
3487
3488 memset(pDst, 0xFF, dstBytesPerLine*pPointerAttributes->Height);
3489 for (y=0; y<pPointerAttributes->Height; ++y)
3490 {
3491 for (x=0, bit=7; x<pPointerAttributes->Width; ++x, --bit)
3492 {
3493 if (0xFF==bit) bit=7;
3494
3495 if (pSrc[y*pSetPointerShape->Pitch + x*4 + 3] > 0x7F)
3496 {
3497 pDst[y*dstBytesPerLine + x/8] &= ~RT_BIT(bit);
3498 }
3499 }
3500 }
3501
3502 /* copy 32bpp to XOR DIB, it start in pPointerAttributes->Pixels should be 4bytes aligned */
3503 pSrc = (BYTE*)pSetPointerShape->pPixels;
3504 pDst = pPointerAttributes->Pixels + RT_ALIGN_T(dstBytesPerLine*pPointerAttributes->Height, 4, ULONG);
3505 dstBytesPerLine = pPointerAttributes->Width * 4;
3506
3507 for (y=0; y<pPointerAttributes->Height; ++y)
3508 {
3509 memcpy(pDst+y*dstBytesPerLine, pSrc+y*pSetPointerShape->Pitch, dstBytesPerLine);
3510 }
3511
3512 return TRUE;
3513}
3514
3515BOOL vboxWddmPointerCopyMonoData(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVIDEO_POINTER_ATTRIBUTES pPointerAttributes)
3516{
3517 ULONG srcMaskW, srcMaskH;
3518 ULONG dstBytesPerLine;
3519 ULONG x, y;
3520 BYTE *pSrc, *pDst, bit;
3521
3522 srcMaskW = pSetPointerShape->Width;
3523 srcMaskH = pSetPointerShape->Height;
3524
3525 /* truncate masks if we exceed supported size */
3526 pPointerAttributes->Width = min(srcMaskW, VBOXWDDM_C_POINTER_MAX_WIDTH);
3527 pPointerAttributes->Height = min(srcMaskH, VBOXWDDM_C_POINTER_MAX_HEIGHT);
3528 pPointerAttributes->WidthInBytes = pPointerAttributes->Width * 4;
3529
3530 /* copy AND mask */
3531 pSrc = (PBYTE)pSetPointerShape->pPixels;
3532 pDst = pPointerAttributes->Pixels;
3533 dstBytesPerLine = (pPointerAttributes->Width+7)/8;
3534
3535 for (y=0; y<pPointerAttributes->Height; ++y)
3536 {
3537 memcpy(pDst+y*dstBytesPerLine, pSrc+y*pSetPointerShape->Pitch, dstBytesPerLine);
3538 }
3539
3540 /* convert XOR mask to RGB0 DIB, it start in pPointerAttributes->Pixels should be 4bytes aligned */
3541 pSrc = (BYTE*)pSetPointerShape->pPixels + srcMaskH*pSetPointerShape->Pitch;
3542 pDst = pPointerAttributes->Pixels + RT_ALIGN_T(dstBytesPerLine*pPointerAttributes->Height, 4, ULONG);
3543 dstBytesPerLine = pPointerAttributes->Width * 4;
3544
3545 for (y=0; y<pPointerAttributes->Height; ++y)
3546 {
3547 for (x=0, bit=7; x<pPointerAttributes->Width; ++x, --bit)
3548 {
3549 if (0xFF==bit) bit=7;
3550
3551 *(ULONG*)&pDst[y*dstBytesPerLine+x*4] = (pSrc[y*pSetPointerShape->Pitch+x/8] & RT_BIT(bit)) ? 0x00FFFFFF : 0;
3552 }
3553 }
3554
3555 return TRUE;
3556}
3557
3558static BOOLEAN vboxVddmPointerShapeToAttributes(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVBOXWDDM_POINTER_INFO pPointerInfo)
3559{
3560 PVIDEO_POINTER_ATTRIBUTES pPointerAttributes = &pPointerInfo->Attributes.data;
3561 /* pPointerAttributes maintains the visibility state, clear all except visibility */
3562 pPointerAttributes->Enable &= VBOX_MOUSE_POINTER_VISIBLE;
3563
3564 Assert(pSetPointerShape->Flags.Value == 1 || pSetPointerShape->Flags.Value == 2);
3565 if (pSetPointerShape->Flags.Color)
3566 {
3567 if (vboxWddmPointerCopyColorData(pSetPointerShape, pPointerAttributes))
3568 {
3569 pPointerAttributes->Flags = VIDEO_MODE_COLOR_POINTER;
3570 pPointerAttributes->Enable |= VBOX_MOUSE_POINTER_ALPHA;
3571 }
3572 else
3573 {
3574 LOGREL(("vboxWddmPointerCopyColorData failed"));
3575 AssertBreakpoint();
3576 return FALSE;
3577 }
3578
3579 }
3580 else if (pSetPointerShape->Flags.Monochrome)
3581 {
3582 if (vboxWddmPointerCopyMonoData(pSetPointerShape, pPointerAttributes))
3583 {
3584 pPointerAttributes->Flags = VIDEO_MODE_MONO_POINTER;
3585 }
3586 else
3587 {
3588 LOGREL(("vboxWddmPointerCopyMonoData failed"));
3589 AssertBreakpoint();
3590 return FALSE;
3591 }
3592 }
3593 else
3594 {
3595 LOGREL(("unsupported pointer type Flags.Value(0x%x)", pSetPointerShape->Flags.Value));
3596 AssertBreakpoint();
3597 return FALSE;
3598 }
3599
3600 pPointerAttributes->Enable |= VBOX_MOUSE_POINTER_SHAPE;
3601
3602 /*
3603 * The hot spot coordinates and alpha flag will be encoded in the pPointerAttributes::Enable field.
3604 * High word will contain hot spot info and low word - flags.
3605 */
3606 pPointerAttributes->Enable |= (pSetPointerShape->YHot & 0xFF) << 24;
3607 pPointerAttributes->Enable |= (pSetPointerShape->XHot & 0xFF) << 16;
3608
3609 return TRUE;
3610}
3611
3612NTSTATUS
3613APIENTRY
3614DxgkDdiSetPointerPosition(
3615 CONST HANDLE hAdapter,
3616 CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition)
3617{
3618// LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3619
3620 vboxVDbgBreakFv();
3621
3622 /* mouse integration is ON */
3623 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3624 PVBOXWDDM_POINTER_INFO pPointerInfo = &pDevExt->aSources[pSetPointerPosition->VidPnSourceId].PointerInfo;
3625 PVBOXWDDM_GLOBAL_POINTER_INFO pGlobalPointerInfo = &pDevExt->PointerInfo;
3626 PVIDEO_POINTER_ATTRIBUTES pPointerAttributes = &pPointerInfo->Attributes.data;
3627 BOOLEAN fScreenVisState = !!(pPointerAttributes->Enable & VBOX_MOUSE_POINTER_VISIBLE);
3628 BOOLEAN fVisStateChanged = FALSE;
3629 BOOLEAN fScreenChanged = pGlobalPointerInfo->iLastReportedScreen != pSetPointerPosition->VidPnSourceId;
3630
3631 if (pSetPointerPosition->Flags.Visible)
3632 {
3633 pPointerAttributes->Enable |= VBOX_MOUSE_POINTER_VISIBLE;
3634 if (!fScreenVisState)
3635 {
3636 fVisStateChanged = !!pGlobalPointerInfo->cVisible;
3637 ++pGlobalPointerInfo->cVisible;
3638 }
3639 }
3640 else
3641 {
3642 pPointerAttributes->Enable &= ~VBOX_MOUSE_POINTER_VISIBLE;
3643 if (fScreenVisState)
3644 {
3645 --pGlobalPointerInfo->cVisible;
3646 fVisStateChanged = !!pGlobalPointerInfo->cVisible;
3647 }
3648 }
3649
3650 pGlobalPointerInfo->iLastReportedScreen = pSetPointerPosition->VidPnSourceId;
3651
3652 if ((fVisStateChanged || fScreenChanged) && VBoxQueryHostWantsAbsolute())
3653 {
3654 if (fScreenChanged)
3655 {
3656 BOOLEAN bResult = VBoxMPCmnUpdatePointerShape(VBoxCommonFromDeviceExt(pDevExt), &pPointerInfo->Attributes.data, VBOXWDDM_POINTER_ATTRIBUTES_SIZE);
3657 Assert(bResult);
3658 }
3659 else
3660 {
3661 // tell the host to use the guest's pointer
3662 VIDEO_POINTER_ATTRIBUTES PointerAttributes;
3663
3664 /* Visible and No Shape means Show the pointer.
3665 * It is enough to init only this field.
3666 */
3667 PointerAttributes.Enable = pSetPointerPosition->Flags.Visible ? VBOX_MOUSE_POINTER_VISIBLE : 0;
3668
3669 BOOLEAN bResult = VBoxMPCmnUpdatePointerShape(VBoxCommonFromDeviceExt(pDevExt), &PointerAttributes, sizeof (PointerAttributes));
3670 Assert(bResult);
3671 }
3672 }
3673
3674// LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3675
3676 return STATUS_SUCCESS;
3677}
3678
3679NTSTATUS
3680APIENTRY
3681DxgkDdiSetPointerShape(
3682 CONST HANDLE hAdapter,
3683 CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape)
3684{
3685// LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3686
3687 vboxVDbgBreakFv();
3688
3689 NTSTATUS Status = STATUS_NOT_SUPPORTED;
3690
3691 if (VBoxQueryHostWantsAbsolute())
3692 {
3693 /* mouse integration is ON */
3694 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3695 PVBOXWDDM_POINTER_INFO pPointerInfo = &pDevExt->aSources[pSetPointerShape->VidPnSourceId].PointerInfo;
3696 /* @todo: to avoid extra data copy and extra heap allocation,
3697 * need to maintain the pre-allocated HGSMI buffer and convert the data directly to it */
3698 if (vboxVddmPointerShapeToAttributes(pSetPointerShape, pPointerInfo))
3699 {
3700 pDevExt->PointerInfo.iLastReportedScreen = pSetPointerShape->VidPnSourceId;
3701 if (VBoxMPCmnUpdatePointerShape(VBoxCommonFromDeviceExt(pDevExt), &pPointerInfo->Attributes.data, VBOXWDDM_POINTER_ATTRIBUTES_SIZE))
3702 Status = STATUS_SUCCESS;
3703 else
3704 {
3705 AssertBreakpoint();
3706 LOGREL(("vboxUpdatePointerShape failed"));
3707 }
3708 }
3709 }
3710
3711// LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3712
3713 return Status;
3714}
3715
3716NTSTATUS
3717APIENTRY CALLBACK
3718DxgkDdiResetFromTimeout(
3719 CONST HANDLE hAdapter)
3720{
3721 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3722
3723 AssertBreakpoint();
3724 /* @todo: fixme: implement */
3725
3726 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3727
3728 return STATUS_SUCCESS;
3729}
3730
3731
3732/* the lpRgnData->Buffer comes to us as RECT
3733 * to avoid extra memcpy we cast it to PRTRECT assuming
3734 * they are identical */
3735AssertCompile(sizeof(RECT) == sizeof(RTRECT));
3736AssertCompile(RT_OFFSETOF(RECT, left) == RT_OFFSETOF(RTRECT, xLeft));
3737AssertCompile(RT_OFFSETOF(RECT, bottom) == RT_OFFSETOF(RTRECT, yBottom));
3738AssertCompile(RT_OFFSETOF(RECT, right) == RT_OFFSETOF(RTRECT, xRight));
3739AssertCompile(RT_OFFSETOF(RECT, top) == RT_OFFSETOF(RTRECT, yTop));
3740
3741NTSTATUS
3742APIENTRY
3743DxgkDdiEscape(
3744 CONST HANDLE hAdapter,
3745 CONST DXGKARG_ESCAPE* pEscape)
3746{
3747 PAGED_CODE();
3748
3749// LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3750
3751 NTSTATUS Status = STATUS_NOT_SUPPORTED;
3752 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3753 Assert(pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE));
3754 if (pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE))
3755 {
3756 PVBOXDISPIFESCAPE pEscapeHdr = (PVBOXDISPIFESCAPE)pEscape->pPrivateDriverData;
3757 switch (pEscapeHdr->escapeCode)
3758 {
3759#ifdef VBOX_WITH_CRHGSMI
3760 case VBOXESC_UHGSMI_SUBMIT:
3761 {
3762 /* submit UHGSMI command */
3763 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
3764 PVBOXDISPIFESCAPE_UHGSMI_SUBMIT pSubmit = (PVBOXDISPIFESCAPE_UHGSMI_SUBMIT)pEscapeHdr;
3765 Assert(pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_UHGSMI_SUBMIT)
3766 && pEscape->PrivateDriverDataSize == RT_OFFSETOF(VBOXDISPIFESCAPE_UHGSMI_SUBMIT, aBuffers[pEscapeHdr->u32CmdSpecific]));
3767 if (pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD)
3768 && pEscape->PrivateDriverDataSize == RT_OFFSETOF(VBOXDISPIFESCAPE_UHGSMI_SUBMIT, aBuffers[pEscapeHdr->u32CmdSpecific]))
3769 {
3770 Status = vboxVideoAMgrCtxAllocSubmit(pDevExt, &pContext->AllocContext, pEscapeHdr->u32CmdSpecific, pSubmit->aBuffers);
3771 Assert(Status == STATUS_SUCCESS);
3772 }
3773 else
3774 Status = STATUS_BUFFER_TOO_SMALL;
3775
3776 break;
3777 }
3778#endif
3779 case VBOXESC_UHGSMI_ALLOCATE:
3780 {
3781 /* allocate UHGSMI buffer */
3782 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
3783 PVBOXDISPIFESCAPE_UHGSMI_ALLOCATE pAlocate = (PVBOXDISPIFESCAPE_UHGSMI_ALLOCATE)pEscapeHdr;
3784 Assert(pEscape->PrivateDriverDataSize == sizeof (VBOXDISPIFESCAPE_UHGSMI_ALLOCATE));
3785 if (pEscape->PrivateDriverDataSize == sizeof (VBOXDISPIFESCAPE_UHGSMI_ALLOCATE))
3786 {
3787 Status = vboxVideoAMgrCtxAllocCreate(&pContext->AllocContext, &pAlocate->Alloc);
3788 Assert(Status == STATUS_SUCCESS);
3789 }
3790 else
3791 Status = STATUS_BUFFER_TOO_SMALL;
3792
3793 break;
3794 }
3795
3796 case VBOXESC_UHGSMI_DEALLOCATE:
3797 {
3798 /* deallocate UHGSMI buffer */
3799 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
3800 PVBOXDISPIFESCAPE_UHGSMI_DEALLOCATE pDealocate = (PVBOXDISPIFESCAPE_UHGSMI_DEALLOCATE)pEscapeHdr;
3801 Assert(pEscape->PrivateDriverDataSize == sizeof (VBOXDISPIFESCAPE_UHGSMI_DEALLOCATE));
3802 if (pEscape->PrivateDriverDataSize == sizeof (VBOXDISPIFESCAPE_UHGSMI_DEALLOCATE))
3803 {
3804 Status = vboxVideoAMgrCtxAllocDestroy(&pContext->AllocContext, pDealocate->hAlloc);
3805 Assert(Status == STATUS_SUCCESS);
3806 }
3807 else
3808 Status = STATUS_BUFFER_TOO_SMALL;
3809
3810 break;
3811 }
3812
3813 case VBOXESC_GETVBOXVIDEOCMCMD:
3814 {
3815 /* get the list of r0->r3 commands (d3d window visible regions reporting )*/
3816 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
3817 PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD pRegions = (PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD)pEscapeHdr;
3818 Assert(pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD));
3819 if (pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD))
3820 {
3821 Status = vboxVideoCmEscape(&pContext->CmContext, pRegions, pEscape->PrivateDriverDataSize);
3822 Assert(Status == STATUS_SUCCESS);
3823 }
3824 else
3825 Status = STATUS_BUFFER_TOO_SMALL;
3826
3827 break;
3828 }
3829
3830 case VBOXESC_CRHGSMICTLCON_CALL:
3831 {
3832 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
3833 PVBOXDISPIFESCAPE_CRHGSMICTLCON_CALL pCall = (PVBOXDISPIFESCAPE_CRHGSMICTLCON_CALL)pEscapeHdr;
3834 if (pEscape->PrivateDriverDataSize >= sizeof (*pCall))
3835 {
3836 /* this is true due to the above condition */
3837 Assert(pEscape->PrivateDriverDataSize > RT_OFFSETOF(VBOXDISPIFESCAPE_CRHGSMICTLCON_CALL, CallInfo));
3838 int rc = VBoxMpCrCtlConCallUserData(&pDevExt->CrCtlCon, &pCall->CallInfo, pEscape->PrivateDriverDataSize - RT_OFFSETOF(VBOXDISPIFESCAPE_CRHGSMICTLCON_CALL, CallInfo));
3839 if (RT_SUCCESS(rc))
3840 Status = STATUS_SUCCESS;
3841 else
3842 {
3843 WARN(("VBoxMpCrUmCtlConCall failed, rc(%d)", rc));
3844 Status = STATUS_UNSUCCESSFUL;
3845 }
3846 }
3847 else
3848 {
3849 WARN(("buffer too small!"));
3850 Status = STATUS_BUFFER_TOO_SMALL;
3851 }
3852
3853 break;
3854 }
3855
3856 case VBOXESC_CRHGSMICTLCON_GETCLIENTID:
3857 {
3858 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
3859 if (pEscape->PrivateDriverDataSize == sizeof (*pEscapeHdr))
3860 {
3861 pEscapeHdr->u32CmdSpecific = pContext->u32CrConClientID;
3862 Status = STATUS_SUCCESS;
3863 }
3864 else
3865 {
3866 WARN(("unexpected buffer size!"));
3867 Status = STATUS_INVALID_PARAMETER;
3868 }
3869
3870 break;
3871 }
3872
3873 case VBOXESC_SETVISIBLEREGION:
3874 {
3875 /* visible regions for seamless */
3876 LPRGNDATA lpRgnData = VBOXDISPIFESCAPE_DATA(pEscapeHdr, RGNDATA);
3877 uint32_t cbData = VBOXDISPIFESCAPE_DATA_SIZE(pEscape->PrivateDriverDataSize);
3878 uint32_t cbRects = cbData - RT_OFFSETOF(RGNDATA, Buffer);
3879 /* the lpRgnData->Buffer comes to us as RECT
3880 * to avoid extra memcpy we cast it to PRTRECT assuming
3881 * they are identical
3882 * see AssertCompile's above */
3883
3884 RTRECT *pRect = (RTRECT *)&lpRgnData->Buffer;
3885
3886 uint32_t cRects = cbRects/sizeof(RTRECT);
3887 int rc;
3888
3889 LOG(("IOCTL_VIDEO_VBOX_SETVISIBLEREGION cRects=%d", cRects));
3890 Assert(cbRects >= sizeof(RTRECT)
3891 && cbRects == cRects*sizeof(RTRECT)
3892 && cRects == lpRgnData->rdh.nCount);
3893 if ( cbRects >= sizeof(RTRECT)
3894 && cbRects == cRects*sizeof(RTRECT)
3895 && cRects == lpRgnData->rdh.nCount)
3896 {
3897 /*
3898 * Inform the host about the visible region
3899 */
3900 VMMDevVideoSetVisibleRegion *req = NULL;
3901
3902 rc = VbglGRAlloc ((VMMDevRequestHeader **)&req,
3903 sizeof (VMMDevVideoSetVisibleRegion) + (cRects-1)*sizeof(RTRECT),
3904 VMMDevReq_VideoSetVisibleRegion);
3905 AssertRC(rc);
3906 if (RT_SUCCESS(rc))
3907 {
3908 req->cRect = cRects;
3909 memcpy(&req->Rect, pRect, cRects*sizeof(RTRECT));
3910
3911 rc = VbglGRPerform (&req->header);
3912 AssertRC(rc);
3913 if (!RT_SUCCESS(rc))
3914 {
3915 LOGREL(("VbglGRPerform failed rc (%d)", rc));
3916 Status = STATUS_UNSUCCESSFUL;
3917 }
3918 }
3919 else
3920 {
3921 LOGREL(("VbglGRAlloc failed rc (%d)", rc));
3922 Status = STATUS_UNSUCCESSFUL;
3923 }
3924 }
3925 else
3926 {
3927 LOGREL(("VBOXESC_SETVISIBLEREGION: incorrect buffer size (%d), reported count (%d)", cbRects, lpRgnData->rdh.nCount));
3928 AssertBreakpoint();
3929 Status = STATUS_INVALID_PARAMETER;
3930 }
3931 break;
3932 }
3933 case VBOXESC_ISVRDPACTIVE:
3934 /* @todo: implement */
3935 Status = STATUS_SUCCESS;
3936 break;
3937 case VBOXESC_SCREENLAYOUT:
3938 {
3939 /* set screen layout (unused currently) */
3940 if (pEscape->PrivateDriverDataSize < sizeof (VBOXDISPIFESCAPE_SCREENLAYOUT))
3941 {
3942 WARN(("VBOXESC_SCREENLAYOUT: incorrect buffer size (%d) < sizeof (VBOXDISPIFESCAPE_SCREENLAYOUT) (%d)",
3943 pEscape->PrivateDriverDataSize, sizeof (VBOXDISPIFESCAPE_SCREENLAYOUT)));
3944 Status = STATUS_INVALID_PARAMETER;
3945 break;
3946 }
3947
3948 PVBOXDISPIFESCAPE_SCREENLAYOUT pLo = (PVBOXDISPIFESCAPE_SCREENLAYOUT)pEscapeHdr;
3949 if (pLo->ScreenLayout.cScreens > (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays)
3950 {
3951 WARN(("VBOXESC_SCREENLAYOUT: number of screens too big (%d), should be <= (%d)",
3952 pLo->ScreenLayout.cScreens, VBoxCommonFromDeviceExt(pDevExt)->cDisplays));
3953 Status = STATUS_INVALID_PARAMETER;
3954 break;
3955 }
3956
3957 for (UINT i = 0; i < pLo->ScreenLayout.cScreens; ++i)
3958 {
3959 PVBOXSCREENLAYOUT_ELEMENT pEl = &pLo->ScreenLayout.aScreens[i];
3960 Assert(pEl->VidPnSourceId < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
3961 if (pEl->VidPnSourceId < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays)
3962 {
3963 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pEl->VidPnSourceId];
3964 NTSTATUS tmpStatus = vboxWddmGhDisplayUpdateScreenPos(pDevExt, pSource, &pEl->pos);
3965 Assert(tmpStatus == STATUS_SUCCESS);
3966 }
3967 }
3968
3969 Status = STATUS_SUCCESS;
3970 break;
3971 }
3972 case VBOXESC_SWAPCHAININFO:
3973 {
3974 /* set swapchain information */
3975 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
3976 Status = vboxWddmSwapchainCtxEscape(pDevExt, pContext, (PVBOXDISPIFESCAPE_SWAPCHAININFO)pEscapeHdr, pEscape->PrivateDriverDataSize);
3977 Assert(Status == STATUS_SUCCESS);
3978 break;
3979 }
3980 case VBOXESC_REINITVIDEOMODES:
3981 {
3982 /* clear driver's internal videomodes cache */
3983 VBoxWddmInvalidateVideoModesInfo(pDevExt);
3984 Status = STATUS_SUCCESS;
3985 break;
3986 }
3987 case VBOXESC_SHRC_ADDREF:
3988 case VBOXESC_SHRC_RELEASE:
3989 {
3990 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)pEscape->hDevice;
3991 /* query whether the allocation represanted by the given [wine-generated] shared resource handle still exists */
3992 if (pEscape->PrivateDriverDataSize != sizeof (VBOXDISPIFESCAPE_SHRC_REF))
3993 {
3994 WARN(("invalid buffer size for VBOXDISPIFESCAPE_SHRC_REF, was(%d), but expected (%d)",
3995 pEscape->PrivateDriverDataSize, sizeof (VBOXDISPIFESCAPE_SHRC_REF)));
3996 Status = STATUS_INVALID_PARAMETER;
3997 break;
3998 }
3999
4000 PVBOXDISPIFESCAPE_SHRC_REF pShRcRef = (PVBOXDISPIFESCAPE_SHRC_REF)pEscapeHdr;
4001 PVBOXWDDM_ALLOCATION pAlloc = vboxWddmGetAllocationFromHandle(pDevExt, (D3DKMT_HANDLE)pShRcRef->hAlloc);
4002 if (!pAlloc)
4003 {
4004 WARN(("failed to get allocation from handle"));
4005 Status = STATUS_INVALID_PARAMETER;
4006 break;
4007 }
4008
4009 PVBOXWDDM_OPENALLOCATION pOa = VBoxWddmOaSearch(pDevice, pAlloc);
4010 if (!pOa)
4011 {
4012 WARN(("failed to get open allocation from alloc"));
4013 Status = STATUS_INVALID_PARAMETER;
4014 break;
4015 }
4016
4017 Assert(pAlloc->cShRcRefs >= pOa->cShRcRefs);
4018
4019 if (pEscapeHdr->escapeCode == VBOXESC_SHRC_ADDREF)
4020 {
4021#ifdef DEBUG
4022 Assert(!pAlloc->fAssumedDeletion);
4023#endif
4024 ++pAlloc->cShRcRefs;
4025 ++pOa->cShRcRefs;
4026 }
4027 else
4028 {
4029 Assert(pAlloc->cShRcRefs);
4030 Assert(pOa->cShRcRefs);
4031 --pAlloc->cShRcRefs;
4032 --pOa->cShRcRefs;
4033#ifdef DEBUG
4034 Assert(!pAlloc->fAssumedDeletion);
4035 if (!pAlloc->cShRcRefs)
4036 {
4037 pAlloc->fAssumedDeletion = TRUE;
4038 }
4039#endif
4040 }
4041
4042 pShRcRef->EscapeHdr.u32CmdSpecific = pAlloc->cShRcRefs;
4043 Status = STATUS_SUCCESS;
4044 break;
4045 }
4046 case VBOXESC_DBGPRINT:
4047 {
4048 /* use RT_OFFSETOF instead of sizeof since sizeof will give an aligned size that might
4049 * be bigger than the VBOXDISPIFESCAPE_DBGPRINT with a data containing just a few chars */
4050 Assert(pEscape->PrivateDriverDataSize >= RT_OFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1]));
4051 /* only do DbgPrint when pEscape->PrivateDriverDataSize > RT_OFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1])
4052 * since == RT_OFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1]) means the buffer contains just \0,
4053 * i.e. no need to print it */
4054 if (pEscape->PrivateDriverDataSize > RT_OFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1]))
4055 {
4056 PVBOXDISPIFESCAPE_DBGPRINT pDbgPrint = (PVBOXDISPIFESCAPE_DBGPRINT)pEscapeHdr;
4057 /* ensure the last char is \0*/
4058 *((uint8_t*)pDbgPrint + pEscape->PrivateDriverDataSize - 1) = '\0';
4059 if (g_VBoxLogUm & VBOXWDDM_CFG_LOG_UM_DBGPRINT)
4060 DbgPrint("%s\n", pDbgPrint->aStringBuf);
4061 if (g_VBoxLogUm & VBOXWDDM_CFG_LOG_UM_BACKDOOR)
4062 LOGREL_EXACT(("%s\n", pDbgPrint->aStringBuf));
4063 }
4064 Status = STATUS_SUCCESS;
4065 break;
4066 }
4067 case VBOXESC_DBGDUMPBUF:
4068 {
4069 Status = vboxUmdDumpBuf((PVBOXDISPIFESCAPE_DBGDUMPBUF)pEscapeHdr, pEscape->PrivateDriverDataSize);
4070 break;
4071 }
4072 default:
4073 Assert(0);
4074 LOGREL(("unsupported escape code (0x%x)", pEscapeHdr->escapeCode));
4075 break;
4076 }
4077 }
4078 else
4079 {
4080 LOGREL(("pEscape->PrivateDriverDataSize(%d) < (%d)", pEscape->PrivateDriverDataSize, sizeof (VBOXDISPIFESCAPE)));
4081 AssertBreakpoint();
4082 Status = STATUS_BUFFER_TOO_SMALL;
4083 }
4084
4085// LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
4086
4087 return Status;
4088}
4089
4090NTSTATUS
4091APIENTRY
4092DxgkDdiCollectDbgInfo(
4093 CONST HANDLE hAdapter,
4094 CONST DXGKARG_COLLECTDBGINFO* pCollectDbgInfo
4095 )
4096{
4097 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
4098
4099 AssertBreakpoint();
4100
4101 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
4102
4103 return STATUS_SUCCESS;
4104}
4105
4106typedef struct VBOXWDDM_QUERYCURFENCE_CB
4107{
4108 PVBOXMP_DEVEXT pDevExt;
4109 ULONG MessageNumber;
4110 ULONG uLastCompletedCmdFenceId;
4111} VBOXWDDM_QUERYCURFENCE_CB, *PVBOXWDDM_QUERYCURFENCE_CB;
4112
4113static BOOLEAN vboxWddmQueryCurrentFenceCb(PVOID Context)
4114{
4115 PVBOXWDDM_QUERYCURFENCE_CB pdc = (PVBOXWDDM_QUERYCURFENCE_CB)Context;
4116 BOOL bRc = DxgkDdiInterruptRoutine(pdc->pDevExt, pdc->MessageNumber);
4117 pdc->uLastCompletedCmdFenceId = pdc->pDevExt->u.primary.Vdma.uLastCompletedPagingBufferCmdFenceId;
4118 return bRc;
4119}
4120
4121NTSTATUS
4122APIENTRY
4123DxgkDdiQueryCurrentFence(
4124 CONST HANDLE hAdapter,
4125 DXGKARG_QUERYCURRENTFENCE* pCurrentFence)
4126{
4127 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
4128
4129 vboxVDbgBreakF();
4130
4131 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
4132 VBOXWDDM_QUERYCURFENCE_CB context = {0};
4133 context.pDevExt = pDevExt;
4134 BOOLEAN bRet;
4135 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
4136 pDevExt->u.primary.DxgkInterface.DeviceHandle,
4137 vboxWddmQueryCurrentFenceCb,
4138 &context,
4139 0, /* IN ULONG MessageNumber */
4140 &bRet);
4141 Assert(Status == STATUS_SUCCESS);
4142 if (Status == STATUS_SUCCESS)
4143 {
4144 pCurrentFence->CurrentFence = context.uLastCompletedCmdFenceId;
4145 }
4146
4147 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
4148
4149 return STATUS_SUCCESS;
4150}
4151
4152NTSTATUS
4153APIENTRY
4154DxgkDdiIsSupportedVidPn(
4155 CONST HANDLE hAdapter,
4156 OUT DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPnArg
4157 )
4158{
4159 /* The DxgkDdiIsSupportedVidPn should be made pageable. */
4160 PAGED_CODE();
4161
4162 LOGF(("ENTER, context(0x%x)", hAdapter));
4163
4164 vboxVDbgBreakFv();
4165
4166 NTSTATUS Status = STATUS_SUCCESS;
4167 BOOLEAN bSupported = TRUE;
4168
4169 PVBOXMP_DEVEXT pContext = (PVBOXMP_DEVEXT)hAdapter;
4170 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
4171 Status = pContext->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pIsSupportedVidPnArg->hDesiredVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
4172 if (!NT_SUCCESS(Status))
4173 {
4174 WARN(("DxgkCbQueryVidPnInterface failed Status()0x%x\n", Status));
4175 return Status;
4176 }
4177
4178#ifdef VBOXWDDM_DEBUG_VIDPN
4179 vboxVidPnDumpVidPn("\n>>>>IS SUPPORTED VidPN : >>>>", pContext, pIsSupportedVidPnArg->hDesiredVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<");
4180#endif
4181
4182 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
4183 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
4184 Status = pVidPnInterface->pfnGetTopology(pIsSupportedVidPnArg->hDesiredVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
4185 if (!NT_SUCCESS(Status))
4186 {
4187 WARN(("pfnGetTopology failed Status()0x%x\n", Status));
4188 return Status;
4189 }
4190
4191 VBOXVIDPNPATHITEM aItems[VBOX_VIDEO_MAX_SCREENS];
4192 BOOLEAN fDisabledFound = FALSE;
4193 Status = vboxVidPnCheckTopology(hVidPnTopology, pVidPnTopologyInterface, TRUE /* fBreakOnDisabled */, RT_ELEMENTS(aItems), aItems, &fDisabledFound);
4194 Assert(Status == STATUS_SUCCESS);
4195 if (!NT_SUCCESS(Status))
4196 {
4197 WARN(("vboxVidPnCheckTopology failed Status()0x%x\n", Status));
4198 return Status;
4199 }
4200
4201 if (fDisabledFound)
4202 {
4203 WARN(("found unsupported path"));
4204 bSupported = FALSE;
4205 }
4206
4207 pIsSupportedVidPnArg->IsVidPnSupported = bSupported;
4208
4209#ifdef VBOXWDDM_DEBUG_VIDPN
4210 LOGREL(("The Given VidPn is %ssupported\n", pIsSupportedVidPnArg->IsVidPnSupported ? "" : "!!NOT!! "));
4211#endif
4212
4213 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
4214
4215 return Status;
4216}
4217
4218NTSTATUS
4219APIENTRY
4220DxgkDdiRecommendFunctionalVidPn(
4221 CONST HANDLE hAdapter,
4222 CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPnArg
4223 )
4224{
4225 /* The DxgkDdiRecommendFunctionalVidPn should be made pageable. */
4226 PAGED_CODE();
4227
4228 LOGF(("ENTER, context(0x%x)", hAdapter));
4229
4230 vboxVDbgBreakFv();
4231
4232 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
4233 NTSTATUS Status;
4234 PVBOXWDDM_RECOMMENDVIDPN pVidPnInfo = pRecommendFunctionalVidPnArg->PrivateDriverDataSize >= sizeof (VBOXWDDM_RECOMMENDVIDPN) ?
4235 (PVBOXWDDM_RECOMMENDVIDPN)pRecommendFunctionalVidPnArg->pPrivateDriverData : NULL;
4236 PVBOXWDDM_VIDEOMODES_INFO pInfos = VBoxWddmUpdateVideoModesInfo(pDevExt, NULL /*pVidPnInfo*/);
4237 int i;
4238
4239 for (i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
4240 {
4241 /* @todo: check that we actually need the current source->target */
4242 PVBOXWDDM_VIDEOMODES_INFO pInfo = &pInfos[i];
4243 VIDEO_MODE_INFORMATION *pModeInfo = &pInfo->aModes[pInfo->iPreferredMode];
4244#if 0
4245 D3DKMDT_2DREGION Resolution;
4246 Resolution.cx = pModeInfo->VisScreenWidth;
4247 Resolution.cy = pModeInfo->VisScreenHeight;
4248 Status = vboxVidPnCheckAddMonitorModes(pDevExt, i, D3DKMDT_MCO_DRIVER, &Resolution, 1, 0);
4249#else
4250 Status = vboxVidPnCheckAddMonitorModes(pDevExt, i, D3DKMDT_MCO_DRIVER, pInfo->aResolutions, pInfo->cResolutions, pInfo->iPreferredResolution);
4251#endif
4252 Assert(Status == STATUS_SUCCESS);
4253 if (Status != STATUS_SUCCESS)
4254 {
4255 LOGREL(("vboxVidPnCheckAddMonitorModes failed Status(0x%x)", Status));
4256 break;
4257 }
4258 }
4259
4260 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
4261 Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
4262 if (!NT_SUCCESS(Status))
4263 {
4264 WARN(("DxgkCbQueryVidPnInterface failed Status(0x%x)", Status));
4265 return Status;
4266 }
4267
4268 for (i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
4269 {
4270 Status = vboxVidPnPathAdd(pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, pVidPnInterface, i, i);
4271 if (!NT_SUCCESS(Status))
4272 {
4273 WARN(("vboxVidPnPathAdd failed Status(0x%x)", Status));
4274 return Status;
4275 }
4276 }
4277
4278 VIDEO_MODE_INFORMATION *pResModes = NULL;
4279 uint32_t cResModes = 0;
4280
4281 for (i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
4282 {
4283 D3DKMDT_2DREGION Resolution;
4284 PVBOXWDDM_VIDEOMODES_INFO pInfo = &pInfos[i];
4285 VIDEO_MODE_INFORMATION *pModeInfo = &pInfo->aModes[pInfo->iPreferredMode];
4286 Resolution.cx = pModeInfo->VisScreenWidth;
4287 Resolution.cy = pModeInfo->VisScreenHeight;
4288 int32_t iPreferableResMode;
4289 uint32_t cActualResModes;
4290
4291 Status = VBoxWddmGetModesForResolution(pInfo->aModes, pInfo->cModes, pInfo->iPreferredMode, &Resolution,
4292 pResModes, cResModes, &cActualResModes, &iPreferableResMode);
4293 Assert(Status == STATUS_SUCCESS || Status == STATUS_BUFFER_TOO_SMALL);
4294 if (Status == STATUS_BUFFER_TOO_SMALL)
4295 {
4296 Assert(cResModes < cActualResModes);
4297 if (pResModes)
4298 {
4299 vboxWddmMemFree(pResModes);
4300 }
4301 pResModes = (VIDEO_MODE_INFORMATION*)vboxWddmMemAllocZero(sizeof (*pResModes) * cActualResModes);
4302 Assert(pResModes);
4303 if (!pResModes)
4304 {
4305 Status = STATUS_NO_MEMORY;
4306 break;
4307 }
4308 cResModes = cActualResModes;
4309 Status = VBoxWddmGetModesForResolution(pInfo->aModes, pInfo->cModes, pInfo->iPreferredMode, &Resolution,
4310 pResModes, cResModes, &cActualResModes, &iPreferableResMode);
4311 Assert(Status == STATUS_SUCCESS);
4312 if (Status != STATUS_SUCCESS)
4313 break;
4314 }
4315 else if (Status != STATUS_SUCCESS)
4316 break;
4317
4318 Assert(iPreferableResMode >= 0);
4319 Assert(cActualResModes);
4320
4321 Status = vboxVidPnCreatePopulateVidPnPathFromLegacy(pDevExt, pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, pVidPnInterface,
4322 pResModes, cActualResModes, iPreferableResMode,
4323 &Resolution, 1 /* cResolutions */,
4324 i, i); /* srcId, tgtId */
4325 Assert(Status == STATUS_SUCCESS);
4326 if (Status != STATUS_SUCCESS)
4327 {
4328 LOGREL(("vboxVidPnCreatePopulateVidPnFromLegacy failed Status(0x%x)", Status));
4329 break;
4330 }
4331 }
4332
4333 if(pResModes)
4334 vboxWddmMemFree(pResModes);
4335
4336#ifdef VBOXWDDM_DEBUG_VIDPN
4337 vboxVidPnDumpVidPn("\n>>>>Recommended VidPN: >>>>", pDevExt, pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<\n");
4338#endif
4339
4340 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
4341
4342 return Status;
4343}
4344
4345NTSTATUS
4346APIENTRY
4347DxgkDdiEnumVidPnCofuncModality(
4348 CONST HANDLE hAdapter,
4349 CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModalityArg
4350 )
4351{
4352 /* The DxgkDdiEnumVidPnCofuncModality function should be made pageable. */
4353 PAGED_CODE();
4354
4355 LOGF(("ENTER, context(0x%x)", hAdapter));
4356
4357 vboxVDbgBreakFv();
4358
4359 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
4360 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
4361 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pEnumCofuncModalityArg->hConstrainingVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
4362 if (!NT_SUCCESS(Status))
4363 {
4364 WARN(("DxgkCbQueryVidPnInterface failed Status()0x%x\n", Status));
4365 return Status;
4366 }
4367#ifdef VBOXWDDM_DEBUG_VIDPN
4368 vboxVidPnDumpCofuncModalityArg(">>>>MODALITY Args: ", pEnumCofuncModalityArg, "\n");
4369 vboxVidPnDumpVidPn(">>>>MODALITY VidPN (IN) : >>>>\n", pDevExt, pEnumCofuncModalityArg->hConstrainingVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<\n");
4370#endif
4371
4372 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
4373 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
4374 Status = pVidPnInterface->pfnGetTopology(pEnumCofuncModalityArg->hConstrainingVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
4375 Assert(Status == STATUS_SUCCESS);
4376 if (!NT_SUCCESS(Status))
4377 {
4378 WARN(("pfnGetTopology failed Status()0x%x\n", Status));
4379 return Status;
4380 }
4381
4382 VBOXVIDPNPATHITEM aItems[VBOX_VIDEO_MAX_SCREENS];
4383 Status = vboxVidPnCheckTopology(hVidPnTopology, pVidPnTopologyInterface, FALSE /* fBreakOnDisabled */, RT_ELEMENTS(aItems), aItems, NULL /* *pfDisabledFound */);
4384 Assert(Status == STATUS_SUCCESS);
4385 if (!NT_SUCCESS(Status))
4386 {
4387 WARN(("vboxVidPnCheckTopology failed Status()0x%x\n", Status));
4388 return Status;
4389 }
4390
4391 VBOXVIDPNCOFUNCMODALITY CbContext = {0};
4392 CbContext.pDevExt = pDevExt;
4393 CbContext.pVidPnInterface = pVidPnInterface;
4394 CbContext.pEnumCofuncModalityArg = pEnumCofuncModalityArg;
4395 CbContext.pInfos = VBoxWddmGetAllVideoModesInfos(pDevExt);
4396 CbContext.cPathInfos = RT_ELEMENTS(aItems);
4397 CbContext.apPathInfos = aItems;
4398
4399 Status = vboxVidPnEnumPaths(hVidPnTopology, pVidPnTopologyInterface,
4400 vboxVidPnCofuncModalityPathEnum, &CbContext);
4401 Assert(Status == STATUS_SUCCESS);
4402 if (!NT_SUCCESS(Status))
4403 {
4404 WARN(("vboxVidPnEnumPaths failed Status()0x%x\n", Status));
4405 return Status;
4406 }
4407
4408 Status = CbContext.Status;
4409 if (!NT_SUCCESS(Status))
4410 {
4411 WARN(("vboxVidPnCofuncModalityPathEnum failed Status()0x%x\n", Status));
4412 return Status;
4413 }
4414
4415#ifdef VBOXWDDM_DEBUG_VIDPN
4416 vboxVidPnDumpVidPn("\n>>>>MODALITY VidPN (OUT) : >>>>\n", pDevExt, pEnumCofuncModalityArg->hConstrainingVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<\n\n");
4417#endif
4418
4419 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
4420
4421 return Status;
4422}
4423
4424NTSTATUS
4425APIENTRY
4426DxgkDdiSetVidPnSourceAddress(
4427 CONST HANDLE hAdapter,
4428 CONST DXGKARG_SETVIDPNSOURCEADDRESS* pSetVidPnSourceAddress
4429 )
4430{
4431 /* The DxgkDdiSetVidPnSourceAddress function should be made pageable. */
4432 PAGED_CODE();
4433
4434 vboxVDbgBreakFv();
4435
4436 LOGF(("ENTER, context(0x%x)", hAdapter));
4437
4438 NTSTATUS Status = STATUS_SUCCESS;
4439 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
4440 Assert((UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays > pSetVidPnSourceAddress->VidPnSourceId);
4441
4442 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pSetVidPnSourceAddress->VidPnSourceId];
4443 Status= vboxWddmDisplaySettingsQueryPos(pDevExt, pSetVidPnSourceAddress->VidPnSourceId, &pSource->VScreenPos);
4444 Assert(Status == STATUS_SUCCESS);
4445 Status = STATUS_SUCCESS;
4446
4447 if ((UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays > pSetVidPnSourceAddress->VidPnSourceId)
4448 {
4449 PVBOXWDDM_ALLOCATION pAllocation;
4450 Assert(pSetVidPnSourceAddress->hAllocation);
4451 Assert(pSetVidPnSourceAddress->hAllocation || pSource->pPrimaryAllocation);
4452 Assert (pSetVidPnSourceAddress->Flags.Value < 2); /* i.e. 0 or 1 (ModeChange) */
4453 if (pSetVidPnSourceAddress->hAllocation)
4454 {
4455 pAllocation = (PVBOXWDDM_ALLOCATION)pSetVidPnSourceAddress->hAllocation;
4456 vboxWddmAssignPrimary(pDevExt, pSource, pAllocation, pSetVidPnSourceAddress->VidPnSourceId);
4457 }
4458 else
4459 pAllocation = pSource->pPrimaryAllocation;
4460
4461 Assert(pAllocation);
4462 Assert(pAllocation->SurfDesc.VidPnSourceId == pSetVidPnSourceAddress->VidPnSourceId);
4463
4464 if (pAllocation)
4465 {
4466// Assert(pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE);
4467 vboxWddmAllocUpdateAddress(pAllocation, pSetVidPnSourceAddress->PrimarySegment, (VBOXVIDEOOFFSET)pSetVidPnSourceAddress->PrimaryAddress.QuadPart);
4468 Assert (pAllocation->SegmentId);
4469 Assert (!pAllocation->bVisible);
4470 Assert(pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
4471 || pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC);
4472
4473 if (
4474#ifdef VBOXWDDM_RENDER_FROM_SHADOW
4475 /* this is the case of full-screen d3d, ensure we notify host */
4476 pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC &&
4477#endif
4478 pAllocation->bVisible)
4479 {
4480#ifdef VBOXWDDM_RENDER_FROM_SHADOW
4481 /* to ensure the resize request gets issued in case we exit a full-screen D3D mode */
4482 pSource->offVram = VBOXVIDEOOFFSET_VOID;
4483#else
4484 /* should not generally happen, but still inform host*/
4485 Status = vboxWddmGhDisplaySetInfo(pDevExt, pSource, pSetVidPnSourceAddress->VidPnSourceId);
4486 Assert(Status == STATUS_SUCCESS);
4487 if (Status != STATUS_SUCCESS)
4488 LOGREL(("vboxWddmGhDisplaySetInfo failed, Status (0x%x)", Status));
4489#endif
4490 }
4491 }
4492 else
4493 {
4494 WARN(("no allocation data available!!"));
4495 Status = STATUS_INVALID_PARAMETER;
4496 }
4497 }
4498 else
4499 {
4500 WARN(("invalid VidPnSourceId (%d), should be smaller than (%d)", pSetVidPnSourceAddress->VidPnSourceId, VBoxCommonFromDeviceExt(pDevExt)->cDisplays));
4501 Status = STATUS_INVALID_PARAMETER;
4502 }
4503
4504 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
4505
4506 return Status;
4507}
4508
4509NTSTATUS
4510APIENTRY
4511DxgkDdiSetVidPnSourceVisibility(
4512 CONST HANDLE hAdapter,
4513 CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility
4514 )
4515{
4516 /* DxgkDdiSetVidPnSourceVisibility should be made pageable. */
4517 PAGED_CODE();
4518
4519 vboxVDbgBreakFv();
4520
4521 LOGF(("ENTER, context(0x%x)", hAdapter));
4522
4523 NTSTATUS Status = STATUS_SUCCESS;
4524 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
4525 Assert((UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays > pSetVidPnSourceVisibility->VidPnSourceId);
4526
4527 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pSetVidPnSourceVisibility->VidPnSourceId];
4528 Status= vboxWddmDisplaySettingsQueryPos(pDevExt, pSetVidPnSourceVisibility->VidPnSourceId, &pSource->VScreenPos);
4529 Assert(Status == STATUS_SUCCESS);
4530 Status = STATUS_SUCCESS;
4531
4532 if ((UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays > pSetVidPnSourceVisibility->VidPnSourceId)
4533 {
4534 PVBOXWDDM_ALLOCATION pAllocation = pSource->pPrimaryAllocation;
4535 if (pAllocation)
4536 {
4537 Assert(pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
4538 || pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC);
4539
4540 Assert(pAllocation->bVisible != pSetVidPnSourceVisibility->Visible);
4541 if (pAllocation->bVisible != pSetVidPnSourceVisibility->Visible)
4542 {
4543 pAllocation->bVisible = pSetVidPnSourceVisibility->Visible;
4544 if (pAllocation->bVisible)
4545 {
4546#ifdef VBOXWDDM_RENDER_FROM_SHADOW
4547 if (/* this is the case of full-screen d3d, ensure we notify host */
4548 pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC
4549 )
4550#endif
4551 {
4552#ifdef VBOXWDDM_RENDER_FROM_SHADOW
4553 /* to ensure the resize request gets issued in case we exit a full-screen D3D mode */
4554 pSource->offVram = VBOXVIDEOOFFSET_VOID;
4555#else
4556 Status = vboxWddmGhDisplaySetInfo(pDevExt, pSource, pSetVidPnSourceVisibility->VidPnSourceId);
4557 Assert(Status == STATUS_SUCCESS);
4558 if (Status != STATUS_SUCCESS)
4559 LOGREL(("vboxWddmGhDisplaySetInfo failed, Status (0x%x)", Status));
4560#endif
4561 }
4562 }
4563#ifdef VBOX_WITH_VDMA
4564 else
4565 {
4566 vboxVdmaFlush (pDevExt, &pDevExt->u.primary.Vdma);
4567 }
4568#endif
4569 }
4570 }
4571 else
4572 {
4573 Assert(!pSetVidPnSourceVisibility->Visible);
4574 }
4575 }
4576 else
4577 {
4578 LOGREL(("invalid VidPnSourceId (%d), should be smaller than (%d)", pSetVidPnSourceVisibility->VidPnSourceId, VBoxCommonFromDeviceExt(pDevExt)->cDisplays));
4579 Status = STATUS_INVALID_PARAMETER;
4580 }
4581
4582 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
4583
4584 return Status;
4585}
4586
4587static DECLCALLBACK(BOOLEAN) vboxWddmVidPnCleanupTargetsForSrcEnum(PVBOXMP_DEVEXT pDevExt, D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface,
4588 CONST D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId, SIZE_T cTgtPaths, PVOID pContext)
4589{
4590 AssertRelease(VidPnTargetId < RT_ELEMENTS(pDevExt->aTargets));
4591 PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[VidPnTargetId];
4592 /* see comments in DxgkDdiCommitVidPn */
4593 pTarget->HeightVisible = 0;
4594 return TRUE;
4595}
4596
4597
4598NTSTATUS
4599APIENTRY
4600DxgkDdiCommitVidPn(
4601 CONST HANDLE hAdapter,
4602 CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPnArg
4603 )
4604{
4605 LOGF(("ENTER, context(0x%x)", hAdapter));
4606
4607 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
4608 uint32_t au32OldHeightVisible[VBOX_VIDEO_MAX_SCREENS];
4609 NTSTATUS Status;
4610
4611 vboxVDbgBreakFv();
4612
4613 /* we first store the current visible height for each target (monitor)
4614 * and then we will zero up it for targets either for the given source
4615 * (in case pCommitVidPnArg->AffectedVidPnSourceId != D3DDDI_ID_ALL)
4616 * or all targets otherwize.
4617 * In the end we will match the old and new visible height for all targets to see if
4618 * some of them become inactivated and hide them accordingly,
4619 * or we will restore the old height values on failure */
4620 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
4621 {
4622 PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[i];
4623 au32OldHeightVisible[i] = pTarget->HeightVisible;
4624 }
4625
4626 do {
4627 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
4628 Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pCommitVidPnArg->hFunctionalVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
4629 if (!NT_SUCCESS(Status))
4630 {
4631 WARN(("DxgkCbQueryVidPnInterface failed Status 0x%x", Status));
4632 break;
4633 }
4634
4635#ifdef VBOXWDDM_DEBUG_VIDPN
4636 vboxVidPnDumpVidPn("\n>>>>COMMIT VidPN: >>>>", pDevExt, pCommitVidPnArg->hFunctionalVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<\n");
4637#endif
4638
4639 if (pCommitVidPnArg->AffectedVidPnSourceId != D3DDDI_ID_ALL)
4640 {
4641 /* there is not VidPn on driver start, check that */
4642 if (pDevExt->u.primary.hCommittedVidPn)
4643 {
4644 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
4645 CONST DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
4646 const DXGK_VIDPN_INTERFACE* pOldVidPnInterface = NULL;
4647 Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pDevExt->u.primary.hCommittedVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pOldVidPnInterface);
4648 if (!NT_SUCCESS(Status))
4649 {
4650 WARN(("DxgkCbQueryVidPnInterface for current VidPn failed Status 0x%x", Status));
4651 break;
4652 }
4653
4654 Status = pOldVidPnInterface->pfnGetTopology(pDevExt->u.primary.hCommittedVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
4655 if (!NT_SUCCESS(Status))
4656 {
4657 WARN(("pfnGetTopology for current VidPn failed Status 0x%x", Status));
4658 break;
4659 }
4660
4661 /* this will sero up visible height for all targets of the fiven source, see above comment */
4662 Status = vboxVidPnEnumTargetsForSource(pDevExt, hVidPnTopology, pVidPnTopologyInterface,
4663 pCommitVidPnArg->AffectedVidPnSourceId,
4664 vboxWddmVidPnCleanupTargetsForSrcEnum, NULL);
4665 if (Status == STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY)
4666 Status = STATUS_SUCCESS;
4667
4668 if (!NT_SUCCESS(Status))
4669 {
4670 WARN(("vboxVidPnEnumTargetsForSource for current VidPn failed Status 0x%x", Status));
4671 break;
4672 }
4673 }
4674
4675 Status = vboxVidPnCommitSourceModeForSrcId(
4676 pDevExt,
4677 pCommitVidPnArg->hFunctionalVidPn, pVidPnInterface,
4678 pCommitVidPnArg->AffectedVidPnSourceId, (PVBOXWDDM_ALLOCATION)pCommitVidPnArg->hPrimaryAllocation);
4679 if (!NT_SUCCESS(Status))
4680 {
4681 WARN(("vboxVidPnCommitSourceModeForSrcId for current VidPn failed Status 0x%x", Status));
4682 break;
4683 }
4684 }
4685 else
4686 {
4687 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
4688 {
4689 PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[i];
4690 /* see above comment */
4691 pTarget->HeightVisible = 0;
4692 }
4693
4694 /* clear all current primaries */
4695 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
4696 {
4697 vboxWddmAssignPrimary(pDevExt, &pDevExt->aSources[i], NULL, i);
4698 }
4699
4700 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
4701 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
4702 Status = pVidPnInterface->pfnGetTopology(pCommitVidPnArg->hFunctionalVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
4703 if (!NT_SUCCESS(Status))
4704 {
4705 WARN(("pfnGetTopology failed Status 0x%x", Status));
4706 break;
4707 }
4708
4709 VBOXVIDPNCOMMIT CbContext = {0};
4710 CbContext.pDevExt = pDevExt;
4711 CbContext.pVidPnInterface = pVidPnInterface;
4712 CbContext.pCommitVidPnArg = pCommitVidPnArg;
4713 Status = vboxVidPnEnumPaths(hVidPnTopology, pVidPnTopologyInterface,
4714 vboxVidPnCommitPathEnum, &CbContext);
4715 if (!NT_SUCCESS(Status))
4716 {
4717 WARN(("vboxVidPnEnumPaths failed Status 0x%x", Status));
4718 break;
4719 }
4720
4721 Status = CbContext.Status;
4722 if (!NT_SUCCESS(Status))
4723 {
4724 WARN(("vboxVidPnCommitPathEnum failed Status 0x%x", Status));
4725 break;
4726 }
4727 }
4728
4729 Assert(NT_SUCCESS(Status));
4730 pDevExt->u.primary.hCommittedVidPn = pCommitVidPnArg->hFunctionalVidPn;
4731
4732 for (int i = 1; /* <- never try to hide a primary monitor */
4733 i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
4734 {
4735 PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[i];
4736 if (!pTarget->HeightVisible && !!au32OldHeightVisible[i])
4737 {
4738 /* the target was previously visible */
4739 vboxWddmGhDisplayHideScreen(pDevExt, i);
4740 }
4741 }
4742
4743 LOGF(("LEAVE, SUCCESS status(0x%x), context(0x%x)", Status, hAdapter));
4744
4745 return Status;
4746 } while (0);
4747
4748 AssertRelease(!NT_SUCCESS(Status));
4749 /* failure branch restore original visible height values, see comments above */
4750 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
4751 {
4752 PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[i];
4753 pTarget->HeightVisible = au32OldHeightVisible[i];
4754 }
4755
4756 LOGF(("LEAVE, !!FAILURE!! status(0x%x), context(0x%x)", Status, hAdapter));
4757 return Status;
4758}
4759
4760NTSTATUS
4761APIENTRY
4762DxgkDdiUpdateActiveVidPnPresentPath(
4763 CONST HANDLE hAdapter,
4764 CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPathArg
4765 )
4766{
4767 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
4768
4769 AssertBreakpoint();
4770
4771 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
4772
4773 return STATUS_SUCCESS;
4774}
4775
4776NTSTATUS
4777APIENTRY
4778DxgkDdiRecommendMonitorModes(
4779 CONST HANDLE hAdapter,
4780 CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModesArg
4781 )
4782{
4783 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
4784
4785 vboxVDbgBreakFv();
4786
4787 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
4788 NTSTATUS Status;
4789 PVBOXWDDM_VIDEOMODES_INFO pInfo = VBoxWddmGetVideoModesInfo(pDevExt, pRecommendMonitorModesArg->VideoPresentTargetId);
4790 PVIDEO_MODE_INFORMATION pPreferredMode = &pInfo->aModes[pInfo->iPreferredMode];
4791
4792
4793 for (uint32_t i = 0; i < pInfo->cResolutions; i++)
4794 {
4795 D3DKMDT_MONITOR_SOURCE_MODE * pNewMonitorSourceModeInfo;
4796 Status = pRecommendMonitorModesArg->pMonitorSourceModeSetInterface->pfnCreateNewModeInfo(
4797 pRecommendMonitorModesArg->hMonitorSourceModeSet, &pNewMonitorSourceModeInfo);
4798 Assert(Status == STATUS_SUCCESS);
4799 if (Status == STATUS_SUCCESS)
4800 {
4801 Status = vboxVidPnPopulateMonitorSourceModeInfoFromLegacy(pDevExt,
4802 pNewMonitorSourceModeInfo,
4803 &pInfo->aResolutions[i],
4804 D3DKMDT_MCO_DRIVER,
4805 pPreferredMode->VisScreenWidth == pInfo->aResolutions[i].cx
4806 && pPreferredMode->VisScreenHeight == pInfo->aResolutions[i].cy);
4807 Assert(Status == STATUS_SUCCESS);
4808 if (Status == STATUS_SUCCESS)
4809 {
4810 Status = pRecommendMonitorModesArg->pMonitorSourceModeSetInterface->pfnAddMode(
4811 pRecommendMonitorModesArg->hMonitorSourceModeSet, pNewMonitorSourceModeInfo);
4812 Assert(Status == STATUS_SUCCESS);
4813 if (Status == STATUS_SUCCESS)
4814 continue;
4815 }
4816
4817 /* error has occurred, release & break */
4818 pRecommendMonitorModesArg->pMonitorSourceModeSetInterface->pfnReleaseModeInfo(
4819 pRecommendMonitorModesArg->hMonitorSourceModeSet, pNewMonitorSourceModeInfo);
4820 break;
4821 }
4822 }
4823
4824 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
4825
4826 return Status;
4827}
4828
4829NTSTATUS
4830APIENTRY
4831DxgkDdiRecommendVidPnTopology(
4832 CONST HANDLE hAdapter,
4833 CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopologyArg
4834 )
4835{
4836 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
4837
4838 vboxVDbgBreakFv();
4839
4840 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
4841
4842 return STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY;
4843}
4844
4845NTSTATUS
4846APIENTRY
4847DxgkDdiGetScanLine(
4848 CONST HANDLE hAdapter,
4849 DXGKARG_GETSCANLINE* pGetScanLine)
4850{
4851 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
4852
4853 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
4854
4855 Assert((UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays > pGetScanLine->VidPnTargetId);
4856 VBOXWDDM_TARGET *pTarget = &pDevExt->aTargets[pGetScanLine->VidPnTargetId];
4857 Assert(pTarget->HeightTotal);
4858 Assert(pTarget->HeightVisible);
4859 Assert(pTarget->HeightTotal > pTarget->HeightVisible);
4860 Assert(pTarget->ScanLineState < pTarget->HeightTotal);
4861 if (pTarget->HeightTotal)
4862 {
4863 uint32_t curScanLine = pTarget->ScanLineState;
4864 ++pTarget->ScanLineState;
4865 if (pTarget->ScanLineState >= pTarget->HeightTotal)
4866 pTarget->ScanLineState = 0;
4867
4868
4869 BOOL bVBlank = (!curScanLine || curScanLine > pTarget->HeightVisible);
4870 pGetScanLine->ScanLine = curScanLine;
4871 pGetScanLine->InVerticalBlank = bVBlank;
4872 }
4873 else
4874 {
4875 pGetScanLine->InVerticalBlank = TRUE;
4876 pGetScanLine->ScanLine = 0;
4877 }
4878
4879 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
4880
4881 return STATUS_SUCCESS;
4882}
4883
4884NTSTATUS
4885APIENTRY
4886DxgkDdiStopCapture(
4887 CONST HANDLE hAdapter,
4888 CONST DXGKARG_STOPCAPTURE* pStopCapture)
4889{
4890 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
4891
4892 AssertBreakpoint();
4893
4894 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
4895
4896 return STATUS_SUCCESS;
4897}
4898
4899NTSTATUS
4900APIENTRY
4901DxgkDdiControlInterrupt(
4902 CONST HANDLE hAdapter,
4903 CONST DXGK_INTERRUPT_TYPE InterruptType,
4904 BOOLEAN Enable
4905 )
4906{
4907 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
4908
4909// AssertBreakpoint();
4910
4911 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
4912
4913 /* @todo: STATUS_NOT_IMPLEMENTED ?? */
4914 return STATUS_SUCCESS;
4915}
4916
4917NTSTATUS
4918APIENTRY
4919DxgkDdiCreateOverlay(
4920 CONST HANDLE hAdapter,
4921 DXGKARG_CREATEOVERLAY *pCreateOverlay)
4922{
4923 LOGF(("ENTER, hAdapter(0x%p)", hAdapter));
4924
4925 NTSTATUS Status = STATUS_SUCCESS;
4926 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
4927 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)vboxWddmMemAllocZero(sizeof (VBOXWDDM_OVERLAY));
4928 Assert(pOverlay);
4929 if (pOverlay)
4930 {
4931 int rc = vboxVhwaHlpOverlayCreate(pDevExt, pCreateOverlay->VidPnSourceId, &pCreateOverlay->OverlayInfo, pOverlay);
4932 AssertRC(rc);
4933 if (RT_SUCCESS(rc))
4934 {
4935 pCreateOverlay->hOverlay = pOverlay;
4936 }
4937 else
4938 {
4939 vboxWddmMemFree(pOverlay);
4940 Status = STATUS_UNSUCCESSFUL;
4941 }
4942 }
4943 else
4944 Status = STATUS_NO_MEMORY;
4945
4946 LOGF(("LEAVE, hAdapter(0x%p)", hAdapter));
4947
4948 return Status;
4949}
4950
4951NTSTATUS
4952APIENTRY
4953DxgkDdiDestroyDevice(
4954 CONST HANDLE hDevice)
4955{
4956 /* DxgkDdiDestroyDevice should be made pageable. */
4957 PAGED_CODE();
4958
4959 LOGF(("ENTER, hDevice(0x%x)", hDevice));
4960
4961 vboxVDbgBreakFv();
4962
4963 vboxWddmMemFree(hDevice);
4964
4965 LOGF(("LEAVE, "));
4966
4967 return STATUS_SUCCESS;
4968}
4969
4970
4971
4972/*
4973 * DxgkDdiOpenAllocation
4974 */
4975NTSTATUS
4976APIENTRY
4977DxgkDdiOpenAllocation(
4978 CONST HANDLE hDevice,
4979 CONST DXGKARG_OPENALLOCATION *pOpenAllocation)
4980{
4981 /* DxgkDdiOpenAllocation should be made pageable. */
4982 PAGED_CODE();
4983
4984 LOGF(("ENTER, hDevice(0x%x)", hDevice));
4985
4986 vboxVDbgBreakFv();
4987
4988 NTSTATUS Status = STATUS_SUCCESS;
4989 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)hDevice;
4990 PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
4991 PVBOXWDDM_RCINFO pRcInfo = NULL;
4992 if (pOpenAllocation->PrivateDriverSize)
4993 {
4994 Assert(pOpenAllocation->PrivateDriverSize == sizeof (VBOXWDDM_RCINFO));
4995 Assert(pOpenAllocation->pPrivateDriverData);
4996 if (pOpenAllocation->PrivateDriverSize >= sizeof (VBOXWDDM_RCINFO))
4997 {
4998 pRcInfo = (PVBOXWDDM_RCINFO)pOpenAllocation->pPrivateDriverData;
4999 Assert(pRcInfo->cAllocInfos == pOpenAllocation->NumAllocations);
5000 }
5001 else
5002 Status = STATUS_INVALID_PARAMETER;
5003 }
5004
5005 if (Status == STATUS_SUCCESS)
5006 {
5007 UINT i = 0;
5008 for (; i < pOpenAllocation->NumAllocations; ++i)
5009 {
5010 DXGK_OPENALLOCATIONINFO* pInfo = &pOpenAllocation->pOpenAllocation[i];
5011 Assert(pInfo->PrivateDriverDataSize == sizeof (VBOXWDDM_ALLOCINFO));
5012 Assert(pInfo->pPrivateDriverData);
5013 PVBOXWDDM_ALLOCATION pAllocation = vboxWddmGetAllocationFromHandle(pDevExt, pInfo->hAllocation);
5014 if (!pAllocation)
5015 {
5016 WARN(("invalid handle"));
5017 Status = STATUS_INVALID_PARAMETER;
5018 break;
5019 }
5020
5021#ifdef DEBUG
5022 Assert(!pAllocation->fAssumedDeletion);
5023#endif
5024 if (pRcInfo)
5025 {
5026 Assert(pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC);
5027
5028 if (pInfo->PrivateDriverDataSize != sizeof (VBOXWDDM_ALLOCINFO)
5029 || !pInfo->pPrivateDriverData)
5030 {
5031 WARN(("invalid data size"));
5032 Status = STATUS_INVALID_PARAMETER;
5033 break;
5034 }
5035 PVBOXWDDM_ALLOCINFO pAllocInfo = (PVBOXWDDM_ALLOCINFO)pInfo->pPrivateDriverData;
5036
5037#ifdef VBOX_WITH_VIDEOHWACCEL
5038 if (pRcInfo->RcDesc.fFlags.Overlay)
5039 {
5040 /* we have queried host for some surface info, like pitch & size,
5041 * need to return it back to the UMD (User Mode Drive) */
5042 pAllocInfo->SurfDesc = pAllocation->SurfDesc;
5043 /* success, just continue */
5044 }
5045#endif
5046 }
5047
5048 KIRQL OldIrql;
5049 PVBOXWDDM_OPENALLOCATION pOa;
5050 KeAcquireSpinLock(&pAllocation->OpenLock, &OldIrql);
5051 pOa = VBoxWddmOaSearchLocked(pDevice, pAllocation);
5052 if (pOa)
5053 {
5054 ++pOa->cOpens;
5055 ++pAllocation->cOpens;
5056 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
5057 }
5058 else
5059 {
5060 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
5061 pOa = (PVBOXWDDM_OPENALLOCATION)vboxWddmMemAllocZero(sizeof (VBOXWDDM_OPENALLOCATION));
5062 if (!pOa)
5063 {
5064 WARN(("failed to allocation alloc info"));
5065 Status = STATUS_INSUFFICIENT_RESOURCES;
5066 break;
5067 }
5068
5069 pOa->hAllocation = pInfo->hAllocation;
5070 pOa->pAllocation = pAllocation;
5071 pOa->pDevice = pDevice;
5072 pOa->cOpens = 1;
5073
5074 PVBOXWDDM_OPENALLOCATION pConcurrentOa;
5075 KeAcquireSpinLock(&pAllocation->OpenLock, &OldIrql);
5076 pConcurrentOa = VBoxWddmOaSearchLocked(pDevice, pAllocation);
5077 if (!pConcurrentOa)
5078 InsertHeadList(&pAllocation->OpenList, &pOa->ListEntry);
5079 else
5080 ++pConcurrentOa->cOpens;
5081 ++pAllocation->cOpens;
5082 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
5083 if (pConcurrentOa)
5084 {
5085 vboxWddmMemFree(pOa);
5086 pOa = pConcurrentOa;
5087 }
5088 }
5089
5090 pInfo->hDeviceSpecificAllocation = pOa;
5091 }
5092
5093 if (Status != STATUS_SUCCESS)
5094 {
5095 for (UINT j = 0; j < i; ++j)
5096 {
5097 DXGK_OPENALLOCATIONINFO* pInfo2Free = &pOpenAllocation->pOpenAllocation[j];
5098 PVBOXWDDM_OPENALLOCATION pOa2Free = (PVBOXWDDM_OPENALLOCATION)pInfo2Free->hDeviceSpecificAllocation;
5099 VBoxWddmOaRelease(pOa2Free);
5100 }
5101 }
5102 }
5103 LOGF(("LEAVE, hDevice(0x%x)", hDevice));
5104
5105 return Status;
5106}
5107
5108NTSTATUS
5109APIENTRY
5110DxgkDdiCloseAllocation(
5111 CONST HANDLE hDevice,
5112 CONST DXGKARG_CLOSEALLOCATION* pCloseAllocation)
5113{
5114 /* DxgkDdiCloseAllocation should be made pageable. */
5115 PAGED_CODE();
5116
5117 LOGF(("ENTER, hDevice(0x%x)", hDevice));
5118
5119 vboxVDbgBreakFv();
5120
5121 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)hDevice;
5122 PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
5123
5124 for (UINT i = 0; i < pCloseAllocation->NumAllocations; ++i)
5125 {
5126 PVBOXWDDM_OPENALLOCATION pOa2Free = (PVBOXWDDM_OPENALLOCATION)pCloseAllocation->pOpenHandleList[i];
5127 PVBOXWDDM_ALLOCATION pAllocation = pOa2Free->pAllocation;
5128 Assert(pAllocation->cShRcRefs >= pOa2Free->cShRcRefs);
5129 pAllocation->cShRcRefs -= pOa2Free->cShRcRefs;
5130 VBoxWddmOaRelease(pOa2Free);
5131 }
5132
5133 LOGF(("LEAVE, hDevice(0x%x)", hDevice));
5134
5135 return STATUS_SUCCESS;
5136}
5137
5138NTSTATUS
5139APIENTRY
5140DxgkDdiRender(
5141 CONST HANDLE hContext,
5142 DXGKARG_RENDER *pRender)
5143{
5144// LOGF(("ENTER, hContext(0x%x)", hContext));
5145
5146 Assert(pRender->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR));
5147 if (pRender->DmaBufferPrivateDataSize < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
5148 {
5149 LOGREL(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_BASEHDR (%d)",
5150 pRender->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
5151 /* @todo: can this actually happen? what status to return? */
5152 return STATUS_INVALID_PARAMETER;
5153 }
5154 if (pRender->CommandLength < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
5155 {
5156 Assert(0);
5157 LOGREL(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_BASEHDR (%d)",
5158 pRender->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
5159 /* @todo: can this actually happen? what status to return? */
5160 return STATUS_INVALID_PARAMETER;
5161 }
5162
5163 PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR pInputHdr = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)pRender->pCommand;
5164 NTSTATUS Status = STATUS_SUCCESS;
5165 switch (pInputHdr->enmCmd)
5166 {
5167 case VBOXVDMACMD_TYPE_CHROMIUM_CMD:
5168 {
5169 if (pRender->CommandLength != RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD, aBufInfos[pInputHdr->u32CmdReserved]))
5170 {
5171 Assert(0);
5172 return STATUS_INVALID_PARAMETER;
5173 }
5174 PVBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD pUmCmd = (PVBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD)pInputHdr;
5175 PVBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD pChromiumCmd = (PVBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD)pRender->pDmaBufferPrivateData;
5176 const uint32_t cbDma = RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD, aBufInfos[pInputHdr->u32CmdReserved]);
5177 if (pRender->DmaBufferPrivateDataSize < cbDma)
5178 {
5179 Assert(0);
5180 return STATUS_INVALID_PARAMETER;
5181 }
5182 if (pRender->DmaSize < cbDma)
5183 {
5184 Assert(0);
5185 return STATUS_INVALID_PARAMETER;
5186 }
5187
5188 if (pRender->PatchLocationListOutSize < pInputHdr->u32CmdReserved)
5189 {
5190 Assert(0);
5191 return STATUS_INVALID_PARAMETER;
5192 }
5193
5194 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
5195 PVBOXWDDM_DEVICE pDevice = pContext->pDevice;
5196 PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
5197
5198 pChromiumCmd->Base.enmCmd = VBOXVDMACMD_TYPE_CHROMIUM_CMD;
5199 pChromiumCmd->Base.u32CmdReserved = pInputHdr->u32CmdReserved;
5200 pRender->pDmaBufferPrivateData = (uint8_t*)pRender->pDmaBufferPrivateData + cbDma;
5201 pRender->pDmaBuffer = ((uint8_t*)pRender->pDmaBuffer) + cbDma;
5202 D3DDDI_PATCHLOCATIONLIST* pPLL = pRender->pPatchLocationListOut;
5203 memset(pPLL, 0, sizeof (*pPLL) * pChromiumCmd->Base.u32CmdReserved);
5204 pRender->pPatchLocationListOut += pInputHdr->u32CmdReserved;
5205 PVBOXWDDM_UHGSMI_BUFFER_SUBMIT_INFO pSubmInfo = pChromiumCmd->aBufInfos;
5206 PVBOXWDDM_UHGSMI_BUFFER_UI_SUBMIT_INFO pSubmUmInfo = pUmCmd->aBufInfos;
5207 DXGK_ALLOCATIONLIST *pAllocationList = pRender->pAllocationList;
5208 for (UINT i = 0; i < pChromiumCmd->Base.u32CmdReserved; ++i)
5209 {
5210 PVBOXWDDM_ALLOCATION pAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pAllocationList);
5211 vboxWddmPopulateDmaAllocInfoWithOffset(&pSubmInfo->Alloc, pAlloc, pAllocationList, pSubmUmInfo->offData);
5212
5213 pSubmInfo->cbData = pSubmUmInfo->cbData;
5214 pSubmInfo->bDoNotSignalCompletion = pSubmUmInfo->bDoNotSignalCompletion;
5215
5216 pPLL->AllocationIndex = i;
5217 pPLL->PatchOffset = RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_CHROMIUM_CMD, aBufInfos[i].Alloc);
5218 pPLL->AllocationOffset = pSubmUmInfo->offData;
5219
5220 ++pPLL;
5221 ++pSubmInfo;
5222 ++pSubmUmInfo;
5223 ++pAllocationList;
5224 }
5225
5226 break;
5227 }
5228 case VBOXVDMACMD_TYPE_DMA_NOP:
5229 {
5230 PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR pPrivateData = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)pRender->pDmaBufferPrivateData;
5231 pPrivateData->enmCmd = VBOXVDMACMD_TYPE_DMA_NOP;
5232
5233 pRender->pDmaBufferPrivateData = (uint8_t*)pRender->pDmaBufferPrivateData + sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR);
5234 pRender->pDmaBuffer = ((uint8_t*)pRender->pDmaBuffer) + pRender->CommandLength;
5235 Assert(pRender->DmaSize >= pRender->CommandLength);
5236 Assert(pRender->PatchLocationListOutSize >= pRender->PatchLocationListInSize);
5237 UINT cbPLL = pRender->PatchLocationListInSize * sizeof (pRender->pPatchLocationListOut[0]);
5238 memcpy(pRender->pPatchLocationListOut, pRender->pPatchLocationListIn, cbPLL);
5239 pRender->pPatchLocationListOut += pRender->PatchLocationListInSize;
5240 break;
5241 }
5242 default:
5243 return STATUS_INVALID_PARAMETER;
5244 }
5245
5246// LOGF(("LEAVE, hContext(0x%x)", hContext));
5247
5248 return Status;
5249}
5250
5251#define VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE() (VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_PRESENT_BLT))
5252#define VBOXVDMACMD_DMA_PRESENT_BLT_SIZE(_c) (VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects[_c]))
5253
5254#ifdef VBOX_WITH_VDMA
5255DECLINLINE(VOID) vboxWddmRectlFromRect(const RECT *pRect, PVBOXVDMA_RECTL pRectl)
5256{
5257 pRectl->left = (int16_t)pRect->left;
5258 pRectl->width = (uint16_t)(pRect->right - pRect->left);
5259 pRectl->top = (int16_t)pRect->top;
5260 pRectl->height = (uint16_t)(pRect->bottom - pRect->top);
5261}
5262
5263DECLINLINE(VBOXVDMA_PIXEL_FORMAT) vboxWddmFromPixFormat(D3DDDIFORMAT format)
5264{
5265 return (VBOXVDMA_PIXEL_FORMAT)format;
5266}
5267
5268DECLINLINE(VOID) vboxWddmSurfDescFromAllocation(PVBOXWDDM_ALLOCATION pAllocation, PVBOXVDMA_SURF_DESC pDesc)
5269{
5270 pDesc->width = pAllocation->SurfDesc.width;
5271 pDesc->height = pAllocation->SurfDesc.height;
5272 pDesc->format = vboxWddmFromPixFormat(pAllocation->SurfDesc.format);
5273 pDesc->bpp = pAllocation->SurfDesc.bpp;
5274 pDesc->pitch = pAllocation->SurfDesc.pitch;
5275 pDesc->fFlags = 0;
5276}
5277#endif
5278
5279DECLINLINE(BOOLEAN) vboxWddmPixFormatConversionSupported(D3DDDIFORMAT From, D3DDDIFORMAT To)
5280{
5281 Assert(From != D3DDDIFMT_UNKNOWN);
5282 Assert(To != D3DDDIFMT_UNKNOWN);
5283 Assert(From == To);
5284 return From == To;
5285}
5286
5287/**
5288 * DxgkDdiPresent
5289 */
5290NTSTATUS
5291APIENTRY
5292DxgkDdiPresent(
5293 CONST HANDLE hContext,
5294 DXGKARG_PRESENT *pPresent)
5295{
5296 PAGED_CODE();
5297
5298// LOGF(("ENTER, hContext(0x%x)", hContext));
5299
5300 vboxVDbgBreakFv();
5301
5302 NTSTATUS Status = STATUS_SUCCESS;
5303 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
5304 PVBOXWDDM_DEVICE pDevice = pContext->pDevice;
5305 PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
5306
5307 Assert(pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR));
5308 if (pPresent->DmaBufferPrivateDataSize < sizeof (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR))
5309 {
5310 LOGREL(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR (%d)", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR)));
5311 /* @todo: can this actually happen? what status tu return? */
5312 return STATUS_INVALID_PARAMETER;
5313 }
5314
5315 PVBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR pPrivateData = (PVBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR)pPresent->pDmaBufferPrivateData;
5316 pPrivateData->BaseHdr.fFlags.Value = 0;
5317 uint32_t cContexts3D = ASMAtomicReadU32(&pDevExt->cContexts3D);
5318 uint32_t cContexts2D = ASMAtomicReadU32(&pDevExt->cContexts2D);
5319#define VBOXWDDM_DUMMY_DMABUFFER_SIZE sizeof(RECT)
5320
5321 if (pPresent->Flags.Blt)
5322 {
5323 Assert(pPresent->Flags.Value == 1); /* only Blt is set, we do not support anything else for now */
5324 DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
5325 DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
5326 PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pSrc);
5327 Assert(pSrcAlloc);
5328 if (pSrcAlloc)
5329 {
5330 PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pDst);
5331 Assert(pDstAlloc);
5332 if (pDstAlloc)
5333 {
5334 do
5335 {
5336#ifdef VBOXWDDM_RENDER_FROM_SHADOW
5337#if 0
5338 Assert (pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE);
5339 Assert (pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE);
5340#else
5341 if (pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM)
5342 {
5343 Assert ((pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE
5344 && pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE)
5345 || (pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
5346 && pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE));
5347 }
5348#endif
5349 /* issue VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE ONLY in case there are no 3D contexts currently
5350 * otherwise we would need info about all rects being updated on primary for visible rect reporting */
5351 if (!cContexts3D && !cContexts2D)
5352 {
5353 if (pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
5354 && pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE)
5355 {
5356 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_SYSTEM);
5357 Assert(pDstAlloc->bAssigned);
5358 Assert(pDstAlloc->bVisible);
5359 if (pDstAlloc->bAssigned
5360 && pDstAlloc->bVisible)
5361 {
5362#ifdef VBOX_WITH_VIDEOHWACCEL
5363// if (vboxVhwaHlpOverlayListIsEmpty(pDevExt, pDstAlloc->SurfDesc.VidPnSourceId))
5364#endif
5365 {
5366 Assert(pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY));
5367 if (pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY))
5368 {
5369 Assert(pPresent->SrcRect.left == pPresent->DstRect.left);
5370 Assert(pPresent->SrcRect.right == pPresent->DstRect.right);
5371 Assert(pPresent->SrcRect.top == pPresent->DstRect.top);
5372 Assert(pPresent->SrcRect.bottom == pPresent->DstRect.bottom);
5373 RECT rect;
5374 if (pPresent->SubRectCnt)
5375 {
5376 rect = pPresent->pDstSubRects[0];
5377 for (UINT i = 1; i < pPresent->SubRectCnt; ++i)
5378 {
5379 vboxWddmRectUnited(&rect, &rect, &pPresent->pDstSubRects[i]);
5380 }
5381 }
5382 else
5383 rect = pPresent->SrcRect;
5384
5385
5386 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof (VBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY);
5387 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
5388 Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
5389 memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
5390 pPresent->pPatchLocationListOut->PatchOffset = 0;
5391 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
5392 ++pPresent->pPatchLocationListOut;
5393 pPresent->pPatchLocationListOut->PatchOffset = 4;
5394 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
5395 ++pPresent->pPatchLocationListOut;
5396
5397 pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_SHADOW2PRIMARY;
5398 PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY pS2P = (PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY)pPrivateData;
5399 /* we do not know the shadow address yet, perform dummy DMA cycle */
5400 vboxWddmPopulateDmaAllocInfo(&pS2P->Shadow2Primary.ShadowAlloc, pSrcAlloc, pSrc);
5401// vboxWddmPopulateDmaAllocInfo(&pPrivateData->DstAllocInfo, pDstAlloc, pDst);
5402 pS2P->Shadow2Primary.SrcRect = rect;
5403 pS2P->Shadow2Primary.VidPnSourceId = pDstAlloc->SurfDesc.VidPnSourceId;
5404 break;
5405 }
5406 else
5407 {
5408 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
5409 break;
5410 }
5411 }
5412 }
5413 }
5414 }
5415
5416 /* we're here because this is NOT a shadow->primary update
5417 * or because there are d3d contexts and we need to report visible rects
5418 * or because we have overlays active and we need a special handling for primary */
5419#endif
5420 UINT cbCmd = pPresent->DmaBufferPrivateDataSize;
5421 pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
5422
5423 PVBOXWDDM_DMA_PRIVATEDATA_BLT pBlt = (PVBOXWDDM_DMA_PRIVATEDATA_BLT)pPrivateData;
5424
5425 vboxWddmPopulateDmaAllocInfo(&pBlt->Blt.SrcAlloc, pSrcAlloc, pSrc);
5426 vboxWddmPopulateDmaAllocInfo(&pBlt->Blt.DstAlloc, pDstAlloc, pDst);
5427
5428 ASSERT_WARN(!pSrcAlloc->fRcFlags.SharedResource, ("Shared Allocatoin used in Present!"));
5429
5430 pBlt->Blt.SrcRect = pPresent->SrcRect;
5431 pBlt->Blt.DstRects.ContextRect = pPresent->DstRect;
5432 pBlt->Blt.DstRects.UpdateRects.cRects = 0;
5433 UINT cbHead = RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_BLT, Blt.DstRects.UpdateRects.aRects[0]);
5434 Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
5435 UINT cbRects = (pPresent->SubRectCnt - pPresent->MultipassOffset) * sizeof (RECT);
5436 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbHead + cbRects;
5437 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
5438 Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
5439 cbCmd -= cbHead;
5440 Assert(cbCmd < UINT32_MAX/2);
5441 Assert(cbCmd > sizeof (RECT));
5442 if (cbCmd >= cbRects)
5443 {
5444 cbCmd -= cbRects;
5445 memcpy(&pBlt->Blt.DstRects.UpdateRects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbRects);
5446 pBlt->Blt.DstRects.UpdateRects.cRects += cbRects/sizeof (RECT);
5447 }
5448 else
5449 {
5450 UINT cbFitingRects = (cbCmd/sizeof (RECT)) * sizeof (RECT);
5451 Assert(cbFitingRects);
5452 memcpy(&pBlt->Blt.DstRects.UpdateRects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbFitingRects);
5453 cbCmd -= cbFitingRects;
5454 pPresent->MultipassOffset += cbFitingRects/sizeof (RECT);
5455 pBlt->Blt.DstRects.UpdateRects.cRects += cbFitingRects/sizeof (RECT);
5456 Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
5457 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
5458 }
5459
5460 memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
5461 pPresent->pPatchLocationListOut->PatchOffset = 0;
5462 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
5463 ++pPresent->pPatchLocationListOut;
5464 pPresent->pPatchLocationListOut->PatchOffset = 4;
5465 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
5466 ++pPresent->pPatchLocationListOut;
5467
5468 break;
5469#ifdef VBOX_WITH_VDMA
5470 cbCmd = pPresent->DmaSize;
5471
5472 Assert(pPresent->SubRectCnt);
5473 UINT cmdSize = VBOXVDMACMD_DMA_PRESENT_BLT_SIZE(pPresent->SubRectCnt - pPresent->MultipassOffset);
5474 PVBOXVDMACMD pCmd = (PVBOXVDMACMD)pPresent->pDmaBuffer;
5475 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + cmdSize;
5476 Assert(cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE());
5477 if (cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE())
5478 {
5479 if (vboxWddmPixFormatConversionSupported(pSrcAlloc->SurfDesc.format, pDstAlloc->SurfDesc.format))
5480 {
5481 memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
5482 // pPresent->pPatchLocationListOut->PatchOffset = 0;
5483 // ++pPresent->pPatchLocationListOut;
5484 pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offSrc);
5485 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
5486 ++pPresent->pPatchLocationListOut;
5487 pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offDst);
5488 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
5489 ++pPresent->pPatchLocationListOut;
5490
5491 pCmd->enmType = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
5492 pCmd->u32CmdSpecific = 0;
5493 PVBOXVDMACMD_DMA_PRESENT_BLT pTransfer = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_PRESENT_BLT);
5494 pTransfer->offSrc = (VBOXVIDEOOFFSET)pSrc->PhysicalAddress.QuadPart;
5495 pTransfer->offDst = (VBOXVIDEOOFFSET)pDst->PhysicalAddress.QuadPart;
5496 vboxWddmSurfDescFromAllocation(pSrcAlloc, &pTransfer->srcDesc);
5497 vboxWddmSurfDescFromAllocation(pDstAlloc, &pTransfer->dstDesc);
5498 vboxWddmRectlFromRect(&pPresent->SrcRect, &pTransfer->srcRectl);
5499 vboxWddmRectlFromRect(&pPresent->DstRect, &pTransfer->dstRectl);
5500 UINT i = 0;
5501 cbCmd -= VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects);
5502 Assert(cbCmd >= sizeof (VBOXVDMA_RECTL));
5503 Assert(cbCmd < pPresent->DmaSize);
5504 for (; i < pPresent->SubRectCnt; ++i)
5505 {
5506 if (cbCmd < sizeof (VBOXVDMA_RECTL))
5507 {
5508 Assert(i);
5509 pPresent->MultipassOffset += i;
5510 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
5511 break;
5512 }
5513 vboxWddmRectlFromRect(&pPresent->pDstSubRects[i + pPresent->MultipassOffset], &pTransfer->aDstSubRects[i]);
5514 cbCmd -= sizeof (VBOXVDMA_RECTL);
5515 }
5516 Assert(i);
5517 pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
5518 pTransfer->cDstSubRects = i;
5519 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof(VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR);
5520 }
5521 else
5522 {
5523 AssertBreakpoint();
5524 LOGREL(("unsupported format conversion from(%d) to (%d)",pSrcAlloc->SurfDesc.format, pDstAlloc->SurfDesc.format));
5525 Status = STATUS_GRAPHICS_CANNOTCOLORCONVERT;
5526 }
5527 }
5528 else
5529 {
5530 /* this should not happen actually */
5531 LOGREL(("cbCmd too small!! (%d)", cbCmd));
5532 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
5533 }
5534#endif
5535 } while(0);
5536 }
5537 else
5538 {
5539 /* this should not happen actually */
5540 LOGREL(("failed to get Dst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
5541 Status = STATUS_INVALID_HANDLE;
5542 }
5543 }
5544 else
5545 {
5546 /* this should not happen actually */
5547 LOGREL(("failed to get Src Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
5548 Status = STATUS_INVALID_HANDLE;
5549 }
5550#if 0
5551 UINT cbCmd = pPresent->DmaSize;
5552
5553 Assert(pPresent->SubRectCnt);
5554 UINT cmdSize = VBOXVDMACMD_DMA_PRESENT_BLT_SIZE(pPresent->SubRectCnt - pPresent->MultipassOffset);
5555 PVBOXVDMACMD pCmd = (PVBOXVDMACMD)pPresent->pDmaBuffer;
5556 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + cmdSize;
5557 Assert(cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE());
5558 if (cbCmd >= VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE())
5559 {
5560 DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
5561 DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
5562 PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pSrc);
5563 Assert(pSrcAlloc);
5564 if (pSrcAlloc)
5565 {
5566 PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pDst);
5567 Assert(pDstAlloc);
5568 if (pDstAlloc)
5569 {
5570 if (vboxWddmPixFormatConversionSupported(pSrcAlloc->SurfDesc.format, pDstAlloc->SurfDesc.format))
5571 {
5572 memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
5573// pPresent->pPatchLocationListOut->PatchOffset = 0;
5574// ++pPresent->pPatchLocationListOut;
5575 pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offSrc);
5576 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
5577 ++pPresent->pPatchLocationListOut;
5578 pPresent->pPatchLocationListOut->PatchOffset = VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, offDst);
5579 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
5580 ++pPresent->pPatchLocationListOut;
5581
5582 pCmd->enmType = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
5583 pCmd->u32CmdSpecific = 0;
5584 PVBOXVDMACMD_DMA_PRESENT_BLT pTransfer = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_PRESENT_BLT);
5585 pTransfer->offSrc = (VBOXVIDEOOFFSET)pSrc->PhysicalAddress.QuadPart;
5586 pTransfer->offDst = (VBOXVIDEOOFFSET)pDst->PhysicalAddress.QuadPart;
5587 vboxWddmSurfDescFromAllocation(pSrcAlloc, &pTransfer->srcDesc);
5588 vboxWddmSurfDescFromAllocation(pDstAlloc, &pTransfer->dstDesc);
5589 vboxWddmRectlFromRect(&pPresent->SrcRect, &pTransfer->srcRectl);
5590 vboxWddmRectlFromRect(&pPresent->DstRect, &pTransfer->dstRectl);
5591 UINT i = 0;
5592 cbCmd -= VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects);
5593 Assert(cbCmd >= sizeof (VBOXVDMA_RECTL));
5594 Assert(cbCmd < pPresent->DmaSize);
5595 for (; i < pPresent->SubRectCnt; ++i)
5596 {
5597 if (cbCmd < sizeof (VBOXVDMA_RECTL))
5598 {
5599 Assert(i);
5600 pPresent->MultipassOffset += i;
5601 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
5602 break;
5603 }
5604 vboxWddmRectlFromRect(&pPresent->pDstSubRects[i + pPresent->MultipassOffset], &pTransfer->aDstSubRects[i]);
5605 cbCmd -= sizeof (VBOXVDMA_RECTL);
5606 }
5607 Assert(i);
5608 pTransfer->cDstSubRects = i;
5609 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + sizeof(VBOXWDDM_DMA_PRIVATEDATA_HDR);
5610 }
5611 else
5612 {
5613 AssertBreakpoint();
5614 LOGREL(("unsupported format conversion from(%d) to (%d)",pSrcAlloc->SurfDesc.format, pDstAlloc->SurfDesc.format));
5615 Status = STATUS_GRAPHICS_CANNOTCOLORCONVERT;
5616 }
5617 }
5618 else
5619 {
5620 /* this should not happen actually */
5621 LOGREL(("failed to get Dst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
5622 Status = STATUS_INVALID_HANDLE;
5623 }
5624 }
5625 else
5626 {
5627 /* this should not happen actually */
5628 LOGREL(("failed to get Src Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
5629 Status = STATUS_INVALID_HANDLE;
5630 }
5631 }
5632 else
5633 {
5634 /* this should not happen actually */
5635 LOGREL(("cbCmd too small!! (%d)", cbCmd));
5636 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
5637 }
5638#endif
5639 }
5640 else if (pPresent->Flags.Flip)
5641 {
5642 Assert(pPresent->Flags.Value == 4); /* only Blt is set, we do not support anything else for now */
5643 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D);
5644 DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
5645 PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pSrc);
5646 Assert(pSrcAlloc);
5647 if (pSrcAlloc)
5648 {
5649 Assert(cContexts3D);
5650 pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP;
5651 PVBOXWDDM_DMA_PRIVATEDATA_FLIP pFlip = (PVBOXWDDM_DMA_PRIVATEDATA_FLIP)pPrivateData;
5652
5653 vboxWddmPopulateDmaAllocInfo(&pFlip->Flip.Alloc, pSrcAlloc, pSrc);
5654
5655 UINT cbCmd = sizeof (VBOXWDDM_DMA_PRIVATEDATA_FLIP);
5656 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbCmd;
5657 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
5658 Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
5659
5660 memset(pPresent->pPatchLocationListOut, 0, sizeof (D3DDDI_PATCHLOCATIONLIST));
5661 pPresent->pPatchLocationListOut->PatchOffset = 0;
5662 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
5663 ++pPresent->pPatchLocationListOut;
5664 }
5665 else
5666 {
5667 /* this should not happen actually */
5668 LOGREL(("failed to get pSrc Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
5669 Status = STATUS_INVALID_HANDLE;
5670 }
5671 }
5672 else if (pPresent->Flags.ColorFill)
5673 {
5674 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D);
5675 Assert(pPresent->Flags.Value == 2); /* only ColorFill is set, we do not support anything else for now */
5676 DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
5677 PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pDst);
5678 Assert(pDstAlloc);
5679 if (pDstAlloc)
5680 {
5681 UINT cbCmd = pPresent->DmaBufferPrivateDataSize;
5682 pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL;
5683 PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL pCF = (PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL)pPrivateData;
5684
5685 vboxWddmPopulateDmaAllocInfo(&pCF->ClrFill.Alloc, pDstAlloc, pDst);
5686
5687 pCF->ClrFill.Color = pPresent->Color;
5688 pCF->ClrFill.Rects.cRects = 0;
5689 UINT cbHead = RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_CLRFILL, ClrFill.Rects.aRects[0]);
5690 Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
5691 UINT cbRects = (pPresent->SubRectCnt - pPresent->MultipassOffset) * sizeof (RECT);
5692 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbHead + cbRects;
5693 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
5694 Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
5695 cbCmd -= cbHead;
5696 Assert(cbCmd < UINT32_MAX/2);
5697 Assert(cbCmd > sizeof (RECT));
5698 if (cbCmd >= cbRects)
5699 {
5700 cbCmd -= cbRects;
5701 memcpy(&pCF->ClrFill.Rects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbRects);
5702 pCF->ClrFill.Rects.cRects += cbRects/sizeof (RECT);
5703 }
5704 else
5705 {
5706 UINT cbFitingRects = (cbCmd/sizeof (RECT)) * sizeof (RECT);
5707 Assert(cbFitingRects);
5708 memcpy(&pCF->ClrFill.Rects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbFitingRects);
5709 cbCmd -= cbFitingRects;
5710 pPresent->MultipassOffset += cbFitingRects/sizeof (RECT);
5711 pCF->ClrFill.Rects.cRects += cbFitingRects/sizeof (RECT);
5712 Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
5713 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
5714 }
5715
5716 memset(pPresent->pPatchLocationListOut, 0, sizeof (D3DDDI_PATCHLOCATIONLIST));
5717 pPresent->pPatchLocationListOut->PatchOffset = 0;
5718 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
5719 ++pPresent->pPatchLocationListOut;
5720 }
5721 else
5722 {
5723 /* this should not happen actually */
5724 LOGREL(("failed to get pDst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
5725 Status = STATUS_INVALID_HANDLE;
5726 }
5727
5728 }
5729 else
5730 {
5731 LOGREL(("cmd NOT IMPLEMENTED!! Flags(0x%x)", pPresent->Flags.Value));
5732 AssertBreakpoint();
5733 }
5734
5735// LOGF(("LEAVE, hContext(0x%x), Status(0x%x)", hContext, Status));
5736
5737 return Status;
5738}
5739
5740NTSTATUS
5741APIENTRY
5742DxgkDdiUpdateOverlay(
5743 CONST HANDLE hOverlay,
5744 CONST DXGKARG_UPDATEOVERLAY *pUpdateOverlay)
5745{
5746 LOGF(("ENTER, hOverlay(0x%p)", hOverlay));
5747
5748 NTSTATUS Status = STATUS_SUCCESS;
5749 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)hOverlay;
5750 Assert(pOverlay);
5751 int rc = vboxVhwaHlpOverlayUpdate(pOverlay, &pUpdateOverlay->OverlayInfo);
5752 AssertRC(rc);
5753 if (RT_SUCCESS(rc))
5754 {
5755 RECT DstRect;
5756 vboxVhwaHlpOverlayDstRectGet(pOverlay->pDevExt, pOverlay, &DstRect);
5757 Status = vboxVdmaHlpUpdatePrimary(pOverlay->pDevExt, pOverlay->VidPnSourceId, &DstRect);
5758 Assert(Status == STATUS_SUCCESS);
5759 }
5760 else
5761 Status = STATUS_UNSUCCESSFUL;
5762
5763 LOGF(("LEAVE, hOverlay(0x%p)", hOverlay));
5764
5765 return Status;
5766}
5767
5768NTSTATUS
5769APIENTRY
5770DxgkDdiFlipOverlay(
5771 CONST HANDLE hOverlay,
5772 CONST DXGKARG_FLIPOVERLAY *pFlipOverlay)
5773{
5774 LOGF(("ENTER, hOverlay(0x%p)", hOverlay));
5775
5776 NTSTATUS Status = STATUS_SUCCESS;
5777 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)hOverlay;
5778 Assert(pOverlay);
5779 int rc = vboxVhwaHlpOverlayFlip(pOverlay, pFlipOverlay);
5780 AssertRC(rc);
5781 if (RT_FAILURE(rc))
5782 Status = STATUS_UNSUCCESSFUL;
5783
5784 LOGF(("LEAVE, hOverlay(0x%p)", hOverlay));
5785
5786 return Status;
5787}
5788
5789NTSTATUS
5790APIENTRY
5791DxgkDdiDestroyOverlay(
5792 CONST HANDLE hOverlay)
5793{
5794 LOGF(("ENTER, hOverlay(0x%p)", hOverlay));
5795
5796 NTSTATUS Status = STATUS_SUCCESS;
5797 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)hOverlay;
5798 Assert(pOverlay);
5799 int rc = vboxVhwaHlpOverlayDestroy(pOverlay);
5800 AssertRC(rc);
5801 if (RT_SUCCESS(rc))
5802 vboxWddmMemFree(pOverlay);
5803 else
5804 Status = STATUS_UNSUCCESSFUL;
5805
5806 LOGF(("LEAVE, hOverlay(0x%p)", hOverlay));
5807
5808 return Status;
5809}
5810
5811/**
5812 * DxgkDdiCreateContext
5813 */
5814NTSTATUS
5815APIENTRY
5816DxgkDdiCreateContext(
5817 CONST HANDLE hDevice,
5818 DXGKARG_CREATECONTEXT *pCreateContext)
5819{
5820 /* DxgkDdiCreateContext should be made pageable */
5821 PAGED_CODE();
5822
5823 LOGF(("ENTER, hDevice(0x%x)", hDevice));
5824
5825 vboxVDbgBreakFv();
5826
5827 if (pCreateContext->NodeOrdinal >= VBOXWDDM_NUM_NODES)
5828 {
5829 WARN(("Invalid NodeOrdinal (%d), expected to be less that (%d)\n", pCreateContext->NodeOrdinal, VBOXWDDM_NUM_NODES));
5830 return STATUS_INVALID_PARAMETER;
5831 }
5832
5833 NTSTATUS Status = STATUS_SUCCESS;
5834 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)hDevice;
5835 PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
5836 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)vboxWddmMemAllocZero(sizeof (VBOXWDDM_CONTEXT));
5837 Assert(pContext);
5838 if (pContext)
5839 {
5840 pContext->pDevice = pDevice;
5841 pContext->hContext = pCreateContext->hContext;
5842 pContext->EngineAffinity = pCreateContext->EngineAffinity;
5843 pContext->NodeOrdinal = pCreateContext->NodeOrdinal;
5844 vboxVideoCmCtxInitEmpty(&pContext->CmContext);
5845 if (pCreateContext->Flags.SystemContext || pCreateContext->PrivateDriverDataSize == 0)
5846 {
5847 Assert(pCreateContext->PrivateDriverDataSize == 0);
5848 Assert(!pCreateContext->pPrivateDriverData);
5849 Assert(pCreateContext->Flags.Value <= 2); /* 2 is a GDI context in Win7 */
5850 pContext->enmType = VBOXWDDM_CONTEXT_TYPE_SYSTEM;
5851 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
5852 {
5853 pDevExt->aSources[i].offVram = VBOXVIDEOOFFSET_VOID;
5854 NTSTATUS tmpStatus= vboxWddmDisplaySettingsQueryPos(pDevExt, i, &pDevExt->aSources[i].VScreenPos);
5855 Assert(tmpStatus == STATUS_SUCCESS);
5856 }
5857 }
5858 else
5859 {
5860 Assert(pCreateContext->Flags.Value == 0);
5861 Assert(pCreateContext->PrivateDriverDataSize == sizeof (VBOXWDDM_CREATECONTEXT_INFO));
5862 Assert(pCreateContext->pPrivateDriverData);
5863 if (pCreateContext->PrivateDriverDataSize == sizeof (VBOXWDDM_CREATECONTEXT_INFO))
5864 {
5865 PVBOXWDDM_CREATECONTEXT_INFO pInfo = (PVBOXWDDM_CREATECONTEXT_INFO)pCreateContext->pPrivateDriverData;
5866 switch (pInfo->enmType)
5867 {
5868 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D:
5869 {
5870 Status = vboxVideoAMgrCtxCreate(&pDevExt->AllocMgr, &pContext->AllocContext);
5871 Assert(Status == STATUS_SUCCESS);
5872 if (Status == STATUS_SUCCESS)
5873 {
5874 Status = vboxWddmSwapchainCtxInit(pDevExt, pContext);
5875 Assert(Status == STATUS_SUCCESS);
5876 if (Status == STATUS_SUCCESS)
5877 {
5878 pContext->enmType = VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D;
5879 Status = vboxVideoCmCtxAdd(&pDevice->pAdapter->CmMgr, &pContext->CmContext, (HANDLE)pInfo->hUmEvent, pInfo->u64UmInfo);
5880 Assert(Status == STATUS_SUCCESS);
5881 if (Status == STATUS_SUCCESS)
5882 {
5883 int rc = VINF_SUCCESS;
5884 if (pInfo->crVersionMajor || pInfo->crVersionMinor)
5885 {
5886 rc = VBoxMpCrCtlConConnect(&pDevExt->CrCtlCon,
5887 pInfo->crVersionMajor, pInfo->crVersionMinor,
5888 &pContext->u32CrConClientID);
5889 if (!RT_SUCCESS(rc))
5890 {
5891 WARN(("VBoxMpCrCtlConConnect failed rc (%d)", rc));
5892 Status = STATUS_UNSUCCESSFUL;
5893 }
5894 }
5895
5896 if (RT_SUCCESS(rc))
5897 {
5898 ASMAtomicIncU32(&pDevExt->cContexts3D);
5899 break;
5900 }
5901 }
5902
5903 vboxWddmSwapchainCtxTerm(pDevExt, pContext);
5904 }
5905 vboxVideoAMgrCtxDestroy(&pContext->AllocContext);
5906 }
5907 break;
5908 }
5909 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_3D:
5910 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_GL:
5911 {
5912 pContext->enmType = pInfo->enmType;
5913 Status = vboxVideoAMgrCtxCreate(&pDevExt->AllocMgr, &pContext->AllocContext);
5914 Assert(Status == STATUS_SUCCESS);
5915 if (Status == STATUS_SUCCESS)
5916 {
5917 int rc = VINF_SUCCESS;
5918 if (pInfo->crVersionMajor || pInfo->crVersionMinor)
5919 {
5920 rc = VBoxMpCrCtlConConnect(&pDevExt->CrCtlCon,
5921 pInfo->crVersionMajor, pInfo->crVersionMinor,
5922 &pContext->u32CrConClientID);
5923 if (!RT_SUCCESS(rc))
5924 {
5925 WARN(("VBoxMpCrCtlConConnect failed rc (%d)", rc));
5926 Status = STATUS_UNSUCCESSFUL;
5927 }
5928 }
5929
5930 if (RT_SUCCESS(rc))
5931 {
5932 ASMAtomicIncU32(&pDevExt->cContexts3D);
5933 break;
5934 }
5935 vboxVideoAMgrCtxDestroy(&pContext->AllocContext);
5936 }
5937 break;
5938 }
5939 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D:
5940 {
5941 pContext->enmType = pInfo->enmType;
5942 ASMAtomicIncU32(&pDevExt->cContexts2D);
5943 break;
5944 }
5945 default:
5946 {
5947 Assert(0);
5948 Status = STATUS_INVALID_PARAMETER;
5949 break;
5950 }
5951 }
5952 }
5953 }
5954
5955 if (Status == STATUS_SUCCESS)
5956 {
5957 pCreateContext->hContext = pContext;
5958 pCreateContext->ContextInfo.DmaBufferSize = VBOXWDDM_C_DMA_BUFFER_SIZE;
5959 pCreateContext->ContextInfo.DmaBufferSegmentSet = 0;
5960 pCreateContext->ContextInfo.DmaBufferPrivateDataSize = VBOXWDDM_C_DMA_PRIVATEDATA_SIZE;
5961 pCreateContext->ContextInfo.AllocationListSize = VBOXWDDM_C_ALLOC_LIST_SIZE;
5962 pCreateContext->ContextInfo.PatchLocationListSize = VBOXWDDM_C_PATH_LOCATION_LIST_SIZE;
5963 //#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
5964 //# error port to Win7 DDI
5965 // //pCreateContext->ContextInfo.DmaBufferAllocationGroup = ???;
5966 //#endif // DXGKDDI_INTERFACE_VERSION
5967 }
5968 else
5969 vboxWddmMemFree(pContext);
5970 }
5971 else
5972 Status = STATUS_NO_MEMORY;
5973
5974 LOGF(("LEAVE, hDevice(0x%x)", hDevice));
5975
5976 return Status;
5977}
5978
5979NTSTATUS
5980APIENTRY
5981DxgkDdiDestroyContext(
5982 CONST HANDLE hContext)
5983{
5984 LOGF(("ENTER, hContext(0x%x)", hContext));
5985 vboxVDbgBreakFv();
5986 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
5987 PVBOXMP_DEVEXT pDevExt = pContext->pDevice->pAdapter;
5988 switch(pContext->enmType)
5989 {
5990 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D:
5991 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_3D:
5992 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_GL:
5993 {
5994 uint32_t cContexts = ASMAtomicDecU32(&pDevExt->cContexts3D);
5995 Assert(cContexts < UINT32_MAX/2);
5996 if (pContext->u32CrConClientID)
5997 {
5998 VBoxMpCrCtlConDisconnect(&pDevExt->CrCtlCon, pContext->u32CrConClientID);
5999 }
6000 break;
6001 }
6002 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D:
6003 {
6004 uint32_t cContexts = ASMAtomicDecU32(&pDevExt->cContexts2D);
6005 Assert(cContexts < UINT32_MAX/2);
6006 break;
6007 }
6008 default:
6009 break;
6010 }
6011
6012 vboxWddmModeRenderFromShadowDisableUnregister(pDevExt, pContext);
6013
6014 /* first terminate the swapchain, this will also ensure
6015 * all currently pending driver->user Cm commands
6016 * (i.e. visible regions commands) are completed */
6017 vboxWddmSwapchainCtxTerm(pDevExt, pContext);
6018
6019 NTSTATUS Status = vboxVideoAMgrCtxDestroy(&pContext->AllocContext);
6020 Assert(Status == STATUS_SUCCESS);
6021 if (Status == STATUS_SUCCESS)
6022 {
6023 Status = vboxVideoCmCtxRemove(&pContext->pDevice->pAdapter->CmMgr, &pContext->CmContext);
6024 Assert(Status == STATUS_SUCCESS);
6025 if (Status == STATUS_SUCCESS)
6026 {
6027 vboxWddmMemFree(pContext);
6028 }
6029 }
6030
6031 LOGF(("LEAVE, hContext(0x%x)", hContext));
6032
6033 return Status;
6034}
6035
6036NTSTATUS
6037APIENTRY
6038DxgkDdiLinkDevice(
6039 __in CONST PDEVICE_OBJECT PhysicalDeviceObject,
6040 __in CONST PVOID MiniportDeviceContext,
6041 __inout PLINKED_DEVICE LinkedDevice
6042 )
6043{
6044 LOGF(("ENTER, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
6045 vboxVDbgBreakFv();
6046 AssertBreakpoint();
6047 LOGF(("LEAVE, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
6048 return STATUS_NOT_IMPLEMENTED;
6049}
6050
6051NTSTATUS
6052APIENTRY
6053DxgkDdiSetDisplayPrivateDriverFormat(
6054 CONST HANDLE hAdapter,
6055 /*CONST*/ DXGKARG_SETDISPLAYPRIVATEDRIVERFORMAT* pSetDisplayPrivateDriverFormat
6056 )
6057{
6058 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
6059 vboxVDbgBreakFv();
6060 AssertBreakpoint();
6061 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
6062 return STATUS_SUCCESS;
6063}
6064
6065NTSTATUS APIENTRY CALLBACK DxgkDdiRestartFromTimeout(IN_CONST_HANDLE hAdapter)
6066{
6067 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
6068 vboxVDbgBreakFv();
6069 AssertBreakpoint();
6070 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
6071 return STATUS_SUCCESS;
6072}
6073
6074NTSTATUS
6075DriverEntry(
6076 IN PDRIVER_OBJECT DriverObject,
6077 IN PUNICODE_STRING RegistryPath
6078 )
6079{
6080 PAGED_CODE();
6081
6082 vboxVDbgBreakFv();
6083
6084#ifdef DEBUG_misha
6085 RTLogGroupSettings(0, "+default.e.l.f.l2.l3");
6086#endif
6087
6088 LOGREL(("Built %s %s", __DATE__, __TIME__));
6089
6090 if (! ARGUMENT_PRESENT(DriverObject) ||
6091 ! ARGUMENT_PRESENT(RegistryPath))
6092 {
6093 return STATUS_INVALID_PARAMETER;
6094 }
6095
6096 vboxWddmDrvCfgInit(RegistryPath);
6097
6098 ULONG major, minor, build;
6099 BOOLEAN checkedBuild = PsGetVersion(&major, &minor, &build, NULL);
6100 BOOLEAN f3Drequired = FALSE;
6101
6102 LOGREL(("OsVersion( %d, %d, %d )", major, minor, build));
6103
6104 NTSTATUS Status = STATUS_SUCCESS;
6105 /* Initialize VBoxGuest library, which is used for requests which go through VMMDev. */
6106 int rc = VbglInit();
6107 if (RT_SUCCESS(rc))
6108 {
6109 if (major > 6)
6110 {
6111 WARN(("Unknow win version, newer major release, assuming 3D is required"));
6112 f3Drequired = TRUE;
6113 }
6114 else if (major == 6)
6115 {
6116 if (minor > 2)
6117 {
6118 WARN(("Unknow win version, newer minor release, assuming 3D is required"));
6119 f3Drequired = TRUE;
6120 }
6121 else if (minor == 2)
6122 {
6123 LOG(("3D is required!"));
6124 f3Drequired = TRUE;
6125 }
6126 else
6127 {
6128 LOG(("3D is NOT required!"));
6129 f3Drequired = FALSE;
6130 }
6131 }
6132 else
6133 {
6134 WARN(("Unsupported OLDER win version, ignore and assume 3D is NOT required"));
6135 f3Drequired = FALSE;
6136 }
6137
6138 Status = STATUS_SUCCESS;
6139
6140 if (f3Drequired)
6141 {
6142 LOG(("3D is required, doing the 3D check.."));
6143 if (!VBoxMpCrCtlConIs3DSupported())
6144 {
6145 LOGREL(("3D is NOT supported by the host, but is required for the current guest version.."));
6146 Status = STATUS_UNSUCCESSFUL;
6147 }
6148 }
6149
6150 if (NT_SUCCESS(Status))
6151 {
6152 Status = VBoxWddmVrInit();
6153 if (NT_SUCCESS(Status))
6154 {
6155 DRIVER_INITIALIZATION_DATA DriverInitializationData = {'\0'};
6156
6157 // Fill in the DriverInitializationData structure and call DxgkInitialize()
6158 DriverInitializationData.Version = DXGKDDI_INTERFACE_VERSION;
6159
6160 DriverInitializationData.DxgkDdiAddDevice = DxgkDdiAddDevice;
6161 DriverInitializationData.DxgkDdiStartDevice = DxgkDdiStartDevice;
6162 DriverInitializationData.DxgkDdiStopDevice = DxgkDdiStopDevice;
6163 DriverInitializationData.DxgkDdiRemoveDevice = DxgkDdiRemoveDevice;
6164 DriverInitializationData.DxgkDdiDispatchIoRequest = DxgkDdiDispatchIoRequest;
6165 DriverInitializationData.DxgkDdiInterruptRoutine = DxgkDdiInterruptRoutine;
6166 DriverInitializationData.DxgkDdiDpcRoutine = DxgkDdiDpcRoutine;
6167 DriverInitializationData.DxgkDdiQueryChildRelations = DxgkDdiQueryChildRelations;
6168 DriverInitializationData.DxgkDdiQueryChildStatus = DxgkDdiQueryChildStatus;
6169 DriverInitializationData.DxgkDdiQueryDeviceDescriptor = DxgkDdiQueryDeviceDescriptor;
6170 DriverInitializationData.DxgkDdiSetPowerState = DxgkDdiSetPowerState;
6171 DriverInitializationData.DxgkDdiNotifyAcpiEvent = DxgkDdiNotifyAcpiEvent;
6172 DriverInitializationData.DxgkDdiResetDevice = DxgkDdiResetDevice;
6173 DriverInitializationData.DxgkDdiUnload = DxgkDdiUnload;
6174 DriverInitializationData.DxgkDdiQueryInterface = DxgkDdiQueryInterface;
6175 DriverInitializationData.DxgkDdiControlEtwLogging = DxgkDdiControlEtwLogging;
6176
6177 DriverInitializationData.DxgkDdiQueryAdapterInfo = DxgkDdiQueryAdapterInfo;
6178 DriverInitializationData.DxgkDdiCreateDevice = DxgkDdiCreateDevice;
6179 DriverInitializationData.DxgkDdiCreateAllocation = DxgkDdiCreateAllocation;
6180 DriverInitializationData.DxgkDdiDestroyAllocation = DxgkDdiDestroyAllocation;
6181 DriverInitializationData.DxgkDdiDescribeAllocation = DxgkDdiDescribeAllocation;
6182 DriverInitializationData.DxgkDdiGetStandardAllocationDriverData = DxgkDdiGetStandardAllocationDriverData;
6183 DriverInitializationData.DxgkDdiAcquireSwizzlingRange = DxgkDdiAcquireSwizzlingRange;
6184 DriverInitializationData.DxgkDdiReleaseSwizzlingRange = DxgkDdiReleaseSwizzlingRange;
6185 DriverInitializationData.DxgkDdiPatch = DxgkDdiPatch;
6186 DriverInitializationData.DxgkDdiSubmitCommand = DxgkDdiSubmitCommand;
6187 DriverInitializationData.DxgkDdiPreemptCommand = DxgkDdiPreemptCommand;
6188 DriverInitializationData.DxgkDdiBuildPagingBuffer = DxgkDdiBuildPagingBuffer;
6189 DriverInitializationData.DxgkDdiSetPalette = DxgkDdiSetPalette;
6190 DriverInitializationData.DxgkDdiSetPointerPosition = DxgkDdiSetPointerPosition;
6191 DriverInitializationData.DxgkDdiSetPointerShape = DxgkDdiSetPointerShape;
6192 DriverInitializationData.DxgkDdiResetFromTimeout = DxgkDdiResetFromTimeout;
6193 DriverInitializationData.DxgkDdiRestartFromTimeout = DxgkDdiRestartFromTimeout;
6194 DriverInitializationData.DxgkDdiEscape = DxgkDdiEscape;
6195 DriverInitializationData.DxgkDdiCollectDbgInfo = DxgkDdiCollectDbgInfo;
6196 DriverInitializationData.DxgkDdiQueryCurrentFence = DxgkDdiQueryCurrentFence;
6197 DriverInitializationData.DxgkDdiIsSupportedVidPn = DxgkDdiIsSupportedVidPn;
6198 DriverInitializationData.DxgkDdiRecommendFunctionalVidPn = DxgkDdiRecommendFunctionalVidPn;
6199 DriverInitializationData.DxgkDdiEnumVidPnCofuncModality = DxgkDdiEnumVidPnCofuncModality;
6200 DriverInitializationData.DxgkDdiSetVidPnSourceAddress = DxgkDdiSetVidPnSourceAddress;
6201 DriverInitializationData.DxgkDdiSetVidPnSourceVisibility = DxgkDdiSetVidPnSourceVisibility;
6202 DriverInitializationData.DxgkDdiCommitVidPn = DxgkDdiCommitVidPn;
6203 DriverInitializationData.DxgkDdiUpdateActiveVidPnPresentPath = DxgkDdiUpdateActiveVidPnPresentPath;
6204 DriverInitializationData.DxgkDdiRecommendMonitorModes = DxgkDdiRecommendMonitorModes;
6205 DriverInitializationData.DxgkDdiRecommendVidPnTopology = DxgkDdiRecommendVidPnTopology;
6206 DriverInitializationData.DxgkDdiGetScanLine = DxgkDdiGetScanLine;
6207 DriverInitializationData.DxgkDdiStopCapture = DxgkDdiStopCapture;
6208 DriverInitializationData.DxgkDdiControlInterrupt = DxgkDdiControlInterrupt;
6209 DriverInitializationData.DxgkDdiCreateOverlay = DxgkDdiCreateOverlay;
6210
6211 DriverInitializationData.DxgkDdiDestroyDevice = DxgkDdiDestroyDevice;
6212 DriverInitializationData.DxgkDdiOpenAllocation = DxgkDdiOpenAllocation;
6213 DriverInitializationData.DxgkDdiCloseAllocation = DxgkDdiCloseAllocation;
6214 DriverInitializationData.DxgkDdiRender = DxgkDdiRender;
6215 DriverInitializationData.DxgkDdiPresent = DxgkDdiPresent;
6216
6217 DriverInitializationData.DxgkDdiUpdateOverlay = DxgkDdiUpdateOverlay;
6218 DriverInitializationData.DxgkDdiFlipOverlay = DxgkDdiFlipOverlay;
6219 DriverInitializationData.DxgkDdiDestroyOverlay = DxgkDdiDestroyOverlay;
6220
6221 DriverInitializationData.DxgkDdiCreateContext = DxgkDdiCreateContext;
6222 DriverInitializationData.DxgkDdiDestroyContext = DxgkDdiDestroyContext;
6223
6224 DriverInitializationData.DxgkDdiLinkDevice = NULL; //DxgkDdiLinkDevice;
6225 DriverInitializationData.DxgkDdiSetDisplayPrivateDriverFormat = DxgkDdiSetDisplayPrivateDriverFormat;
6226 //#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
6227 //# error port to Win7 DDI
6228 // DriverInitializationData.DxgkDdiRenderKm = DxgkDdiRenderKm;
6229 // DriverInitializationData.DxgkDdiRestartFromTimeout = DxgkDdiRestartFromTimeout;
6230 // DriverInitializationData.DxgkDdiSetVidPnSourceVisibility = DxgkDdiSetVidPnSourceVisibility;
6231 // DriverInitializationData.DxgkDdiUpdateActiveVidPnPresentPath = DxgkDdiUpdateActiveVidPnPresentPath;
6232 // DriverInitializationData.DxgkDdiQueryVidPnHWCapability = DxgkDdiQueryVidPnHWCapability;
6233 //#endif
6234
6235 Status = DxgkInitialize(DriverObject,
6236 RegistryPath,
6237 &DriverInitializationData);
6238 if (NT_SUCCESS(Status))
6239 return Status;
6240 VBoxWddmVrTerm();
6241 }
6242 else
6243 WARN(("VBoxWddmVrInit failed, Status(0x%x)", Status));
6244 }
6245 else
6246 LOGREL(("Aborting the video driver load due to 3D support missing"));
6247
6248 VbglTerminate();
6249 }
6250 else
6251 {
6252 WARN(("VbglInit failed, rc(%d)", rc));
6253 Status = STATUS_UNSUCCESSFUL;
6254 }
6255
6256 AssertRelease(!NT_SUCCESS(Status));
6257
6258 PRTLOGGER pLogger = RTLogRelSetDefaultInstance(NULL);
6259 if (pLogger)
6260 {
6261 RTLogDestroy(pLogger);
6262 }
6263 pLogger = RTLogSetDefaultInstance(NULL);
6264 if (pLogger)
6265 {
6266 RTLogDestroy(pLogger);
6267 }
6268
6269 return Status;
6270}
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