VirtualBox

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

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

wddm: disable driver load for win8 if 3D support is unavailable

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette