VirtualBox

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

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

wddm: better handling 2d->3d mode switch

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