VirtualBox

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

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

wddm/d-o: enable mouse cursor integration

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