VirtualBox

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

Last change on this file since 50921 was 50921, checked in by vboxsync, 11 years ago

wddm/graphics/crogl: more new command submission fixes

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