VirtualBox

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

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

wddm/DevVGA: complex command submission; bugfixes

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette