VirtualBox

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

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

wddm/graphics: new command submission working for 2D, more testing needed

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

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