VirtualBox

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

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

wddm: win8 driver .inf file fixes, better device description, etc.

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

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