VirtualBox

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

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

wddm: gdi rendering, etc. fixes

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