VirtualBox

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

Last change on this file since 42091 was 42091, checked in by vboxsync, 12 years ago

wddm/d-o: more fixes

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