VirtualBox

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

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

Dev/VGA/crOpenGL/wddm: command thread, more command processing

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 279.3 KB
Line 
1/* $Id: VBoxMPWddm.cpp 50754 2014-03-12 17:43:09Z 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
1650 vboxVtListDetach2List(&pdc->pDevExt->CtlList, &pdc->data.CtlList);
1651#ifdef VBOX_WITH_VDMA
1652 vboxVtListDetach2List(&pdc->pDevExt->DmaCmdList, &pdc->data.DmaCmdList);
1653#endif
1654#ifdef VBOX_WITH_VIDEOHWACCEL
1655 vboxVtListDetach2List(&pdc->pDevExt->VhwaCmdList, &pdc->data.VhwaCmdList);
1656#endif
1657 vboxVdmaDdiCmdGetCompletedListIsr(pdc->pDevExt, &pdc->data.CompletedDdiCmdQueue);
1658
1659 pdc->data.bNotifyDpc = pdc->pDevExt->bNotifyDxDpc;
1660 pdc->pDevExt->bNotifyDxDpc = FALSE;
1661
1662 ASMAtomicWriteU32(&pdc->pDevExt->fCompletingCommands, 0);
1663
1664 return TRUE;
1665}
1666
1667static VOID DxgkDdiDpcRoutineNew(
1668 IN CONST PVOID MiniportDeviceContext
1669 )
1670{
1671// LOGF(("ENTER, context(0x%p)", MiniportDeviceContext));
1672
1673 vboxVDbgBreakFv();
1674
1675 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1676
1677 pDevExt->u.primary.DxgkInterface.DxgkCbNotifyDpc(pDevExt->u.primary.DxgkInterface.DeviceHandle);
1678
1679 if (ASMAtomicReadU32(&pDevExt->fCompletingCommands))
1680 {
1681 VBOXWDDM_GETDPCDATA_CONTEXT context = {0};
1682 BOOLEAN bRet;
1683
1684 context.pDevExt = pDevExt;
1685
1686 /* get DPC data at IRQL */
1687 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
1688 pDevExt->u.primary.DxgkInterface.DeviceHandle,
1689 vboxWddmGetDPCDataCallback,
1690 &context,
1691 0, /* IN ULONG MessageNumber */
1692 &bRet);
1693 Assert(Status == STATUS_SUCCESS);
1694
1695 // if (context.data.bNotifyDpc)
1696 pDevExt->u.primary.DxgkInterface.DxgkCbNotifyDpc(pDevExt->u.primary.DxgkInterface.DeviceHandle);
1697
1698 if (!vboxVtListIsEmpty(&context.data.CtlList))
1699 {
1700 int rc = VBoxSHGSMICommandPostprocessCompletion (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, &context.data.CtlList);
1701 AssertRC(rc);
1702 }
1703 #ifdef VBOX_WITH_VIDEOHWACCEL
1704 if (!vboxVtListIsEmpty(&context.data.VhwaCmdList))
1705 {
1706 vboxVhwaCompletionListProcess(pDevExt, &context.data.VhwaCmdList);
1707 }
1708 #endif
1709
1710 vboxVdmaDdiCmdHandleCompletedList(pDevExt, &context.data.CompletedDdiCmdQueue);
1711 }
1712// LOGF(("LEAVE, context(0x%p)", MiniportDeviceContext));
1713}
1714
1715
1716static VOID DxgkDdiDpcRoutineLegacy(
1717 IN CONST PVOID MiniportDeviceContext
1718 )
1719{
1720// LOGF(("ENTER, context(0x%p)", MiniportDeviceContext));
1721
1722 vboxVDbgBreakFv();
1723
1724 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1725
1726 VBOXWDDM_GETDPCDATA_CONTEXT context = {0};
1727 BOOLEAN bRet;
1728
1729 context.pDevExt = pDevExt;
1730
1731 /* get DPC data at IRQL */
1732 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
1733 pDevExt->u.primary.DxgkInterface.DeviceHandle,
1734 vboxWddmGetDPCDataCallback,
1735 &context,
1736 0, /* IN ULONG MessageNumber */
1737 &bRet);
1738 Assert(Status == STATUS_SUCCESS);
1739
1740// if (context.data.bNotifyDpc)
1741 pDevExt->u.primary.DxgkInterface.DxgkCbNotifyDpc(pDevExt->u.primary.DxgkInterface.DeviceHandle);
1742
1743 if (!vboxVtListIsEmpty(&context.data.CtlList))
1744 {
1745 int rc = VBoxSHGSMICommandPostprocessCompletion (&VBoxCommonFromDeviceExt(pDevExt)->guestCtx.heapCtx, &context.data.CtlList);
1746 AssertRC(rc);
1747 }
1748#ifdef VBOX_WITH_VDMA
1749 if (!vboxVtListIsEmpty(&context.data.DmaCmdList))
1750 {
1751 int rc = VBoxSHGSMICommandPostprocessCompletion (&pDevExt->u.primary.Vdma.CmdHeap, &context.data.DmaCmdList);
1752 AssertRC(rc);
1753 }
1754#endif
1755#ifdef VBOX_WITH_VIDEOHWACCEL
1756 if (!vboxVtListIsEmpty(&context.data.VhwaCmdList))
1757 {
1758 vboxVhwaCompletionListProcess(pDevExt, &context.data.VhwaCmdList);
1759 }
1760#endif
1761
1762 vboxVdmaDdiCmdHandleCompletedList(pDevExt, &context.data.CompletedDdiCmdQueue);
1763
1764// LOGF(("LEAVE, context(0x%p)", MiniportDeviceContext));
1765}
1766
1767NTSTATUS DxgkDdiQueryChildRelations(
1768 IN CONST PVOID MiniportDeviceContext,
1769 IN OUT PDXGK_CHILD_DESCRIPTOR ChildRelations,
1770 IN ULONG ChildRelationsSize
1771 )
1772{
1773 /* The DxgkDdiQueryChildRelations function should be made pageable. */
1774 PAGED_CODE();
1775
1776 vboxVDbgBreakFv();
1777
1778 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1779
1780 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
1781 Assert(ChildRelationsSize == (VBoxCommonFromDeviceExt(pDevExt)->cDisplays + 1)*sizeof(DXGK_CHILD_DESCRIPTOR));
1782 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
1783 {
1784 ChildRelations[i].ChildDeviceType = TypeVideoOutput;
1785 ChildRelations[i].ChildCapabilities.Type.VideoOutput.InterfaceTechnology = D3DKMDT_VOT_HD15; /* VGA */
1786 ChildRelations[i].ChildCapabilities.Type.VideoOutput.MonitorOrientationAwareness = D3DKMDT_MOA_NONE; //D3DKMDT_MOA_INTERRUPTIBLE; /* ?? D3DKMDT_MOA_NONE*/
1787 ChildRelations[i].ChildCapabilities.Type.VideoOutput.SupportsSdtvModes = FALSE;
1788 ChildRelations[i].ChildCapabilities.HpdAwareness = HpdAwarenessInterruptible; /* ?? HpdAwarenessAlwaysConnected; */
1789 ChildRelations[i].AcpiUid = 0; /* */
1790 ChildRelations[i].ChildUid = i; /* should be == target id */
1791 }
1792 LOGF(("LEAVE, context(0x%x)", MiniportDeviceContext));
1793 return STATUS_SUCCESS;
1794}
1795
1796NTSTATUS DxgkDdiQueryChildStatus(
1797 IN CONST PVOID MiniportDeviceContext,
1798 IN PDXGK_CHILD_STATUS ChildStatus,
1799 IN BOOLEAN NonDestructiveOnly
1800 )
1801{
1802 /* The DxgkDdiQueryChildStatus should be made pageable. */
1803 PAGED_CODE();
1804
1805 vboxVDbgBreakFv();
1806
1807 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
1808
1809 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)MiniportDeviceContext;
1810
1811 NTSTATUS Status = STATUS_SUCCESS;
1812 switch (ChildStatus->Type)
1813 {
1814 case StatusConnection:
1815 {
1816 LOGF(("StatusConnection"));
1817 VBOXWDDM_TARGET *pTarget = &pDevExt->aTargets[ChildStatus->ChildUid];
1818 ChildStatus->HotPlug.Connected = !!pTarget->fConnected;
1819 break;
1820 }
1821 case StatusRotation:
1822 LOGF(("StatusRotation"));
1823 ChildStatus->Rotation.Angle = 0;
1824 break;
1825 default:
1826 WARN(("ERROR: status type: %d", ChildStatus->Type));
1827 Status = STATUS_INVALID_PARAMETER;
1828 break;
1829 }
1830
1831 LOGF(("LEAVE, context(0x%x)", MiniportDeviceContext));
1832
1833 return Status;
1834}
1835
1836NTSTATUS DxgkDdiQueryDeviceDescriptor(
1837 IN CONST PVOID MiniportDeviceContext,
1838 IN ULONG ChildUid,
1839 IN OUT PDXGK_DEVICE_DESCRIPTOR DeviceDescriptor
1840 )
1841{
1842 /* The DxgkDdiQueryDeviceDescriptor should be made pageable. */
1843 PAGED_CODE();
1844
1845 vboxVDbgBreakFv();
1846
1847 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
1848
1849 LOGF(("LEAVE, context(0x%x)", MiniportDeviceContext));
1850
1851 /* we do not support EDID */
1852 return STATUS_MONITOR_NO_DESCRIPTOR;
1853}
1854
1855NTSTATUS DxgkDdiSetPowerState(
1856 IN CONST PVOID MiniportDeviceContext,
1857 IN ULONG DeviceUid,
1858 IN DEVICE_POWER_STATE DevicePowerState,
1859 IN POWER_ACTION ActionType
1860 )
1861{
1862 /* The DxgkDdiSetPowerState function should be made pageable. */
1863 PAGED_CODE();
1864
1865 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
1866
1867 vboxVDbgBreakFv();
1868
1869 LOGF(("LEAVE, context(0x%x)", MiniportDeviceContext));
1870
1871 return STATUS_SUCCESS;
1872}
1873
1874NTSTATUS DxgkDdiNotifyAcpiEvent(
1875 IN CONST PVOID MiniportDeviceContext,
1876 IN DXGK_EVENT_TYPE EventType,
1877 IN ULONG Event,
1878 IN PVOID Argument,
1879 OUT PULONG AcpiFlags
1880 )
1881{
1882 LOGF(("ENTER, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
1883
1884 vboxVDbgBreakF();
1885
1886 LOGF(("LEAVE, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
1887
1888 return STATUS_SUCCESS;
1889}
1890
1891VOID DxgkDdiResetDevice(
1892 IN CONST PVOID MiniportDeviceContext
1893 )
1894{
1895 /* DxgkDdiResetDevice can be called at any IRQL, so it must be in nonpageable memory. */
1896 vboxVDbgBreakF();
1897
1898
1899
1900 LOGF(("ENTER, context(0x%x)", MiniportDeviceContext));
1901 LOGF(("LEAVE, context(0x%x)", MiniportDeviceContext));
1902}
1903
1904VOID DxgkDdiUnload(
1905 VOID
1906 )
1907{
1908 /* DxgkDdiUnload should be made pageable. */
1909 PAGED_CODE();
1910 LOGF((": unloading"));
1911
1912 vboxVDbgBreakFv();
1913
1914 VbglTerminate();
1915
1916 VBoxVrTerm();
1917
1918 PRTLOGGER pLogger = RTLogRelSetDefaultInstance(NULL);
1919 if (pLogger)
1920 {
1921 RTLogDestroy(pLogger);
1922 }
1923 pLogger = RTLogSetDefaultInstance(NULL);
1924 if (pLogger)
1925 {
1926 RTLogDestroy(pLogger);
1927 }
1928}
1929
1930NTSTATUS DxgkDdiQueryInterface(
1931 IN CONST PVOID MiniportDeviceContext,
1932 IN PQUERY_INTERFACE QueryInterface
1933 )
1934{
1935 LOGF(("ENTER, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
1936
1937 vboxVDbgBreakFv();
1938
1939 LOGF(("LEAVE, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
1940
1941 return STATUS_NOT_SUPPORTED;
1942}
1943
1944VOID DxgkDdiControlEtwLogging(
1945 IN BOOLEAN Enable,
1946 IN ULONG Flags,
1947 IN UCHAR Level
1948 )
1949{
1950 LOGF(("ENTER"));
1951
1952 vboxVDbgBreakF();
1953
1954 LOGF(("LEAVE"));
1955}
1956
1957/**
1958 * DxgkDdiQueryAdapterInfo
1959 */
1960NTSTATUS APIENTRY DxgkDdiQueryAdapterInfo(
1961 CONST HANDLE hAdapter,
1962 CONST DXGKARG_QUERYADAPTERINFO* pQueryAdapterInfo)
1963{
1964 /* The DxgkDdiQueryAdapterInfo should be made pageable. */
1965 PAGED_CODE();
1966
1967 LOGF(("ENTER, context(0x%x), Query type (%d)", hAdapter, pQueryAdapterInfo->Type));
1968 NTSTATUS Status = STATUS_SUCCESS;
1969 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
1970
1971 vboxVDbgBreakFv();
1972
1973 switch (pQueryAdapterInfo->Type)
1974 {
1975 case DXGKQAITYPE_DRIVERCAPS:
1976 {
1977 DXGK_DRIVERCAPS *pCaps = (DXGK_DRIVERCAPS*)pQueryAdapterInfo->pOutputData;
1978
1979#ifdef VBOX_WDDM_WIN8
1980 memset(pCaps, 0, sizeof (*pCaps));
1981#endif
1982
1983 pCaps->HighestAcceptableAddress.QuadPart = ~((uintptr_t)0);
1984 pCaps->MaxPointerWidth = VBOXWDDM_C_POINTER_MAX_WIDTH;
1985 pCaps->MaxPointerHeight = VBOXWDDM_C_POINTER_MAX_HEIGHT;
1986 pCaps->PointerCaps.Value = 3; /* Monochrome , Color*/ /* MaskedColor == Value | 4, disable for now */
1987#ifdef VBOX_WDDM_WIN8
1988 if (!g_VBoxDisplayOnly)
1989#endif
1990 {
1991 pCaps->MaxAllocationListSlotId = 16;
1992 pCaps->ApertureSegmentCommitLimit = 0;
1993 pCaps->InterruptMessageNumber = 0;
1994 pCaps->NumberOfSwizzlingRanges = 0;
1995 pCaps->MaxOverlays = 0;
1996#ifdef VBOX_WITH_VIDEOHWACCEL
1997 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
1998 {
1999 if ( pDevExt->aSources[i].Vhwa.Settings.fFlags & VBOXVHWA_F_ENABLED)
2000 pCaps->MaxOverlays += pDevExt->aSources[i].Vhwa.Settings.cOverlaysSupported;
2001 }
2002#endif
2003 pCaps->GammaRampCaps.Value = 0;
2004 pCaps->PresentationCaps.Value = 0;
2005 pCaps->PresentationCaps.NoScreenToScreenBlt = 1;
2006 pCaps->PresentationCaps.NoOverlapScreenBlt = 1;
2007 pCaps->MaxQueuedFlipOnVSync = 0; /* do we need it? */
2008 pCaps->FlipCaps.Value = 0;
2009 /* ? pCaps->FlipCaps.FlipOnVSyncWithNoWait = 1; */
2010 pCaps->SchedulingCaps.Value = 0;
2011 /* we might need it for Aero.
2012 * Setting this flag means we support DeviceContext, i.e.
2013 * DxgkDdiCreateContext and DxgkDdiDestroyContext
2014 */
2015 pCaps->SchedulingCaps.MultiEngineAware = 1;
2016 pCaps->MemoryManagementCaps.Value = 0;
2017 /* @todo: this correlates with pCaps->SchedulingCaps.MultiEngineAware */
2018 pCaps->MemoryManagementCaps.PagingNode = 0;
2019 /* @todo: this correlates with pCaps->SchedulingCaps.MultiEngineAware */
2020 pCaps->GpuEngineTopology.NbAsymetricProcessingNodes = VBOXWDDM_NUM_NODES;
2021#ifdef VBOX_WDDM_WIN8
2022 pCaps->WDDMVersion = DXGKDDI_WDDMv1;
2023#endif
2024 }
2025#ifdef VBOX_WDDM_WIN8
2026 else
2027 {
2028 pCaps->WDDMVersion = DXGKDDI_WDDMv1_2;
2029 }
2030#endif
2031 break;
2032 }
2033 case DXGKQAITYPE_QUERYSEGMENT:
2034 {
2035#ifdef VBOX_WDDM_WIN8
2036 if (!g_VBoxDisplayOnly)
2037#endif
2038 {
2039 /* no need for DXGK_QUERYSEGMENTIN as it contains AGP aperture info, which (AGP aperture) we do not support
2040 * DXGK_QUERYSEGMENTIN *pQsIn = (DXGK_QUERYSEGMENTIN*)pQueryAdapterInfo->pInputData; */
2041 DXGK_QUERYSEGMENTOUT *pQsOut = (DXGK_QUERYSEGMENTOUT*)pQueryAdapterInfo->pOutputData;
2042#ifdef VBOXWDDM_RENDER_FROM_SHADOW
2043# define VBOXWDDM_SEGMENTS_COUNT 2
2044#else
2045# define VBOXWDDM_SEGMENTS_COUNT 1
2046#endif
2047 if (!pQsOut->pSegmentDescriptor)
2048 {
2049 /* we are requested to provide the number of segments we support */
2050 pQsOut->NbSegment = VBOXWDDM_SEGMENTS_COUNT;
2051 }
2052 else if (pQsOut->NbSegment != VBOXWDDM_SEGMENTS_COUNT)
2053 {
2054 AssertBreakpoint();
2055 LOGREL(("NbSegment (%d) != 1", pQsOut->NbSegment));
2056 Status = STATUS_INVALID_PARAMETER;
2057 }
2058 else
2059 {
2060 DXGK_SEGMENTDESCRIPTOR* pDr = pQsOut->pSegmentDescriptor;
2061 /* we are requested to provide segment information */
2062 pDr->BaseAddress.QuadPart = 0;
2063 pDr->CpuTranslatedAddress = VBoxCommonFromDeviceExt(pDevExt)->phVRAM;
2064 /* make sure the size is page aligned */
2065 /* @todo: need to setup VBVA buffers and adjust the mem size here */
2066 pDr->Size = vboxWddmVramCpuVisibleSegmentSize(pDevExt);
2067 pDr->NbOfBanks = 0;
2068 pDr->pBankRangeTable = 0;
2069 pDr->CommitLimit = pDr->Size;
2070 pDr->Flags.Value = 0;
2071 pDr->Flags.CpuVisible = 1;
2072#ifdef VBOXWDDM_RENDER_FROM_SHADOW
2073 ++pDr;
2074 /* create cpu-invisible segment of the same size */
2075 pDr->BaseAddress.QuadPart = 0;
2076 pDr->CpuTranslatedAddress.QuadPart = 0;
2077 /* make sure the size is page aligned */
2078 /* @todo: need to setup VBVA buffers and adjust the mem size here */
2079 pDr->Size = vboxWddmVramCpuInvisibleSegmentSize(pDevExt);
2080 pDr->NbOfBanks = 0;
2081 pDr->pBankRangeTable = 0;
2082 pDr->CommitLimit = pDr->Size;
2083 pDr->Flags.Value = 0;
2084#endif
2085
2086 pQsOut->PagingBufferSegmentId = 0;
2087 pQsOut->PagingBufferSize = 1024;
2088 pQsOut->PagingBufferPrivateDataSize = 0; /* @todo: do we need a private buffer ? */
2089 }
2090 }
2091#ifdef VBOX_WDDM_WIN8
2092 else
2093 {
2094 WARN(("unsupported Type (%d)", pQueryAdapterInfo->Type));
2095 Status = STATUS_NOT_SUPPORTED;
2096 }
2097#endif
2098
2099 break;
2100 }
2101 case DXGKQAITYPE_UMDRIVERPRIVATE:
2102#ifdef VBOX_WDDM_WIN8
2103 if (!g_VBoxDisplayOnly)
2104#endif
2105 {
2106 if (pQueryAdapterInfo->OutputDataSize == sizeof (VBOXWDDM_QI))
2107 {
2108 VBOXWDDM_QI * pQi = (VBOXWDDM_QI*)pQueryAdapterInfo->pOutputData;
2109 memset (pQi, 0, sizeof (VBOXWDDM_QI));
2110 pQi->u32Version = VBOXVIDEOIF_VERSION;
2111 pQi->u32VBox3DCaps = VBoxMpCrGetHostCaps();
2112 pQi->cInfos = VBoxCommonFromDeviceExt(pDevExt)->cDisplays;
2113#ifdef VBOX_WITH_VIDEOHWACCEL
2114 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
2115 {
2116 pQi->aInfos[i] = pDevExt->aSources[i].Vhwa.Settings;
2117 }
2118#endif
2119 }
2120 else
2121 {
2122 WARN(("incorrect buffer size %d, expected %d", pQueryAdapterInfo->OutputDataSize, sizeof (VBOXWDDM_QI)));
2123 Status = STATUS_BUFFER_TOO_SMALL;
2124 }
2125 }
2126#ifdef VBOX_WDDM_WIN8
2127 else
2128 {
2129 WARN(("unsupported Type (%d)", pQueryAdapterInfo->Type));
2130 Status = STATUS_NOT_SUPPORTED;
2131 }
2132#endif
2133 break;
2134#ifdef VBOX_WDDM_WIN8
2135 case DXGKQAITYPE_QUERYSEGMENT3:
2136 LOGREL(("DXGKQAITYPE_QUERYSEGMENT3 treating as unsupported!"));
2137 Status = STATUS_NOT_SUPPORTED;
2138 break;
2139#endif
2140 default:
2141 WARN(("unsupported Type (%d)", pQueryAdapterInfo->Type));
2142 Status = STATUS_NOT_SUPPORTED;
2143 break;
2144 }
2145 LOGF(("LEAVE, context(0x%x), Status(0x%x)", hAdapter, Status));
2146 return Status;
2147}
2148
2149/**
2150 * DxgkDdiCreateDevice
2151 */
2152NTSTATUS APIENTRY DxgkDdiCreateDevice(
2153 CONST HANDLE hAdapter,
2154 DXGKARG_CREATEDEVICE* pCreateDevice)
2155{
2156 /* DxgkDdiCreateDevice should be made pageable. */
2157 PAGED_CODE();
2158
2159 LOGF(("ENTER, context(0x%x)", hAdapter));
2160 NTSTATUS Status = STATUS_SUCCESS;
2161 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
2162
2163 vboxVDbgBreakFv();
2164
2165 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)vboxWddmMemAllocZero(sizeof (VBOXWDDM_DEVICE));
2166 pCreateDevice->hDevice = pDevice;
2167 if (pCreateDevice->Flags.SystemDevice)
2168 pDevice->enmType = VBOXWDDM_DEVICE_TYPE_SYSTEM;
2169
2170 pDevice->pAdapter = pDevExt;
2171 pDevice->hDevice = pCreateDevice->hDevice;
2172
2173 pCreateDevice->hDevice = pDevice;
2174 pCreateDevice->pInfo = NULL;
2175
2176 LOGF(("LEAVE, context(0x%x), Status(0x%x)", hAdapter, Status));
2177
2178 return Status;
2179}
2180
2181PVBOXWDDM_RESOURCE vboxWddmResourceCreate(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_RCINFO pRcInfo)
2182{
2183 PVBOXWDDM_RESOURCE pResource = (PVBOXWDDM_RESOURCE)vboxWddmMemAllocZero(RT_OFFSETOF(VBOXWDDM_RESOURCE, aAllocations[pRcInfo->cAllocInfos]));
2184 if (!pResource)
2185 {
2186 AssertFailed();
2187 return NULL;
2188 }
2189 pResource->cRefs = 1;
2190 pResource->cAllocations = pRcInfo->cAllocInfos;
2191 pResource->fFlags = pRcInfo->fFlags;
2192 pResource->RcDesc = pRcInfo->RcDesc;
2193 return pResource;
2194}
2195
2196VOID vboxWddmResourceRetain(PVBOXWDDM_RESOURCE pResource)
2197{
2198 ASMAtomicIncU32(&pResource->cRefs);
2199}
2200
2201static VOID vboxWddmResourceDestroy(PVBOXWDDM_RESOURCE pResource)
2202{
2203 vboxWddmMemFree(pResource);
2204}
2205
2206VOID vboxWddmResourceWaitDereference(PVBOXWDDM_RESOURCE pResource)
2207{
2208 vboxWddmCounterU32Wait(&pResource->cRefs, 1);
2209}
2210
2211VOID vboxWddmResourceRelease(PVBOXWDDM_RESOURCE pResource)
2212{
2213 uint32_t cRefs = ASMAtomicDecU32(&pResource->cRefs);
2214 Assert(cRefs < UINT32_MAX/2);
2215 if (!cRefs)
2216 {
2217 vboxWddmResourceDestroy(pResource);
2218 }
2219}
2220
2221void vboxWddmAllocationDeleteFromResource(PVBOXWDDM_RESOURCE pResource, PVBOXWDDM_ALLOCATION pAllocation)
2222{
2223 Assert(pAllocation->pResource == pResource);
2224 if (pResource)
2225 {
2226 Assert(&pResource->aAllocations[pAllocation->iIndex] == pAllocation);
2227 vboxWddmResourceRelease(pResource);
2228 }
2229 else
2230 {
2231 vboxWddmMemFree(pAllocation);
2232 }
2233}
2234
2235VOID vboxWddmAllocationCleanupAssignment(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pAllocation)
2236{
2237 switch (pAllocation->enmType)
2238 {
2239 case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
2240 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
2241 {
2242 if (pAllocation->bAssigned)
2243 {
2244 /* @todo: do we need to notify host? */
2245 vboxWddmAssignPrimary(pDevExt, &pDevExt->aSources[pAllocation->AllocData.SurfDesc.VidPnSourceId], NULL, pAllocation->AllocData.SurfDesc.VidPnSourceId);
2246 }
2247 break;
2248 }
2249#ifdef VBOXWDDM_RENDER_FROM_SHADOW
2250 case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
2251 {
2252 if (pAllocation->bAssigned)
2253 {
2254 Assert(pAllocation->AllocData.SurfDesc.VidPnSourceId != D3DDDI_ID_UNINITIALIZED);
2255 /* @todo: do we need to notify host? */
2256 vboxWddmAssignShadow(pDevExt, &pDevExt->aSources[pAllocation->AllocData.SurfDesc.VidPnSourceId], NULL, pAllocation->AllocData.SurfDesc.VidPnSourceId);
2257 }
2258 break;
2259 }
2260#endif
2261 default:
2262 break;
2263 }
2264}
2265
2266VOID vboxWddmAllocationCleanup(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_ALLOCATION pAllocation)
2267{
2268 switch (pAllocation->enmType)
2269 {
2270 case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
2271 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
2272 {
2273#if 0
2274 if (pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC)
2275 {
2276 if (pAllocation->hSharedHandle)
2277 {
2278 vboxShRcTreeRemove(pDevExt, pAllocation);
2279 }
2280 }
2281#endif
2282 break;
2283 }
2284 case VBOXWDDM_ALLOC_TYPE_UMD_HGSMI_BUFFER:
2285 {
2286 break;
2287 }
2288 default:
2289 break;
2290 }
2291
2292 PVBOXWDDM_SWAPCHAIN pSwapchain = vboxWddmSwapchainRetainByAlloc(pDevExt, pAllocation);
2293 if (pSwapchain)
2294 {
2295 vboxWddmSwapchainAllocRemove(pDevExt, pSwapchain, pAllocation);
2296 vboxWddmSwapchainRelease(pSwapchain);
2297 }
2298}
2299
2300VOID vboxWddmAllocationDestroy(PVBOXWDDM_ALLOCATION pAllocation)
2301{
2302 PAGED_CODE();
2303
2304 vboxWddmAllocationDeleteFromResource(pAllocation->pResource, pAllocation);
2305}
2306
2307PVBOXWDDM_ALLOCATION vboxWddmAllocationCreateFromResource(PVBOXWDDM_RESOURCE pResource, uint32_t iIndex)
2308{
2309 PVBOXWDDM_ALLOCATION pAllocation = NULL;
2310 if (pResource)
2311 {
2312 Assert(iIndex < pResource->cAllocations);
2313 if (iIndex < pResource->cAllocations)
2314 {
2315 pAllocation = &pResource->aAllocations[iIndex];
2316 memset(pAllocation, 0, sizeof (VBOXWDDM_ALLOCATION));
2317 }
2318 vboxWddmResourceRetain(pResource);
2319 }
2320 else
2321 pAllocation = (PVBOXWDDM_ALLOCATION)vboxWddmMemAllocZero(sizeof (VBOXWDDM_ALLOCATION));
2322
2323 if (pAllocation)
2324 {
2325 if (pResource)
2326 {
2327 pAllocation->pResource = pResource;
2328 pAllocation->iIndex = iIndex;
2329 }
2330 }
2331
2332 return pAllocation;
2333}
2334
2335VOID vboxWddmAllocationWaitDereference(PVBOXWDDM_ALLOCATION pAllocation)
2336{
2337 vboxWddmCounterU32Wait(&pAllocation->cRefs, 1);
2338}
2339
2340
2341NTSTATUS vboxWddmAllocationCreate(PVBOXMP_DEVEXT pDevExt, PVBOXWDDM_RESOURCE pResource, uint32_t iIndex, DXGK_ALLOCATIONINFO* pAllocationInfo)
2342{
2343 PAGED_CODE();
2344
2345 NTSTATUS Status = STATUS_SUCCESS;
2346
2347 Assert(pAllocationInfo->PrivateDriverDataSize == sizeof (VBOXWDDM_ALLOCINFO));
2348 if (pAllocationInfo->PrivateDriverDataSize >= sizeof (VBOXWDDM_ALLOCINFO))
2349 {
2350 PVBOXWDDM_ALLOCINFO pAllocInfo = (PVBOXWDDM_ALLOCINFO)pAllocationInfo->pPrivateDriverData;
2351 PVBOXWDDM_ALLOCATION pAllocation = vboxWddmAllocationCreateFromResource(pResource, iIndex);
2352 Assert(pAllocation);
2353 if (pAllocation)
2354 {
2355 pAllocationInfo->pPrivateDriverData = NULL;
2356 pAllocationInfo->PrivateDriverDataSize = 0;
2357 pAllocationInfo->Alignment = 0;
2358 pAllocationInfo->PitchAlignedSize = 0;
2359 pAllocationInfo->HintedBank.Value = 0;
2360 pAllocationInfo->PreferredSegment.Value = 0;
2361 pAllocationInfo->SupportedReadSegmentSet = 1;
2362 pAllocationInfo->SupportedWriteSegmentSet = 1;
2363 pAllocationInfo->EvictionSegmentSet = 0;
2364 pAllocationInfo->MaximumRenamingListLength = 0;
2365 pAllocationInfo->hAllocation = pAllocation;
2366 pAllocationInfo->Flags.Value = 0;
2367 pAllocationInfo->pAllocationUsageHint = NULL;
2368 pAllocationInfo->AllocationPriority = D3DDDI_ALLOCATIONPRIORITY_NORMAL;
2369
2370 pAllocation->enmType = pAllocInfo->enmType;
2371 pAllocation->AllocData.Addr.SegmentId = 0;
2372 pAllocation->AllocData.Addr.offVram = VBOXVIDEOOFFSET_VOID;
2373 pAllocation->cRefs = 1;
2374 pAllocation->bVisible = FALSE;
2375 pAllocation->bAssigned = FALSE;
2376 KeInitializeSpinLock(&pAllocation->OpenLock);
2377 InitializeListHead(&pAllocation->OpenList);
2378
2379 switch (pAllocInfo->enmType)
2380 {
2381 case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
2382 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
2383 case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
2384 case VBOXWDDM_ALLOC_TYPE_STD_STAGINGSURFACE:
2385 {
2386 pAllocation->fRcFlags = pAllocInfo->fFlags;
2387 pAllocation->AllocData.SurfDesc = pAllocInfo->SurfDesc;
2388 pAllocation->AllocData.hostID = pAllocInfo->hostID;
2389
2390 pAllocationInfo->Size = pAllocInfo->SurfDesc.cbSize;
2391
2392 switch (pAllocInfo->enmType)
2393 {
2394 case VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE:
2395#if 0 //defined(VBOXWDDM_RENDER_FROM_SHADOW)
2396 pAllocationInfo->SupportedReadSegmentSet = 2;
2397 pAllocationInfo->SupportedWriteSegmentSet = 2;
2398#endif
2399#ifndef VBOXWDDM_RENDER_FROM_SHADOW
2400 pAllocationInfo->Flags.CpuVisible = 1;
2401#endif
2402 break;
2403 case VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC:
2404#ifdef VBOX_WITH_VIDEOHWACCEL
2405 if (pAllocInfo->fFlags.Overlay)
2406 {
2407 /* actually we can not "properly" issue create overlay commands to the host here
2408 * because we do not know source VidPn id here, i.e.
2409 * the primary which is supposed to be overlayed,
2410 * however we need to get some info like pitch & size from the host here */
2411 int rc = vboxVhwaHlpGetSurfInfo(pDevExt, pAllocation);
2412 AssertRC(rc);
2413 if (RT_SUCCESS(rc))
2414 {
2415 pAllocationInfo->Flags.Overlay = 1;
2416 pAllocationInfo->Flags.CpuVisible = 1;
2417 pAllocationInfo->Size = pAllocation->AllocData.SurfDesc.cbSize;
2418
2419 pAllocationInfo->AllocationPriority = D3DDDI_ALLOCATIONPRIORITY_HIGH;
2420 }
2421 else
2422 Status = STATUS_UNSUCCESSFUL;
2423 }
2424 else
2425#endif
2426 {
2427 Assert(pAllocation->AllocData.SurfDesc.bpp);
2428 Assert(pAllocation->AllocData.SurfDesc.pitch);
2429 Assert(pAllocation->AllocData.SurfDesc.cbSize);
2430 if (!pAllocInfo->fFlags.SharedResource)
2431 {
2432 pAllocationInfo->Flags.CpuVisible = 1;
2433 }
2434 else
2435 {
2436 pAllocation->hSharedHandle = (HANDLE)pAllocInfo->hSharedHandle;
2437#if 0
2438 if (pAllocation->hSharedHandle)
2439 {
2440 vboxShRcTreePut(pDevExt, pAllocation);
2441 }
2442#endif
2443 }
2444 }
2445 break;
2446 case VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE:
2447 case VBOXWDDM_ALLOC_TYPE_STD_STAGINGSURFACE:
2448 pAllocationInfo->Flags.CpuVisible = 1;
2449 break;
2450 }
2451
2452 if (Status == STATUS_SUCCESS)
2453 {
2454 pAllocation->UsageHint.Version = 0;
2455 pAllocation->UsageHint.v1.Flags.Value = 0;
2456 pAllocation->UsageHint.v1.Format = pAllocInfo->SurfDesc.format;
2457 pAllocation->UsageHint.v1.SwizzledFormat = 0;
2458 pAllocation->UsageHint.v1.ByteOffset = 0;
2459 pAllocation->UsageHint.v1.Width = pAllocation->AllocData.SurfDesc.width;
2460 pAllocation->UsageHint.v1.Height = pAllocation->AllocData.SurfDesc.height;
2461 pAllocation->UsageHint.v1.Pitch = pAllocation->AllocData.SurfDesc.pitch;
2462 pAllocation->UsageHint.v1.Depth = 0;
2463 pAllocation->UsageHint.v1.SlicePitch = 0;
2464
2465 Assert(!pAllocationInfo->pAllocationUsageHint);
2466 pAllocationInfo->pAllocationUsageHint = &pAllocation->UsageHint;
2467 }
2468
2469 break;
2470 }
2471 case VBOXWDDM_ALLOC_TYPE_UMD_HGSMI_BUFFER:
2472 {
2473 pAllocationInfo->Size = pAllocInfo->cbBuffer;
2474 pAllocation->fUhgsmiType = pAllocInfo->fUhgsmiType;
2475 pAllocation->AllocData.SurfDesc.cbSize = pAllocInfo->cbBuffer;
2476 pAllocationInfo->Flags.CpuVisible = 1;
2477// pAllocationInfo->Flags.SynchronousPaging = 1;
2478 pAllocationInfo->AllocationPriority = D3DDDI_ALLOCATIONPRIORITY_MAXIMUM;
2479 break;
2480 }
2481
2482 default:
2483 LOGREL(("ERROR: invalid alloc info type(%d)", pAllocInfo->enmType));
2484 AssertBreakpoint();
2485 Status = STATUS_INVALID_PARAMETER;
2486 break;
2487
2488 }
2489
2490 if (Status != STATUS_SUCCESS)
2491 vboxWddmAllocationDeleteFromResource(pResource, pAllocation);
2492 }
2493 else
2494 {
2495 LOGREL(("ERROR: failed to create allocation description"));
2496 Status = STATUS_NO_MEMORY;
2497 }
2498
2499 }
2500 else
2501 {
2502 LOGREL(("ERROR: PrivateDriverDataSize(%d) less than header size(%d)", pAllocationInfo->PrivateDriverDataSize, sizeof (VBOXWDDM_ALLOCINFO)));
2503 Status = STATUS_INVALID_PARAMETER;
2504 }
2505
2506 return Status;
2507}
2508
2509NTSTATUS APIENTRY DxgkDdiCreateAllocation(
2510 CONST HANDLE hAdapter,
2511 DXGKARG_CREATEALLOCATION* pCreateAllocation)
2512{
2513 /* DxgkDdiCreateAllocation should be made pageable. */
2514 PAGED_CODE();
2515
2516 LOGF(("ENTER, context(0x%x)", hAdapter));
2517
2518 vboxVDbgBreakFv();
2519
2520 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
2521 NTSTATUS Status = STATUS_SUCCESS;
2522 PVBOXWDDM_RESOURCE pResource = NULL;
2523
2524 if (pCreateAllocation->PrivateDriverDataSize)
2525 {
2526 Assert(pCreateAllocation->PrivateDriverDataSize == sizeof (VBOXWDDM_RCINFO));
2527 Assert(pCreateAllocation->pPrivateDriverData);
2528 if (pCreateAllocation->PrivateDriverDataSize < sizeof (VBOXWDDM_RCINFO))
2529 {
2530 WARN(("invalid private data size (%d)", pCreateAllocation->PrivateDriverDataSize));
2531 return STATUS_INVALID_PARAMETER;
2532 }
2533
2534 PVBOXWDDM_RCINFO pRcInfo = (PVBOXWDDM_RCINFO)pCreateAllocation->pPrivateDriverData;
2535// Assert(pRcInfo->RcDesc.VidPnSourceId < VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
2536 if (pRcInfo->cAllocInfos != pCreateAllocation->NumAllocations)
2537 {
2538 WARN(("invalid number of allocations passed in, (%d), expected (%d)", pRcInfo->cAllocInfos, pCreateAllocation->NumAllocations));
2539 return STATUS_INVALID_PARAMETER;
2540 }
2541
2542 /* a check to ensure we do not get the allocation size which is too big to overflow the 32bit value */
2543 if (VBOXWDDM_TRAILARRAY_MAXELEMENTSU32(VBOXWDDM_RESOURCE, aAllocations) < pRcInfo->cAllocInfos)
2544 {
2545 WARN(("number of allocations passed too big (%d), max is (%d)", pRcInfo->cAllocInfos, VBOXWDDM_TRAILARRAY_MAXELEMENTSU32(VBOXWDDM_RESOURCE, aAllocations)));
2546 return STATUS_INVALID_PARAMETER;
2547 }
2548
2549 pResource = (PVBOXWDDM_RESOURCE)vboxWddmMemAllocZero(RT_OFFSETOF(VBOXWDDM_RESOURCE, aAllocations[pRcInfo->cAllocInfos]));
2550 if (!pResource)
2551 {
2552 WARN(("vboxWddmMemAllocZero failed for (%d) allocations", pRcInfo->cAllocInfos));
2553 return STATUS_NO_MEMORY;
2554 }
2555
2556 pResource->cRefs = 1;
2557 pResource->cAllocations = pRcInfo->cAllocInfos;
2558 pResource->fFlags = pRcInfo->fFlags;
2559 pResource->RcDesc = pRcInfo->RcDesc;
2560 }
2561
2562
2563 for (UINT i = 0; i < pCreateAllocation->NumAllocations; ++i)
2564 {
2565 Status = vboxWddmAllocationCreate(pDevExt, pResource, i, &pCreateAllocation->pAllocationInfo[i]);
2566 if (Status != STATUS_SUCCESS)
2567 {
2568 WARN(("vboxWddmAllocationCreate(%d) failed, Status(0x%x)", i, Status));
2569 /* note: i-th allocation is expected to be cleared in a fail handling code above */
2570 for (UINT j = 0; j < i; ++j)
2571 {
2572 vboxWddmAllocationCleanup(pDevExt, (PVBOXWDDM_ALLOCATION)pCreateAllocation->pAllocationInfo[j].hAllocation);
2573 vboxWddmAllocationRelease((PVBOXWDDM_ALLOCATION)pCreateAllocation->pAllocationInfo[j].hAllocation);
2574 }
2575 }
2576 }
2577
2578 pCreateAllocation->hResource = pResource;
2579 if (pResource && Status != STATUS_SUCCESS)
2580 vboxWddmResourceRelease(pResource);
2581
2582 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
2583
2584 return Status;
2585}
2586
2587NTSTATUS
2588APIENTRY
2589DxgkDdiDestroyAllocation(
2590 CONST HANDLE hAdapter,
2591 CONST DXGKARG_DESTROYALLOCATION* pDestroyAllocation)
2592{
2593 /* DxgkDdiDestroyAllocation should be made pageable. */
2594 PAGED_CODE();
2595
2596 LOGF(("ENTER, context(0x%x)", hAdapter));
2597
2598 vboxVDbgBreakFv();
2599
2600 NTSTATUS Status = STATUS_SUCCESS;
2601
2602 PVBOXWDDM_RESOURCE pRc = (PVBOXWDDM_RESOURCE)pDestroyAllocation->hResource;
2603 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
2604
2605 if (pRc)
2606 {
2607 Assert(pRc->cAllocations == pDestroyAllocation->NumAllocations);
2608 }
2609
2610 for (UINT i = 0; i < pDestroyAllocation->NumAllocations; ++i)
2611 {
2612 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pDestroyAllocation->pAllocationList[i];
2613 Assert(pAlloc->pResource == pRc);
2614 vboxWddmAllocationCleanupAssignment(pDevExt, pAlloc);
2615 /* wait for all current allocation-related ops are completed */
2616 vboxWddmAllocationWaitDereference(pAlloc);
2617 vboxWddmAllocationCleanup(pDevExt, pAlloc);
2618 vboxWddmAllocationRelease(pAlloc);
2619 }
2620
2621 if (pRc)
2622 {
2623 /* wait for all current resource-related ops are completed */
2624 vboxWddmResourceWaitDereference(pRc);
2625 vboxWddmResourceRelease(pRc);
2626 }
2627
2628 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
2629
2630 return Status;
2631}
2632
2633/**
2634 * DxgkDdiDescribeAllocation
2635 */
2636NTSTATUS
2637APIENTRY
2638DxgkDdiDescribeAllocation(
2639 CONST HANDLE hAdapter,
2640 DXGKARG_DESCRIBEALLOCATION* pDescribeAllocation)
2641{
2642// LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
2643
2644 vboxVDbgBreakFv();
2645
2646 PVBOXWDDM_ALLOCATION pAllocation = (PVBOXWDDM_ALLOCATION)pDescribeAllocation->hAllocation;
2647 pDescribeAllocation->Width = pAllocation->AllocData.SurfDesc.width;
2648 pDescribeAllocation->Height = pAllocation->AllocData.SurfDesc.height;
2649 pDescribeAllocation->Format = pAllocation->AllocData.SurfDesc.format;
2650 memset (&pDescribeAllocation->MultisampleMethod, 0, sizeof (pDescribeAllocation->MultisampleMethod));
2651 pDescribeAllocation->RefreshRate.Numerator = 60000;
2652 pDescribeAllocation->RefreshRate.Denominator = 1000;
2653 pDescribeAllocation->PrivateDriverFormatAttribute = 0;
2654
2655// LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
2656
2657 return STATUS_SUCCESS;
2658}
2659
2660/**
2661 * DxgkDdiGetStandardAllocationDriverData
2662 */
2663NTSTATUS
2664APIENTRY
2665DxgkDdiGetStandardAllocationDriverData(
2666 CONST HANDLE hAdapter,
2667 DXGKARG_GETSTANDARDALLOCATIONDRIVERDATA* pGetStandardAllocationDriverData)
2668{
2669 /* DxgkDdiGetStandardAllocationDriverData should be made pageable. */
2670 PAGED_CODE();
2671
2672 LOGF(("ENTER, context(0x%x)", hAdapter));
2673
2674 vboxVDbgBreakFv();
2675
2676 NTSTATUS Status = STATUS_SUCCESS;
2677 PVBOXWDDM_ALLOCINFO pAllocInfo = NULL;
2678
2679 switch (pGetStandardAllocationDriverData->StandardAllocationType)
2680 {
2681 case D3DKMDT_STANDARDALLOCATION_SHAREDPRIMARYSURFACE:
2682 {
2683 LOGF(("D3DKMDT_STANDARDALLOCATION_SHAREDPRIMARYSURFACE"));
2684 if(pGetStandardAllocationDriverData->pAllocationPrivateDriverData)
2685 {
2686 pAllocInfo = (PVBOXWDDM_ALLOCINFO)pGetStandardAllocationDriverData->pAllocationPrivateDriverData;
2687 memset (pAllocInfo, 0, sizeof (VBOXWDDM_ALLOCINFO));
2688 pAllocInfo->enmType = VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE;
2689 pAllocInfo->SurfDesc.width = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Width;
2690 pAllocInfo->SurfDesc.height = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Height;
2691 pAllocInfo->SurfDesc.format = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Format;
2692 pAllocInfo->SurfDesc.bpp = vboxWddmCalcBitsPerPixel(pAllocInfo->SurfDesc.format);
2693 pAllocInfo->SurfDesc.pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->Width, pAllocInfo->SurfDesc.format);
2694 pAllocInfo->SurfDesc.cbSize = vboxWddmCalcSize(pAllocInfo->SurfDesc.pitch, pAllocInfo->SurfDesc.height, pAllocInfo->SurfDesc.format);
2695 pAllocInfo->SurfDesc.depth = 0;
2696 pAllocInfo->SurfDesc.slicePitch = 0;
2697 pAllocInfo->SurfDesc.RefreshRate = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->RefreshRate;
2698 pAllocInfo->SurfDesc.VidPnSourceId = pGetStandardAllocationDriverData->pCreateSharedPrimarySurfaceData->VidPnSourceId;
2699 }
2700 pGetStandardAllocationDriverData->AllocationPrivateDriverDataSize = sizeof (VBOXWDDM_ALLOCINFO);
2701
2702 pGetStandardAllocationDriverData->ResourcePrivateDriverDataSize = 0;
2703 break;
2704 }
2705 case D3DKMDT_STANDARDALLOCATION_SHADOWSURFACE:
2706 {
2707 LOGF(("D3DKMDT_STANDARDALLOCATION_SHADOWSURFACE"));
2708 UINT bpp = vboxWddmCalcBitsPerPixel(pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format);
2709 Assert(bpp);
2710 if (bpp != 0)
2711 {
2712 UINT Pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Width, pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format);
2713 pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Pitch = Pitch;
2714
2715 /* @todo: need [d/q]word align?? */
2716
2717 if (pGetStandardAllocationDriverData->pAllocationPrivateDriverData)
2718 {
2719 pAllocInfo = (PVBOXWDDM_ALLOCINFO)pGetStandardAllocationDriverData->pAllocationPrivateDriverData;
2720 pAllocInfo->enmType = VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE;
2721 pAllocInfo->SurfDesc.width = pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Width;
2722 pAllocInfo->SurfDesc.height = pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Height;
2723 pAllocInfo->SurfDesc.format = pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format;
2724 pAllocInfo->SurfDesc.bpp = vboxWddmCalcBitsPerPixel(pAllocInfo->SurfDesc.format);
2725 pAllocInfo->SurfDesc.pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Width, pAllocInfo->SurfDesc.format);
2726 pAllocInfo->SurfDesc.cbSize = vboxWddmCalcSize(pAllocInfo->SurfDesc.pitch, pAllocInfo->SurfDesc.height, pAllocInfo->SurfDesc.format);
2727 pAllocInfo->SurfDesc.depth = 0;
2728 pAllocInfo->SurfDesc.slicePitch = 0;
2729 pAllocInfo->SurfDesc.RefreshRate.Numerator = 0;
2730 pAllocInfo->SurfDesc.RefreshRate.Denominator = 1000;
2731 pAllocInfo->SurfDesc.VidPnSourceId = D3DDDI_ID_UNINITIALIZED;
2732
2733 pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Pitch = pAllocInfo->SurfDesc.pitch;
2734 }
2735 pGetStandardAllocationDriverData->AllocationPrivateDriverDataSize = sizeof (VBOXWDDM_ALLOCINFO);
2736
2737 pGetStandardAllocationDriverData->ResourcePrivateDriverDataSize = 0;
2738 }
2739 else
2740 {
2741 LOGREL(("Invalid format (%d)", pGetStandardAllocationDriverData->pCreateShadowSurfaceData->Format));
2742 Status = STATUS_INVALID_PARAMETER;
2743 }
2744 break;
2745 }
2746 case D3DKMDT_STANDARDALLOCATION_STAGINGSURFACE:
2747 {
2748 LOGF(("D3DKMDT_STANDARDALLOCATION_STAGINGSURFACE"));
2749 if(pGetStandardAllocationDriverData->pAllocationPrivateDriverData)
2750 {
2751 pAllocInfo = (PVBOXWDDM_ALLOCINFO)pGetStandardAllocationDriverData->pAllocationPrivateDriverData;
2752 pAllocInfo->enmType = VBOXWDDM_ALLOC_TYPE_STD_STAGINGSURFACE;
2753 pAllocInfo->SurfDesc.width = pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Width;
2754 pAllocInfo->SurfDesc.height = pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Height;
2755 pAllocInfo->SurfDesc.format = D3DDDIFMT_X8R8G8B8; /* staging has always always D3DDDIFMT_X8R8G8B8 */
2756 pAllocInfo->SurfDesc.bpp = vboxWddmCalcBitsPerPixel(pAllocInfo->SurfDesc.format);
2757 pAllocInfo->SurfDesc.pitch = vboxWddmCalcPitch(pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Width, pAllocInfo->SurfDesc.format);
2758 pAllocInfo->SurfDesc.cbSize = vboxWddmCalcSize(pAllocInfo->SurfDesc.pitch, pAllocInfo->SurfDesc.height, pAllocInfo->SurfDesc.format);
2759 pAllocInfo->SurfDesc.depth = 0;
2760 pAllocInfo->SurfDesc.slicePitch = 0;
2761 pAllocInfo->SurfDesc.RefreshRate.Numerator = 0;
2762 pAllocInfo->SurfDesc.RefreshRate.Denominator = 1000;
2763 pAllocInfo->SurfDesc.VidPnSourceId = D3DDDI_ID_UNINITIALIZED;
2764
2765 pGetStandardAllocationDriverData->pCreateStagingSurfaceData->Pitch = pAllocInfo->SurfDesc.pitch;
2766 }
2767 pGetStandardAllocationDriverData->AllocationPrivateDriverDataSize = sizeof (VBOXWDDM_ALLOCINFO);
2768
2769 pGetStandardAllocationDriverData->ResourcePrivateDriverDataSize = 0;
2770 break;
2771 }
2772//#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
2773// case D3DKMDT_STANDARDALLOCATION_GDISURFACE:
2774//# error port to Win7 DDI
2775// break;
2776//#endif
2777 default:
2778 LOGREL(("Invalid allocation type (%d)", pGetStandardAllocationDriverData->StandardAllocationType));
2779 Status = STATUS_INVALID_PARAMETER;
2780 break;
2781 }
2782
2783 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
2784
2785 return Status;
2786}
2787
2788NTSTATUS
2789APIENTRY
2790DxgkDdiAcquireSwizzlingRange(
2791 CONST HANDLE hAdapter,
2792 DXGKARG_ACQUIRESWIZZLINGRANGE* pAcquireSwizzlingRange)
2793{
2794 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
2795
2796 AssertBreakpoint();
2797
2798 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
2799
2800 return STATUS_SUCCESS;
2801}
2802
2803NTSTATUS
2804APIENTRY
2805DxgkDdiReleaseSwizzlingRange(
2806 CONST HANDLE hAdapter,
2807 CONST DXGKARG_RELEASESWIZZLINGRANGE* pReleaseSwizzlingRange)
2808{
2809 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
2810
2811 AssertBreakpoint();
2812
2813 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
2814
2815 return STATUS_SUCCESS;
2816}
2817
2818static NTSTATUS
2819APIENTRY
2820DxgkDdiPatchNew(
2821 CONST HANDLE hAdapter,
2822 CONST DXGKARG_PATCH* pPatch)
2823{
2824 /* DxgkDdiPatch should be made pageable. */
2825 PAGED_CODE();
2826
2827 LOGF(("ENTER, context(0x%x)", hAdapter));
2828
2829 vboxVDbgBreakFv();
2830
2831 uint8_t * pPrivateBuf = (uint8_t*)((uint8_t*)pPatch->pDmaBufferPrivateData + pPatch->DmaBufferPrivateDataSubmissionStartOffset);
2832 UINT cbPatchBuff = pPatch->DmaBufferPrivateDataSubmissionEndOffset - pPatch->DmaBufferPrivateDataSubmissionStartOffset;
2833
2834 for (UINT i = pPatch->PatchLocationListSubmissionStart; i < pPatch->PatchLocationListSubmissionLength; ++i)
2835 {
2836 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[i];
2837 Assert(pPatchList->AllocationIndex < pPatch->AllocationListSize);
2838 const DXGK_ALLOCATIONLIST *pAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2839 if (!pAllocationList->SegmentId)
2840 {
2841 WARN(("no segment id specified"));
2842 continue;
2843 }
2844
2845 if (pPatchList->PatchOffset == ~0UL)
2846 {
2847 /* this is a dummy patch request, ignore */
2848 continue;
2849 }
2850
2851 if (pPatchList->PatchOffset >= cbPatchBuff)
2852 {
2853 WARN(("pPatchList->PatchOffset(%d) >= cbPatchBuff(%d)", pPatchList->PatchOffset, cbPatchBuff));
2854 return STATUS_INVALID_PARAMETER;
2855 }
2856
2857 VBOXCMDVBVAOFFSET *poffVram = (VBOXCMDVBVAOFFSET*)(pPrivateBuf + pPatchList->PatchOffset);
2858 Assert(pAllocationList->SegmentId);
2859 Assert(!pAllocationList->PhysicalAddress.HighPart);
2860 Assert(!(pAllocationList->PhysicalAddress.QuadPart & 0xfffUL)); /* <- just a check to ensure allocation offset does not go here */
2861 *poffVram = pAllocationList->PhysicalAddress.LowPart + pPatchList->AllocationOffset;;
2862 }
2863
2864 return STATUS_SUCCESS;
2865}
2866
2867
2868static NTSTATUS
2869APIENTRY
2870DxgkDdiPatchLegacy(
2871 CONST HANDLE hAdapter,
2872 CONST DXGKARG_PATCH* pPatch)
2873{
2874 /* DxgkDdiPatch should be made pageable. */
2875 PAGED_CODE();
2876
2877 NTSTATUS Status = STATUS_SUCCESS;
2878
2879 LOGF(("ENTER, context(0x%x)", hAdapter));
2880
2881 vboxVDbgBreakFv();
2882
2883 /* Value == 2 is Present
2884 * Value == 4 is RedirectedPresent
2885 * we do not expect any other flags to be set here */
2886// Assert(pPatch->Flags.Value == 2 || pPatch->Flags.Value == 4);
2887 if (pPatch->DmaBufferPrivateDataSubmissionEndOffset - pPatch->DmaBufferPrivateDataSubmissionStartOffset >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
2888 {
2889 Assert(pPatch->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR));
2890 VBOXWDDM_DMA_PRIVATEDATA_BASEHDR *pPrivateDataBase = (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR*)((uint8_t*)pPatch->pDmaBufferPrivateData + pPatch->DmaBufferPrivateDataSubmissionStartOffset);
2891 switch (pPrivateDataBase->enmCmd)
2892 {
2893 case VBOXVDMACMD_TYPE_DMA_PRESENT_SHADOW2PRIMARY:
2894 {
2895 PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY pS2P = (PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY)pPrivateDataBase;
2896 Assert(pPatch->PatchLocationListSubmissionLength == 2);
2897 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart];
2898 Assert(pPatchList->AllocationIndex == DXGK_PRESENT_SOURCE_INDEX);
2899 Assert(pPatchList->PatchOffset == 0);
2900 const DXGK_ALLOCATIONLIST *pSrcAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2901 Assert(pSrcAllocationList->SegmentId);
2902 pS2P->Shadow2Primary.ShadowAlloc.segmentIdAlloc = pSrcAllocationList->SegmentId;
2903 pS2P->Shadow2Primary.ShadowAlloc.offAlloc = (VBOXVIDEOOFFSET)pSrcAllocationList->PhysicalAddress.QuadPart;
2904//
2905// pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart + 1];
2906// Assert(pPatchList->AllocationIndex == DXGK_PRESENT_DESTINATION_INDEX);
2907// Assert(pPatchList->PatchOffset == 4);
2908// const DXGK_ALLOCATIONLIST *pDstAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2909// Assert(pDstAllocationList->SegmentId);
2910// pPrivateData->DstAllocInfo.segmentIdAlloc = pDstAllocationList->SegmentId;
2911// pPrivateData->DstAllocInfo.offAlloc = (VBOXVIDEOOFFSET)pDstAllocationList->PhysicalAddress.QuadPart;
2912 break;
2913 }
2914 case VBOXVDMACMD_TYPE_DMA_PRESENT_BLT:
2915 {
2916 PVBOXWDDM_DMA_PRIVATEDATA_BLT pBlt = (PVBOXWDDM_DMA_PRIVATEDATA_BLT)pPrivateDataBase;
2917 Assert(pPatch->PatchLocationListSubmissionLength == 2);
2918 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart];
2919 Assert(pPatchList->AllocationIndex == DXGK_PRESENT_SOURCE_INDEX);
2920 Assert(pPatchList->PatchOffset == 0);
2921 const DXGK_ALLOCATIONLIST *pSrcAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2922 Assert(pSrcAllocationList->SegmentId);
2923 pBlt->Blt.SrcAlloc.segmentIdAlloc = pSrcAllocationList->SegmentId;
2924 pBlt->Blt.SrcAlloc.offAlloc = (VBOXVIDEOOFFSET)pSrcAllocationList->PhysicalAddress.QuadPart;
2925
2926 pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart + 1];
2927 Assert(pPatchList->AllocationIndex == DXGK_PRESENT_DESTINATION_INDEX);
2928 Assert(pPatchList->PatchOffset == 4);
2929 const DXGK_ALLOCATIONLIST *pDstAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2930 Assert(pDstAllocationList->SegmentId);
2931 pBlt->Blt.DstAlloc.segmentIdAlloc = pDstAllocationList->SegmentId;
2932 pBlt->Blt.DstAlloc.offAlloc = (VBOXVIDEOOFFSET)pDstAllocationList->PhysicalAddress.QuadPart;
2933 break;
2934 }
2935 case VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP:
2936 {
2937 PVBOXWDDM_DMA_PRIVATEDATA_FLIP pFlip = (PVBOXWDDM_DMA_PRIVATEDATA_FLIP)pPrivateDataBase;
2938 Assert(pPatch->PatchLocationListSubmissionLength == 1);
2939 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart];
2940 Assert(pPatchList->AllocationIndex == DXGK_PRESENT_SOURCE_INDEX);
2941 Assert(pPatchList->PatchOffset == 0);
2942 const DXGK_ALLOCATIONLIST *pSrcAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2943 Assert(pSrcAllocationList->SegmentId);
2944 pFlip->Flip.Alloc.segmentIdAlloc = pSrcAllocationList->SegmentId;
2945 pFlip->Flip.Alloc.offAlloc = (VBOXVIDEOOFFSET)pSrcAllocationList->PhysicalAddress.QuadPart;
2946 break;
2947 }
2948 case VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL:
2949 {
2950 PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL pCF = (PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL)pPrivateDataBase;
2951 Assert(pPatch->PatchLocationListSubmissionLength == 1);
2952 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[pPatch->PatchLocationListSubmissionStart];
2953 Assert(pPatchList->AllocationIndex == DXGK_PRESENT_DESTINATION_INDEX);
2954 Assert(pPatchList->PatchOffset == 0);
2955 const DXGK_ALLOCATIONLIST *pDstAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2956 Assert(pDstAllocationList->SegmentId);
2957 pCF->ClrFill.Alloc.segmentIdAlloc = pDstAllocationList->SegmentId;
2958 pCF->ClrFill.Alloc.offAlloc = (VBOXVIDEOOFFSET)pDstAllocationList->PhysicalAddress.QuadPart;
2959 break;
2960 }
2961 case VBOXVDMACMD_TYPE_DMA_NOP:
2962 break;
2963 case VBOXVDMACMD_TYPE_CHROMIUM_CMD:
2964 {
2965 uint8_t * pPrivateBuf = (uint8_t*)pPrivateDataBase;
2966 for (UINT i = pPatch->PatchLocationListSubmissionStart; i < pPatch->PatchLocationListSubmissionLength; ++i)
2967 {
2968 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[i];
2969 Assert(pPatchList->AllocationIndex < pPatch->AllocationListSize);
2970 const DXGK_ALLOCATIONLIST *pAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2971 Assert(pAllocationList->SegmentId);
2972 if (pAllocationList->SegmentId)
2973 {
2974 DXGK_ALLOCATIONLIST *pAllocation2Patch = (DXGK_ALLOCATIONLIST*)(pPrivateBuf + pPatchList->PatchOffset);
2975 pAllocation2Patch->SegmentId = pAllocationList->SegmentId;
2976 pAllocation2Patch->PhysicalAddress.QuadPart = pAllocationList->PhysicalAddress.QuadPart + pPatchList->AllocationOffset;
2977 Assert(!(pAllocationList->PhysicalAddress.QuadPart & 0xfffUL)); /* <- just a check to ensure allocation offset does not go here */
2978 }
2979 }
2980 break;
2981 }
2982 default:
2983 {
2984 AssertBreakpoint();
2985 uint8_t *pBuf = ((uint8_t *)pPatch->pDmaBuffer) + pPatch->DmaBufferSubmissionStartOffset;
2986 for (UINT i = pPatch->PatchLocationListSubmissionStart; i < pPatch->PatchLocationListSubmissionLength; ++i)
2987 {
2988 const D3DDDI_PATCHLOCATIONLIST* pPatchList = &pPatch->pPatchLocationList[i];
2989 Assert(pPatchList->AllocationIndex < pPatch->AllocationListSize);
2990 const DXGK_ALLOCATIONLIST *pAllocationList = &pPatch->pAllocationList[pPatchList->AllocationIndex];
2991 if (pAllocationList->SegmentId)
2992 {
2993 Assert(pPatchList->PatchOffset < (pPatch->DmaBufferSubmissionEndOffset - pPatch->DmaBufferSubmissionStartOffset));
2994 *((VBOXVIDEOOFFSET*)(pBuf+pPatchList->PatchOffset)) = (VBOXVIDEOOFFSET)pAllocationList->PhysicalAddress.QuadPart;
2995 }
2996 else
2997 {
2998 /* sanity */
2999 if (pPatch->Flags.Value == 2 || pPatch->Flags.Value == 4)
3000 Assert(i == 0);
3001 }
3002 }
3003 break;
3004 }
3005 }
3006 }
3007 else if (pPatch->DmaBufferPrivateDataSubmissionEndOffset == pPatch->DmaBufferPrivateDataSubmissionStartOffset)
3008 {
3009 /* this is a NOP, just return success */
3010// LOG(("null data size, treating as NOP"));
3011 return STATUS_SUCCESS;
3012 }
3013 else
3014 {
3015 WARN(("DmaBufferPrivateDataSubmissionEndOffset (%d) - DmaBufferPrivateDataSubmissionStartOffset (%d) < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR) (%d)",
3016 pPatch->DmaBufferPrivateDataSubmissionEndOffset,
3017 pPatch->DmaBufferPrivateDataSubmissionStartOffset,
3018 sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
3019 return STATUS_INVALID_PARAMETER;
3020 }
3021
3022 LOGF(("LEAVE, context(0x%x)", hAdapter));
3023
3024 return Status;
3025}
3026
3027typedef struct VBOXWDDM_CALL_ISR
3028{
3029 PVBOXMP_DEVEXT pDevExt;
3030 ULONG MessageNumber;
3031} VBOXWDDM_CALL_ISR, *PVBOXWDDM_CALL_ISR;
3032
3033static BOOLEAN vboxWddmCallIsrCb(PVOID Context)
3034{
3035 PVBOXWDDM_CALL_ISR pdc = (PVBOXWDDM_CALL_ISR)Context;
3036 if (pdc->pDevExt->fCmdVbvaEnabled)
3037 return DxgkDdiInterruptRoutineNew(pdc->pDevExt, pdc->MessageNumber);
3038 return DxgkDdiInterruptRoutineLegacy(pdc->pDevExt, pdc->MessageNumber);
3039}
3040
3041NTSTATUS vboxWddmCallIsr(PVBOXMP_DEVEXT pDevExt)
3042{
3043 VBOXWDDM_CALL_ISR context;
3044 context.pDevExt = pDevExt;
3045 context.MessageNumber = 0;
3046 BOOLEAN bRet;
3047 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
3048 pDevExt->u.primary.DxgkInterface.DeviceHandle,
3049 vboxWddmCallIsrCb,
3050 &context,
3051 0, /* IN ULONG MessageNumber */
3052 &bRet);
3053 Assert(Status == STATUS_SUCCESS);
3054 return Status;
3055}
3056
3057#ifdef VBOX_WITH_CRHGSMI
3058DECLCALLBACK(VOID) vboxWddmDmaCompleteChromiumCmd(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext)
3059{
3060 PVBOXVDMACBUF_DR pDr = (PVBOXVDMACBUF_DR)pvContext;
3061 PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
3062 VBOXVDMACMD_CHROMIUM_CMD *pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_CHROMIUM_CMD);
3063 UINT cBufs = pBody->cBuffers;
3064 vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
3065}
3066#endif
3067
3068static NTSTATUS
3069APIENTRY
3070DxgkDdiSubmitCommandNew(
3071 CONST HANDLE hAdapter,
3072 CONST DXGKARG_SUBMITCOMMAND* pSubmitCommand)
3073{
3074 /* DxgkDdiSubmitCommand runs at dispatch, should not be pageable. */
3075
3076// LOGF(("ENTER, context(0x%x)", hAdapter));
3077
3078 vboxVDbgBreakFv();
3079
3080 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3081#ifdef DEBUG
3082 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pSubmitCommand->hContext;
3083 Assert(pContext);
3084 Assert(pContext->pDevice);
3085 Assert(pContext->pDevice->pAdapter == pDevExt);
3086 Assert(!pSubmitCommand->DmaBufferSegmentId);
3087#endif
3088
3089 /* the DMA command buffer is located in system RAM, the host will need to pick it from there */
3090 //BufInfo.fFlags = 0; /* see VBOXVDMACBUF_FLAG_xx */
3091 uint32_t cbCmd = pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset - pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset;
3092 if (cbCmd < sizeof (VBOXCMDVBVA_HDR))
3093 {
3094 WARN(("DmaBufferPrivateDataSubmissionEndOffset (%d) - DmaBufferPrivateDataSubmissionStartOffset (%d) < sizeof (VBOXCMDVBVA_HDR) (%d)",
3095 pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset,
3096 pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset,
3097 sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
3098 return STATUS_INVALID_PARAMETER;
3099 }
3100
3101 VBOXCMDVBVA_HDR *pHdr = (VBOXCMDVBVA_HDR*)((uint8_t*)pSubmitCommand->pDmaBufferPrivateData + pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset);
3102 pHdr->u32FenceID = pSubmitCommand->SubmissionFenceId;
3103 int rc = VBoxCmdVbvaSubmit(pDevExt, &pDevExt->CmdVbva, pHdr, cbCmd);
3104 if (RT_SUCCESS(rc))
3105 return STATUS_SUCCESS;
3106
3107 WARN(("VBoxCmdVbvaSubmit failed rc %d", rc));
3108 return STATUS_UNSUCCESSFUL;
3109}
3110
3111static NTSTATUS
3112APIENTRY
3113DxgkDdiSubmitCommandLegacy(
3114 CONST HANDLE hAdapter,
3115 CONST DXGKARG_SUBMITCOMMAND* pSubmitCommand)
3116{
3117 /* DxgkDdiSubmitCommand runs at dispatch, should not be pageable. */
3118 NTSTATUS Status = STATUS_SUCCESS;
3119
3120// LOGF(("ENTER, context(0x%x)", hAdapter));
3121
3122 vboxVDbgBreakFv();
3123
3124 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3125 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pSubmitCommand->hContext;
3126 PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR pPrivateDataBase = NULL;
3127 VBOXVDMACMD_TYPE enmCmd = VBOXVDMACMD_TYPE_UNDEFINED;
3128 Assert(pContext);
3129 Assert(pContext->pDevice);
3130 Assert(pContext->pDevice->pAdapter == pDevExt);
3131 Assert(!pSubmitCommand->DmaBufferSegmentId);
3132
3133 /* the DMA command buffer is located in system RAM, the host will need to pick it from there */
3134 //BufInfo.fFlags = 0; /* see VBOXVDMACBUF_FLAG_xx */
3135 if (pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset - pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
3136 {
3137 pPrivateDataBase = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)((uint8_t*)pSubmitCommand->pDmaBufferPrivateData + pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset);
3138 Assert(pPrivateDataBase);
3139 enmCmd = pPrivateDataBase->enmCmd;
3140 }
3141 else if (pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset == pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset)
3142 {
3143 enmCmd = VBOXVDMACMD_TYPE_DMA_NOP;
3144 }
3145 else
3146 {
3147 WARN(("DmaBufferPrivateDataSubmissionEndOffset (%d) - DmaBufferPrivateDataSubmissionStartOffset (%d) < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR) (%d)",
3148 pSubmitCommand->DmaBufferPrivateDataSubmissionEndOffset,
3149 pSubmitCommand->DmaBufferPrivateDataSubmissionStartOffset,
3150 sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
3151 return STATUS_INVALID_PARAMETER;
3152 }
3153
3154 if (pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D)
3155 vboxWddmModeRenderFromShadowDisableRegister(pDevExt, pContext);
3156
3157 switch (enmCmd)
3158 {
3159#ifdef VBOXWDDM_RENDER_FROM_SHADOW
3160 case VBOXVDMACMD_TYPE_DMA_PRESENT_SHADOW2PRIMARY:
3161 {
3162 PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY pS2P = (PVBOXWDDM_DMA_PRIVATEDATA_SHADOW2PRIMARY)pPrivateDataBase;
3163 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pS2P->Shadow2Primary.VidPnSourceId];
3164 PVBOXWDDM_ALLOCATION pSrcAlloc = pS2P->Shadow2Primary.ShadowAlloc.pAlloc;
3165 BOOLEAN fShadowChanged = vboxWddmAddrSetVram(&pSrcAlloc->AllocData.Addr, pS2P->Shadow2Primary.ShadowAlloc.segmentIdAlloc, pS2P->Shadow2Primary.ShadowAlloc.offAlloc);
3166 if (fShadowChanged)
3167 pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_LOCATION;
3168 vboxWddmAssignShadow(pDevExt, pSource, pSrcAlloc, pS2P->Shadow2Primary.VidPnSourceId);
3169 vboxWddmModeRenderFromShadowCheckOnSubmitCommand(pDevExt, NULL);
3170 vboxWddmGhDisplayCheckSetInfoFromSource(pDevExt, pSource);
3171 if (pSrcAlloc->bVisible)
3172 {
3173 uint32_t cUnlockedVBVADisabled = ASMAtomicReadU32(&pDevExt->cUnlockedVBVADisabled);
3174 if (!cUnlockedVBVADisabled)
3175 VBOXVBVA_OP(ReportDirtyRect, pDevExt, pSource, &pS2P->Shadow2Primary.SrcRect);
3176 else
3177 {
3178 Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
3179 VBOXVBVA_OP_WITHLOCK_ATDPC(ReportDirtyRect, pDevExt, pSource, &pS2P->Shadow2Primary.SrcRect);
3180 }
3181 }
3182
3183 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_COMPLETED);
3184 break;
3185 }
3186#endif
3187 case VBOXVDMACMD_TYPE_DMA_PRESENT_BLT:
3188 {
3189 VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR *pPrivateData = (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR*)pPrivateDataBase;
3190 PVBOXWDDM_DMA_PRIVATEDATA_BLT pBlt = (PVBOXWDDM_DMA_PRIVATEDATA_BLT)pPrivateData;
3191 PVBOXWDDM_ALLOCATION pDstAlloc = pBlt->Blt.DstAlloc.pAlloc;
3192 PVBOXWDDM_ALLOCATION pSrcAlloc = pBlt->Blt.SrcAlloc.pAlloc;
3193 BOOLEAN fSrcChanged;
3194 BOOLEAN fDstChanged;
3195
3196 fDstChanged = vboxWddmAddrSetVram(&pDstAlloc->AllocData.Addr, pBlt->Blt.DstAlloc.segmentIdAlloc, pBlt->Blt.DstAlloc.offAlloc);
3197 fSrcChanged = vboxWddmAddrSetVram(&pSrcAlloc->AllocData.Addr, pBlt->Blt.SrcAlloc.segmentIdAlloc, pBlt->Blt.SrcAlloc.offAlloc);
3198
3199 vboxWddmModeRenderFromShadowCheckOnSubmitCommand(pDevExt, NULL);
3200
3201 if (VBOXWDDM_IS_REAL_FB_ALLOCATION(pDevExt, pDstAlloc))
3202 {
3203 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pDstAlloc->AllocData.SurfDesc.VidPnSourceId];
3204
3205 Assert(pDstAlloc->AllocData.SurfDesc.VidPnSourceId < VBOX_VIDEO_MAX_SCREENS);
3206#if 0
3207 if (VBOXWDDM_IS_FB_ALLOCATION(pDevExt, pDstAlloc) && pDstAlloc->AllocData.hostID)
3208 {
3209 if (pSource->AllocData.hostID != pDstAlloc->AllocData.hostID)
3210 {
3211 pSource->AllocData.hostID = pDstAlloc->AllocData.hostID;
3212 fDstChanged = TRUE;
3213 }
3214
3215 if (fDstChanged)
3216 pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_LOCATION;
3217 }
3218 else
3219#endif
3220 if (pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE)
3221 {
3222 if (fSrcChanged)
3223 pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_LOCATION;
3224
3225 vboxWddmAssignShadow(pDevExt, pSource, pSrcAlloc, pDstAlloc->AllocData.SurfDesc.VidPnSourceId);
3226 vboxWddmGhDisplayCheckSetInfoFromSource(pDevExt, pSource);
3227 }
3228
3229 Assert(pSource->u8SyncState == VBOXWDDM_HGSYNC_F_SYNCED_ALL || pDevExt->aTargets[pDstAlloc->AllocData.SurfDesc.VidPnSourceId].fStateSyncPening);
3230 }
3231
3232 Status = vboxVdmaProcessBltCmd(pDevExt, pContext, pBlt);
3233 if (!NT_SUCCESS(Status))
3234 WARN(("vboxVdmaProcessBltCmd failed, Status 0x%x", Status));
3235
3236 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId,
3237 NT_SUCCESS(Status) ? DXGK_INTERRUPT_DMA_COMPLETED : DXGK_INTERRUPT_DMA_FAULTED);
3238 break;
3239 }
3240 case VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP:
3241 {
3242 VBOXWDDM_DMA_PRIVATEDATA_FLIP *pFlip = (VBOXWDDM_DMA_PRIVATEDATA_FLIP*)pPrivateDataBase;
3243 PVBOXWDDM_ALLOCATION pAlloc = pFlip->Flip.Alloc.pAlloc;
3244 VBOXWDDM_SOURCE *pSource = &pDevExt->aSources[pAlloc->AllocData.SurfDesc.VidPnSourceId];
3245 vboxWddmAddrSetVram(&pAlloc->AllocData.Addr, pFlip->Flip.Alloc.segmentIdAlloc, pFlip->Flip.Alloc.offAlloc);
3246 vboxWddmAssignPrimary(pDevExt, pSource, pAlloc, pAlloc->AllocData.SurfDesc.VidPnSourceId);
3247 vboxWddmGhDisplayCheckSetInfoFromSource(pDevExt, pSource);
3248
3249 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId,
3250 NT_SUCCESS(Status) ? DXGK_INTERRUPT_DMA_COMPLETED : DXGK_INTERRUPT_DMA_FAULTED);
3251 break;
3252 }
3253 case VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL:
3254 {
3255 PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL pCF = (PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL)pPrivateDataBase;
3256 vboxWddmAddrSetVram(&pCF->ClrFill.Alloc.pAlloc->AllocData.Addr, pCF->ClrFill.Alloc.segmentIdAlloc, pCF->ClrFill.Alloc.offAlloc);
3257
3258 Status = vboxVdmaProcessClrFillCmd(pDevExt, pContext, pCF);
3259 if (!NT_SUCCESS(Status))
3260 WARN(("vboxVdmaProcessClrFillCmd failed, Status 0x%x", Status));
3261
3262 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId,
3263 NT_SUCCESS(Status) ? DXGK_INTERRUPT_DMA_COMPLETED : DXGK_INTERRUPT_DMA_FAULTED);
3264 break;
3265 }
3266 case VBOXVDMACMD_TYPE_DMA_NOP:
3267 {
3268 Status = vboxVdmaDdiCmdFenceComplete(pDevExt, pContext->NodeOrdinal, pSubmitCommand->SubmissionFenceId, DXGK_INTERRUPT_DMA_COMPLETED);
3269 Assert(Status == STATUS_SUCCESS);
3270 break;
3271 }
3272 default:
3273 {
3274 WARN(("unexpected command %d", enmCmd));
3275#if 0 //def VBOX_WITH_VDMA
3276 VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR *pPrivateData = (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR*)pPrivateDataBase;
3277 PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate (&pDevExt->u.primary.Vdma, 0);
3278 if (!pDr)
3279 {
3280 /* @todo: try flushing.. */
3281 LOGREL(("vboxVdmaCBufDrCreate returned NULL"));
3282 return STATUS_INSUFFICIENT_RESOURCES;
3283 }
3284 // vboxVdmaCBufDrCreate zero initializes the pDr
3285 //pDr->fFlags = 0;
3286 pDr->cbBuf = pSubmitCommand->DmaBufferSubmissionEndOffset - pSubmitCommand->DmaBufferSubmissionStartOffset;
3287 pDr->u32FenceId = pSubmitCommand->SubmissionFenceId;
3288 pDr->rc = VERR_NOT_IMPLEMENTED;
3289 if (pPrivateData)
3290 pDr->u64GuestContext = (uint64_t)pPrivateData->pContext;
3291 // else // vboxVdmaCBufDrCreate zero initializes the pDr
3292 // pDr->u64GuestContext = NULL;
3293 pDr->Location.phBuf = pSubmitCommand->DmaBufferPhysicalAddress.QuadPart + pSubmitCommand->DmaBufferSubmissionStartOffset;
3294
3295 vboxVdmaCBufDrSubmit(pDevExt, &pDevExt->u.primary.Vdma, pDr);
3296#endif
3297 break;
3298 }
3299 }
3300// LOGF(("LEAVE, context(0x%x)", hAdapter));
3301
3302 return Status;
3303}
3304
3305static NTSTATUS
3306APIENTRY
3307DxgkDdiPreemptCommandNew(
3308 CONST HANDLE hAdapter,
3309 CONST DXGKARG_PREEMPTCOMMAND* pPreemptCommand)
3310{
3311 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3312
3313 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3314
3315 VBoxCmdVbvaPreempt(pDevExt, &pDevExt->CmdVbva, pPreemptCommand->PreemptionFenceId);
3316
3317 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3318
3319 return STATUS_SUCCESS;
3320}
3321
3322
3323static NTSTATUS
3324APIENTRY
3325DxgkDdiPreemptCommandLegacy(
3326 CONST HANDLE hAdapter,
3327 CONST DXGKARG_PREEMPTCOMMAND* pPreemptCommand)
3328{
3329 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3330
3331 AssertFailed();
3332 /* @todo: fixme: implement */
3333
3334 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3335
3336 return STATUS_SUCCESS;
3337}
3338
3339/*
3340 * DxgkDdiBuildPagingBuffer
3341 */
3342static NTSTATUS
3343APIENTRY
3344DxgkDdiBuildPagingBufferNew(
3345 CONST HANDLE hAdapter,
3346 DXGKARG_BUILDPAGINGBUFFER* pBuildPagingBuffer)
3347{
3348 /* DxgkDdiBuildPagingBuffer should be made pageable. */
3349 PAGED_CODE();
3350
3351 vboxVDbgBreakFv();
3352
3353 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3354 uint32_t cbBuffer = 0, cbPrivateData = 0;
3355
3356 LOGF(("ENTER, context(0x%x)", hAdapter));
3357
3358 /* paging buffer transfer is nop for hostID allocations */
3359 if (pBuildPagingBuffer->DmaBufferPrivateDataSize < sizeof (VBOXCMDVBVA_HDR))
3360 {
3361 WARN(("pBuildPagingBuffer->DmaBufferPrivateDataSize(%d) < sizeof VBOXCMDVBVA_HDR (%d)", pBuildPagingBuffer->DmaBufferPrivateDataSize , sizeof (VBOXCMDVBVA_HDR)));
3362 /* @todo: can this actually happen? what status to return? */
3363 return STATUS_INVALID_PARAMETER;
3364 }
3365
3366 switch (pBuildPagingBuffer->Operation)
3367 {
3368 case DXGK_OPERATION_TRANSFER:
3369 {
3370 VBOXCMDVBVA_HDR *pHdr = (VBOXCMDVBVA_HDR*)pBuildPagingBuffer->pDmaBuffer;
3371 pHdr->u8Flags = 0;
3372 pHdr->u8State = VBOXCMDVBVA_STATE_SUBMITTED;
3373 /* sanity */
3374 pHdr->u32FenceID = 0;
3375
3376 if ((!pBuildPagingBuffer->Transfer.Source.SegmentId) == (!pBuildPagingBuffer->Transfer.Destination.SegmentId))
3377 {
3378 WARN(("we only support RAM <-> VRAM moves, Src Seg(%d), Dst Seg(%d)", pBuildPagingBuffer->Transfer.Source.SegmentId, pBuildPagingBuffer->Transfer.Destination.SegmentId));
3379 return STATUS_INVALID_PARAMETER;
3380 }
3381
3382 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pBuildPagingBuffer->Transfer.hAllocation;
3383 if (!pAlloc)
3384 {
3385 WARN(("allocation is null"));
3386 return STATUS_INVALID_PARAMETER;
3387 }
3388
3389 if (pAlloc->AllocData.hostID)
3390 {
3391 pHdr->u8OpCode = VBOXCMDVBVA_OPTYPE_NOPCMD;
3392 cbBuffer = VBOXWDDM_DUMMY_DMABUFFER_SIZE;
3393 cbPrivateData = sizeof (*pHdr);
3394 break;
3395 }
3396
3397 if (pBuildPagingBuffer->DmaBufferPrivateDataSize < sizeof (VBOXCMDVBVA_PAGING_TRANSFER))
3398 {
3399 WARN(("pBuildPagingBuffer->DmaBufferPrivateDataSize(%d) < sizeof VBOXCMDVBVA_PAGING_TRANSFER (%d)", pBuildPagingBuffer->DmaBufferPrivateDataSize , sizeof (VBOXCMDVBVA_PAGING_TRANSFER)));
3400 /* @todo: can this actually happen? what status to return? */
3401 return STATUS_INVALID_PARAMETER;
3402 }
3403
3404 VBOXCMDVBVA_PAGING_TRANSFER *pPaging = (VBOXCMDVBVA_PAGING_TRANSFER*)pBuildPagingBuffer->pDmaBuffer;
3405 pPaging->Hdr.u8OpCode = VBOXCMDVBVA_OPTYPE_PAGING_TRANSFER;
3406
3407 PMDL pMdl;
3408 uint32_t offVRAM;
3409 BOOLEAN fIn;
3410
3411 if (pBuildPagingBuffer->Transfer.Source.SegmentId)
3412 {
3413 Assert(!pBuildPagingBuffer->Transfer.Destination.SegmentId);
3414 Assert(!pBuildPagingBuffer->Transfer.Source.SegmentAddress.HighPart);
3415 offVRAM = pBuildPagingBuffer->Transfer.Source.SegmentAddress.LowPart;
3416 pMdl = pBuildPagingBuffer->Transfer.Destination.pMdl;
3417 fIn = FALSE;
3418 }
3419 else
3420 {
3421 Assert(pBuildPagingBuffer->Transfer.Destination.SegmentId);
3422 Assert(!pBuildPagingBuffer->Transfer.Source.SegmentId);
3423 Assert(!pBuildPagingBuffer->Transfer.Destination.SegmentAddress.HighPart);
3424 offVRAM = pBuildPagingBuffer->Transfer.Destination.SegmentAddress.LowPart;
3425 pMdl = pBuildPagingBuffer->Transfer.Source.pMdl;
3426 fIn = TRUE;
3427 }
3428
3429 uint32_t cPages = (uint32_t)((pBuildPagingBuffer->Transfer.TransferSize + 0xfff) >> PAGE_SHIFT);
3430 uint32_t cTotalPages = cPages;
3431 cPages -= pBuildPagingBuffer->MultipassOffset;
3432 uint32_t iFirstPage = pBuildPagingBuffer->Transfer.MdlOffset + pBuildPagingBuffer->MultipassOffset;
3433 uint32_t cPagesWritten;
3434 offVRAM += pBuildPagingBuffer->Transfer.TransferOffset + pBuildPagingBuffer->MultipassOffset;
3435
3436 pPaging->Alloc.offVRAM = offVRAM;
3437 if (fIn)
3438 pPaging->Hdr.u8Flags |= VBOXCMDVBVA_OPF_PAGING_TRANSFER_IN;
3439 cbPrivateData = VBoxCVDdiPTransferVRamSysBuildEls(pPaging, pMdl, iFirstPage, cPages, pBuildPagingBuffer->DmaBufferPrivateDataSize, &cPagesWritten);
3440 if (cPagesWritten != cPages)
3441 pBuildPagingBuffer->MultipassOffset += cPagesWritten;
3442 else
3443 pBuildPagingBuffer->MultipassOffset = 0;
3444
3445 cbBuffer = VBOXWDDM_DUMMY_DMABUFFER_SIZE;
3446 break;
3447 }
3448 case DXGK_OPERATION_FILL:
3449 {
3450 Assert(pBuildPagingBuffer->Fill.FillPattern == 0);
3451 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pBuildPagingBuffer->Fill.hAllocation;
3452 if (!pAlloc)
3453 {
3454 WARN(("allocation is null"));
3455 return STATUS_INVALID_PARAMETER;
3456 }
3457 /** @todo: add necessary bits */
3458 WARN(("Impl!"));
3459 break;
3460 }
3461 case DXGK_OPERATION_DISCARD_CONTENT:
3462 {
3463 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pBuildPagingBuffer->DiscardContent.hAllocation;
3464 if (!pAlloc)
3465 {
3466 WARN(("allocation is null"));
3467 return STATUS_INVALID_PARAMETER;
3468 }
3469 break;
3470 }
3471 default:
3472 {
3473 WARN(("unsupported op (%d)", pBuildPagingBuffer->Operation));
3474 break;
3475 }
3476 }
3477
3478 pBuildPagingBuffer->pDmaBuffer = ((uint8_t*)pBuildPagingBuffer->pDmaBuffer) + cbBuffer;
3479 pBuildPagingBuffer->pDmaBufferPrivateData = ((uint8_t*)pBuildPagingBuffer->pDmaBufferPrivateData) + cbPrivateData;
3480
3481 LOGF(("LEAVE, context(0x%x)", hAdapter));
3482
3483 if (pBuildPagingBuffer->MultipassOffset)
3484 return STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
3485 return STATUS_SUCCESS;
3486}
3487
3488
3489static NTSTATUS
3490APIENTRY
3491DxgkDdiBuildPagingBufferLegacy(
3492 CONST HANDLE hAdapter,
3493 DXGKARG_BUILDPAGINGBUFFER* pBuildPagingBuffer)
3494{
3495 /* DxgkDdiBuildPagingBuffer should be made pageable. */
3496 PAGED_CODE();
3497
3498 vboxVDbgBreakFv();
3499
3500 NTSTATUS Status = STATUS_SUCCESS;
3501 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3502
3503 LOGF(("ENTER, context(0x%x)", hAdapter));
3504
3505 uint32_t cbCmdDma = 0;
3506
3507 /* @todo: */
3508 switch (pBuildPagingBuffer->Operation)
3509 {
3510 case DXGK_OPERATION_TRANSFER:
3511 {
3512 cbCmdDma = VBOXWDDM_DUMMY_DMABUFFER_SIZE;
3513#ifdef VBOX_WITH_VDMA
3514#if 0
3515 if ((!pBuildPagingBuffer->Transfer.Source.SegmentId) != (!pBuildPagingBuffer->Transfer.Destination.SegmentId))
3516 {
3517 PVBOXVDMACMD pCmd = (PVBOXVDMACMD)pBuildPagingBuffer->pDmaBuffer;
3518 pCmd->enmType = VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER_VRAMSYS;
3519 pCmd->u32CmdSpecific = 0;
3520 PVBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS pBody = VBOXVDMACMD_BODY(pCmd, VBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS);
3521 PMDL pMdl;
3522 uint32_t cPages = (pBuildPagingBuffer->Transfer.TransferSize + 0xfff) >> 12;
3523 cPages -= pBuildPagingBuffer->MultipassOffset;
3524 uint32_t iFirstPage = pBuildPagingBuffer->Transfer.MdlOffset + pBuildPagingBuffer->MultipassOffset;
3525 uint32_t cPagesRemaining;
3526 if (pBuildPagingBuffer->Transfer.Source.SegmentId)
3527 {
3528 uint64_t off = pBuildPagingBuffer->Transfer.Source.SegmentAddress.QuadPart;
3529 off += pBuildPagingBuffer->Transfer.TransferOffset + (pBuildPagingBuffer->MultipassOffset << 12);
3530 pBody->offVramBuf = off;
3531 pMdl = pBuildPagingBuffer->Transfer.Source.pMdl;
3532 pBody->fFlags = 0;//VBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS_SYS2VRAM
3533 }
3534 else
3535 {
3536 uint64_t off = pBuildPagingBuffer->Transfer.Destination.SegmentAddress.QuadPart;
3537 off += pBuildPagingBuffer->Transfer.TransferOffset + (pBuildPagingBuffer->MultipassOffset << 12);
3538 pBody->offVramBuf = off;
3539 pMdl = pBuildPagingBuffer->Transfer.Destination.pMdl;
3540 pBody->fFlags = VBOXVDMACMD_DMA_BPB_TRANSFER_VRAMSYS_SYS2VRAM;
3541 }
3542
3543 uint32_t sbBufferUsed = vboxWddmBpbTransferVRamSysBuildEls(pBody, pMdl, iFirstPage, cPages, pBuildPagingBuffer->DmaSize, &cPagesRemaining);
3544 Assert(sbBufferUsed);
3545 }
3546
3547#else
3548 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pBuildPagingBuffer->Transfer.hAllocation;
3549 Assert(pAlloc);
3550 if (pAlloc
3551 && !pAlloc->fRcFlags.Overlay /* overlay surfaces actually contain a valid data */
3552 && pAlloc->enmType != VBOXWDDM_ALLOC_TYPE_STD_SHADOWSURFACE /* shadow primary - also */
3553 && pAlloc->enmType != VBOXWDDM_ALLOC_TYPE_UMD_HGSMI_BUFFER /* hgsmi buffer - also */
3554 )
3555 {
3556 /* we do not care about the others for now */
3557 Status = STATUS_SUCCESS;
3558 break;
3559 }
3560 UINT cbCmd = VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_BPB_TRANSFER);
3561 PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate (&pDevExt->u.primary.Vdma, cbCmd);
3562 Assert(pDr);
3563 if (pDr)
3564 {
3565 SIZE_T cbTransfered = 0;
3566 SIZE_T cbTransferSize = pBuildPagingBuffer->Transfer.TransferSize;
3567 PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
3568 do
3569 {
3570 // vboxVdmaCBufDrCreate zero initializes the pDr
3571 pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR;
3572 pDr->cbBuf = cbCmd;
3573 pDr->rc = VERR_NOT_IMPLEMENTED;
3574
3575 pHdr->enmType = VBOXVDMACMD_TYPE_DMA_BPB_TRANSFER;
3576 pHdr->u32CmdSpecific = 0;
3577 VBOXVDMACMD_DMA_BPB_TRANSFER *pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_DMA_BPB_TRANSFER);
3578// pBody->cbTransferSize = (uint32_t)pBuildPagingBuffer->Transfer.TransferSize;
3579 pBody->fFlags = 0;
3580 SIZE_T cSrcPages = (cbTransferSize + 0xfff ) >> 12;
3581 SIZE_T cDstPages = cSrcPages;
3582
3583 if (pBuildPagingBuffer->Transfer.Source.SegmentId)
3584 {
3585 uint64_t off = pBuildPagingBuffer->Transfer.Source.SegmentAddress.QuadPart;
3586 off += pBuildPagingBuffer->Transfer.TransferOffset + cbTransfered;
3587 pBody->Src.offVramBuf = off;
3588 pBody->fFlags |= VBOXVDMACMD_DMA_BPB_TRANSFER_F_SRC_VRAMOFFSET;
3589 }
3590 else
3591 {
3592 UINT index = pBuildPagingBuffer->Transfer.MdlOffset + (UINT)(cbTransfered>>12);
3593 pBody->Src.phBuf = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Source.pMdl)[index] << 12;
3594 PFN_NUMBER num = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Source.pMdl)[index];
3595 cSrcPages = 1;
3596 for (UINT i = 1; i < ((cbTransferSize - cbTransfered + 0xfff) >> 12); ++i)
3597 {
3598 PFN_NUMBER cur = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Source.pMdl)[index+i];
3599 if(cur != ++num)
3600 {
3601 cSrcPages+= i-1;
3602 break;
3603 }
3604 }
3605 }
3606
3607 if (pBuildPagingBuffer->Transfer.Destination.SegmentId)
3608 {
3609 uint64_t off = pBuildPagingBuffer->Transfer.Destination.SegmentAddress.QuadPart;
3610 off += pBuildPagingBuffer->Transfer.TransferOffset;
3611 pBody->Dst.offVramBuf = off + cbTransfered;
3612 pBody->fFlags |= VBOXVDMACMD_DMA_BPB_TRANSFER_F_DST_VRAMOFFSET;
3613 }
3614 else
3615 {
3616 UINT index = pBuildPagingBuffer->Transfer.MdlOffset + (UINT)(cbTransfered>>12);
3617 pBody->Dst.phBuf = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Destination.pMdl)[index] << 12;
3618 PFN_NUMBER num = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Destination.pMdl)[index];
3619 cDstPages = 1;
3620 for (UINT i = 1; i < ((cbTransferSize - cbTransfered + 0xfff) >> 12); ++i)
3621 {
3622 PFN_NUMBER cur = MmGetMdlPfnArray(pBuildPagingBuffer->Transfer.Destination.pMdl)[index+i];
3623 if(cur != ++num)
3624 {
3625 cDstPages+= i-1;
3626 break;
3627 }
3628 }
3629 }
3630
3631 SIZE_T cbCurTransfer;
3632 cbCurTransfer = RT_MIN(cbTransferSize - cbTransfered, cSrcPages << 12);
3633 cbCurTransfer = RT_MIN(cbCurTransfer, cDstPages << 12);
3634
3635 pBody->cbTransferSize = (UINT)cbCurTransfer;
3636 Assert(!(cbCurTransfer & 0xfff));
3637
3638 int rc = vboxVdmaCBufDrSubmitSynch(pDevExt, &pDevExt->u.primary.Vdma, pDr);
3639 AssertRC(rc);
3640 if (RT_SUCCESS(rc))
3641 {
3642 Status = STATUS_SUCCESS;
3643 cbTransfered += cbCurTransfer;
3644 }
3645 else
3646 Status = STATUS_UNSUCCESSFUL;
3647 } while (cbTransfered < cbTransferSize);
3648 Assert(cbTransfered == cbTransferSize);
3649 vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
3650 }
3651 else
3652 {
3653 /* @todo: try flushing.. */
3654 LOGREL(("vboxVdmaCBufDrCreate returned NULL"));
3655 Status = STATUS_INSUFFICIENT_RESOURCES;
3656 }
3657#endif
3658#endif /* #ifdef VBOX_WITH_VDMA */
3659 break;
3660 }
3661 case DXGK_OPERATION_FILL:
3662 {
3663 cbCmdDma = VBOXWDDM_DUMMY_DMABUFFER_SIZE;
3664 Assert(pBuildPagingBuffer->Fill.FillPattern == 0);
3665 PVBOXWDDM_ALLOCATION pAlloc = (PVBOXWDDM_ALLOCATION)pBuildPagingBuffer->Fill.hAllocation;
3666// pBuildPagingBuffer->pDmaBuffer = (uint8_t*)pBuildPagingBuffer->pDmaBuffer + VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_BPB_FILL);
3667 break;
3668 }
3669 case DXGK_OPERATION_DISCARD_CONTENT:
3670 {
3671// AssertBreakpoint();
3672 break;
3673 }
3674 default:
3675 {
3676 WARN(("unsupported op (%d)", pBuildPagingBuffer->Operation));
3677 break;
3678 }
3679 }
3680
3681 if (cbCmdDma)
3682 {
3683 pBuildPagingBuffer->pDmaBuffer = ((uint8_t*)pBuildPagingBuffer->pDmaBuffer) + cbCmdDma;
3684 }
3685
3686 LOGF(("LEAVE, context(0x%x)", hAdapter));
3687
3688 return Status;
3689
3690}
3691
3692NTSTATUS
3693APIENTRY
3694DxgkDdiSetPalette(
3695 CONST HANDLE hAdapter,
3696 CONST DXGKARG_SETPALETTE* pSetPalette
3697 )
3698{
3699 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3700
3701 AssertBreakpoint();
3702 /* @todo: fixme: implement */
3703
3704 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3705
3706 return STATUS_SUCCESS;
3707}
3708
3709BOOL vboxWddmPointerCopyColorData(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVIDEO_POINTER_ATTRIBUTES pPointerAttributes)
3710{
3711 ULONG srcMaskW, srcMaskH;
3712 ULONG dstBytesPerLine;
3713 ULONG x, y;
3714 BYTE *pSrc, *pDst, bit;
3715
3716 srcMaskW = pSetPointerShape->Width;
3717 srcMaskH = pSetPointerShape->Height;
3718
3719 /* truncate masks if we exceed supported size */
3720 pPointerAttributes->Width = min(srcMaskW, VBOXWDDM_C_POINTER_MAX_WIDTH);
3721 pPointerAttributes->Height = min(srcMaskH, VBOXWDDM_C_POINTER_MAX_HEIGHT);
3722 pPointerAttributes->WidthInBytes = pPointerAttributes->Width * 4;
3723
3724 /* cnstruct and mask from alpha color channel */
3725 pSrc = (PBYTE)pSetPointerShape->pPixels;
3726 pDst = pPointerAttributes->Pixels;
3727 dstBytesPerLine = (pPointerAttributes->Width+7)/8;
3728
3729 /* sanity check */
3730 uint32_t cbData = RT_ALIGN_T(dstBytesPerLine*pPointerAttributes->Height, 4, ULONG)+
3731 pPointerAttributes->Height*pPointerAttributes->WidthInBytes;
3732 uint32_t cbPointerAttributes = RT_OFFSETOF(VIDEO_POINTER_ATTRIBUTES, Pixels[cbData]);
3733 Assert(VBOXWDDM_POINTER_ATTRIBUTES_SIZE >= cbPointerAttributes);
3734 if (VBOXWDDM_POINTER_ATTRIBUTES_SIZE < cbPointerAttributes)
3735 {
3736 LOGREL(("VBOXWDDM_POINTER_ATTRIBUTES_SIZE(%d) < cbPointerAttributes(%d)", VBOXWDDM_POINTER_ATTRIBUTES_SIZE, cbPointerAttributes));
3737 return FALSE;
3738 }
3739
3740 memset(pDst, 0xFF, dstBytesPerLine*pPointerAttributes->Height);
3741 for (y=0; y<pPointerAttributes->Height; ++y)
3742 {
3743 for (x=0, bit=7; x<pPointerAttributes->Width; ++x, --bit)
3744 {
3745 if (0xFF==bit) bit=7;
3746
3747 if (pSrc[y*pSetPointerShape->Pitch + x*4 + 3] > 0x7F)
3748 {
3749 pDst[y*dstBytesPerLine + x/8] &= ~RT_BIT(bit);
3750 }
3751 }
3752 }
3753
3754 /* copy 32bpp to XOR DIB, it start in pPointerAttributes->Pixels should be 4bytes aligned */
3755 pSrc = (BYTE*)pSetPointerShape->pPixels;
3756 pDst = pPointerAttributes->Pixels + RT_ALIGN_T(dstBytesPerLine*pPointerAttributes->Height, 4, ULONG);
3757 dstBytesPerLine = pPointerAttributes->Width * 4;
3758
3759 for (y=0; y<pPointerAttributes->Height; ++y)
3760 {
3761 memcpy(pDst+y*dstBytesPerLine, pSrc+y*pSetPointerShape->Pitch, dstBytesPerLine);
3762 }
3763
3764 return TRUE;
3765}
3766
3767BOOL vboxWddmPointerCopyMonoData(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVIDEO_POINTER_ATTRIBUTES pPointerAttributes)
3768{
3769 ULONG srcMaskW, srcMaskH;
3770 ULONG dstBytesPerLine;
3771 ULONG x, y;
3772 BYTE *pSrc, *pDst, bit;
3773
3774 srcMaskW = pSetPointerShape->Width;
3775 srcMaskH = pSetPointerShape->Height;
3776
3777 /* truncate masks if we exceed supported size */
3778 pPointerAttributes->Width = min(srcMaskW, VBOXWDDM_C_POINTER_MAX_WIDTH);
3779 pPointerAttributes->Height = min(srcMaskH, VBOXWDDM_C_POINTER_MAX_HEIGHT);
3780 pPointerAttributes->WidthInBytes = pPointerAttributes->Width * 4;
3781
3782 /* copy AND mask */
3783 pSrc = (PBYTE)pSetPointerShape->pPixels;
3784 pDst = pPointerAttributes->Pixels;
3785 dstBytesPerLine = (pPointerAttributes->Width+7)/8;
3786
3787 for (y=0; y<pPointerAttributes->Height; ++y)
3788 {
3789 memcpy(pDst+y*dstBytesPerLine, pSrc+y*pSetPointerShape->Pitch, dstBytesPerLine);
3790 }
3791
3792 /* convert XOR mask to RGB0 DIB, it start in pPointerAttributes->Pixels should be 4bytes aligned */
3793 pSrc = (BYTE*)pSetPointerShape->pPixels + srcMaskH*pSetPointerShape->Pitch;
3794 pDst = pPointerAttributes->Pixels + RT_ALIGN_T(dstBytesPerLine*pPointerAttributes->Height, 4, ULONG);
3795 dstBytesPerLine = pPointerAttributes->Width * 4;
3796
3797 for (y=0; y<pPointerAttributes->Height; ++y)
3798 {
3799 for (x=0, bit=7; x<pPointerAttributes->Width; ++x, --bit)
3800 {
3801 if (0xFF==bit) bit=7;
3802
3803 *(ULONG*)&pDst[y*dstBytesPerLine+x*4] = (pSrc[y*pSetPointerShape->Pitch+x/8] & RT_BIT(bit)) ? 0x00FFFFFF : 0;
3804 }
3805 }
3806
3807 return TRUE;
3808}
3809
3810static BOOLEAN vboxVddmPointerShapeToAttributes(CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape, PVBOXWDDM_POINTER_INFO pPointerInfo)
3811{
3812 PVIDEO_POINTER_ATTRIBUTES pPointerAttributes = &pPointerInfo->Attributes.data;
3813 /* pPointerAttributes maintains the visibility state, clear all except visibility */
3814 pPointerAttributes->Enable &= VBOX_MOUSE_POINTER_VISIBLE;
3815
3816 Assert(pSetPointerShape->Flags.Value == 1 || pSetPointerShape->Flags.Value == 2);
3817 if (pSetPointerShape->Flags.Color)
3818 {
3819 if (vboxWddmPointerCopyColorData(pSetPointerShape, pPointerAttributes))
3820 {
3821 pPointerAttributes->Flags = VIDEO_MODE_COLOR_POINTER;
3822 pPointerAttributes->Enable |= VBOX_MOUSE_POINTER_ALPHA;
3823 }
3824 else
3825 {
3826 LOGREL(("vboxWddmPointerCopyColorData failed"));
3827 AssertBreakpoint();
3828 return FALSE;
3829 }
3830
3831 }
3832 else if (pSetPointerShape->Flags.Monochrome)
3833 {
3834 if (vboxWddmPointerCopyMonoData(pSetPointerShape, pPointerAttributes))
3835 {
3836 pPointerAttributes->Flags = VIDEO_MODE_MONO_POINTER;
3837 }
3838 else
3839 {
3840 LOGREL(("vboxWddmPointerCopyMonoData failed"));
3841 AssertBreakpoint();
3842 return FALSE;
3843 }
3844 }
3845 else
3846 {
3847 LOGREL(("unsupported pointer type Flags.Value(0x%x)", pSetPointerShape->Flags.Value));
3848 AssertBreakpoint();
3849 return FALSE;
3850 }
3851
3852 pPointerAttributes->Enable |= VBOX_MOUSE_POINTER_SHAPE;
3853
3854 /*
3855 * The hot spot coordinates and alpha flag will be encoded in the pPointerAttributes::Enable field.
3856 * High word will contain hot spot info and low word - flags.
3857 */
3858 pPointerAttributes->Enable |= (pSetPointerShape->YHot & 0xFF) << 24;
3859 pPointerAttributes->Enable |= (pSetPointerShape->XHot & 0xFF) << 16;
3860
3861 return TRUE;
3862}
3863
3864NTSTATUS
3865APIENTRY
3866DxgkDdiSetPointerPosition(
3867 CONST HANDLE hAdapter,
3868 CONST DXGKARG_SETPOINTERPOSITION* pSetPointerPosition)
3869{
3870// LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3871
3872 vboxVDbgBreakFv();
3873
3874 /* mouse integration is ON */
3875 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3876 PVBOXWDDM_POINTER_INFO pPointerInfo = &pDevExt->aSources[pSetPointerPosition->VidPnSourceId].PointerInfo;
3877 PVBOXWDDM_GLOBAL_POINTER_INFO pGlobalPointerInfo = &pDevExt->PointerInfo;
3878 PVIDEO_POINTER_ATTRIBUTES pPointerAttributes = &pPointerInfo->Attributes.data;
3879 BOOLEAN fScreenVisState = !!(pPointerAttributes->Enable & VBOX_MOUSE_POINTER_VISIBLE);
3880 BOOLEAN fVisStateChanged = FALSE;
3881 BOOLEAN fScreenChanged = pGlobalPointerInfo->iLastReportedScreen != pSetPointerPosition->VidPnSourceId;
3882
3883 if (pSetPointerPosition->Flags.Visible)
3884 {
3885 pPointerAttributes->Enable |= VBOX_MOUSE_POINTER_VISIBLE;
3886 if (!fScreenVisState)
3887 {
3888 fVisStateChanged = !!pGlobalPointerInfo->cVisible;
3889 ++pGlobalPointerInfo->cVisible;
3890 }
3891 }
3892 else
3893 {
3894 pPointerAttributes->Enable &= ~VBOX_MOUSE_POINTER_VISIBLE;
3895 if (fScreenVisState)
3896 {
3897 --pGlobalPointerInfo->cVisible;
3898 fVisStateChanged = !!pGlobalPointerInfo->cVisible;
3899 }
3900 }
3901
3902 pGlobalPointerInfo->iLastReportedScreen = pSetPointerPosition->VidPnSourceId;
3903
3904 if ((fVisStateChanged || fScreenChanged) && VBoxQueryHostWantsAbsolute())
3905 {
3906 if (fScreenChanged)
3907 {
3908 BOOLEAN bResult = VBoxMPCmnUpdatePointerShape(VBoxCommonFromDeviceExt(pDevExt), &pPointerInfo->Attributes.data, VBOXWDDM_POINTER_ATTRIBUTES_SIZE);
3909 Assert(bResult);
3910 }
3911 else
3912 {
3913 // tell the host to use the guest's pointer
3914 VIDEO_POINTER_ATTRIBUTES PointerAttributes;
3915
3916 /* Visible and No Shape means Show the pointer.
3917 * It is enough to init only this field.
3918 */
3919 PointerAttributes.Enable = pSetPointerPosition->Flags.Visible ? VBOX_MOUSE_POINTER_VISIBLE : 0;
3920
3921 BOOLEAN bResult = VBoxMPCmnUpdatePointerShape(VBoxCommonFromDeviceExt(pDevExt), &PointerAttributes, sizeof (PointerAttributes));
3922 Assert(bResult);
3923 }
3924 }
3925
3926// LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3927
3928 return STATUS_SUCCESS;
3929}
3930
3931NTSTATUS
3932APIENTRY
3933DxgkDdiSetPointerShape(
3934 CONST HANDLE hAdapter,
3935 CONST DXGKARG_SETPOINTERSHAPE* pSetPointerShape)
3936{
3937// LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3938
3939 vboxVDbgBreakFv();
3940
3941 NTSTATUS Status = STATUS_NOT_SUPPORTED;
3942
3943 if (VBoxQueryHostWantsAbsolute())
3944 {
3945 /* mouse integration is ON */
3946 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
3947 PVBOXWDDM_POINTER_INFO pPointerInfo = &pDevExt->aSources[pSetPointerShape->VidPnSourceId].PointerInfo;
3948 /* @todo: to avoid extra data copy and extra heap allocation,
3949 * need to maintain the pre-allocated HGSMI buffer and convert the data directly to it */
3950 if (vboxVddmPointerShapeToAttributes(pSetPointerShape, pPointerInfo))
3951 {
3952 pDevExt->PointerInfo.iLastReportedScreen = pSetPointerShape->VidPnSourceId;
3953 if (VBoxMPCmnUpdatePointerShape(VBoxCommonFromDeviceExt(pDevExt), &pPointerInfo->Attributes.data, VBOXWDDM_POINTER_ATTRIBUTES_SIZE))
3954 Status = STATUS_SUCCESS;
3955 else
3956 {
3957 AssertBreakpoint();
3958 LOGREL(("vboxUpdatePointerShape failed"));
3959 }
3960 }
3961 }
3962
3963// LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3964
3965 return Status;
3966}
3967
3968NTSTATUS
3969APIENTRY CALLBACK
3970DxgkDdiResetFromTimeout(
3971 CONST HANDLE hAdapter)
3972{
3973 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
3974
3975 AssertBreakpoint();
3976 /* @todo: fixme: implement */
3977
3978 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
3979
3980 return STATUS_SUCCESS;
3981}
3982
3983
3984/* the lpRgnData->Buffer comes to us as RECT
3985 * to avoid extra memcpy we cast it to PRTRECT assuming
3986 * they are identical */
3987AssertCompile(sizeof(RECT) == sizeof(RTRECT));
3988AssertCompile(RT_OFFSETOF(RECT, left) == RT_OFFSETOF(RTRECT, xLeft));
3989AssertCompile(RT_OFFSETOF(RECT, bottom) == RT_OFFSETOF(RTRECT, yBottom));
3990AssertCompile(RT_OFFSETOF(RECT, right) == RT_OFFSETOF(RTRECT, xRight));
3991AssertCompile(RT_OFFSETOF(RECT, top) == RT_OFFSETOF(RTRECT, yTop));
3992
3993NTSTATUS
3994APIENTRY
3995DxgkDdiEscape(
3996 CONST HANDLE hAdapter,
3997 CONST DXGKARG_ESCAPE* pEscape)
3998{
3999 PAGED_CODE();
4000
4001// LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
4002
4003 NTSTATUS Status = STATUS_NOT_SUPPORTED;
4004 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
4005 Assert(pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE));
4006 if (pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE))
4007 {
4008 PVBOXDISPIFESCAPE pEscapeHdr = (PVBOXDISPIFESCAPE)pEscape->pPrivateDriverData;
4009 switch (pEscapeHdr->escapeCode)
4010 {
4011#ifdef VBOX_WITH_CRHGSMI
4012 case VBOXESC_UHGSMI_SUBMIT:
4013 {
4014 if (pDevExt->fCmdVbvaEnabled)
4015 {
4016 WARN(("VBOXESC_UHGSMI_SUBMIT not supported for CmdVbva mode"));
4017 Status = STATUS_INVALID_PARAMETER;
4018 break;
4019 }
4020 /* submit VBOXUHGSMI command */
4021 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
4022 PVBOXDISPIFESCAPE_UHGSMI_SUBMIT pSubmit = (PVBOXDISPIFESCAPE_UHGSMI_SUBMIT)pEscapeHdr;
4023 Assert(pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_UHGSMI_SUBMIT)
4024 && pEscape->PrivateDriverDataSize == RT_OFFSETOF(VBOXDISPIFESCAPE_UHGSMI_SUBMIT, aBuffers[pEscapeHdr->u32CmdSpecific]));
4025 if (pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD)
4026 && pEscape->PrivateDriverDataSize == RT_OFFSETOF(VBOXDISPIFESCAPE_UHGSMI_SUBMIT, aBuffers[pEscapeHdr->u32CmdSpecific]))
4027 {
4028 Status = vboxVideoAMgrCtxAllocSubmit(pDevExt, &pContext->AllocContext, pEscapeHdr->u32CmdSpecific, pSubmit->aBuffers);
4029 Assert(Status == STATUS_SUCCESS);
4030 }
4031 else
4032 Status = STATUS_BUFFER_TOO_SMALL;
4033
4034 break;
4035 }
4036#endif
4037 case VBOXESC_UHGSMI_ALLOCATE:
4038 {
4039 /* allocate VBOXUHGSMI buffer */
4040 if (pDevExt->fCmdVbvaEnabled)
4041 {
4042 WARN(("VBOXESC_UHGSMI_ALLOCATE not supported for CmdVbva mode"));
4043 Status = STATUS_INVALID_PARAMETER;
4044 break;
4045 }
4046
4047 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
4048 PVBOXDISPIFESCAPE_UHGSMI_ALLOCATE pAlocate = (PVBOXDISPIFESCAPE_UHGSMI_ALLOCATE)pEscapeHdr;
4049 Assert(pEscape->PrivateDriverDataSize == sizeof (VBOXDISPIFESCAPE_UHGSMI_ALLOCATE));
4050 if (pEscape->PrivateDriverDataSize == sizeof (VBOXDISPIFESCAPE_UHGSMI_ALLOCATE))
4051 {
4052 Status = vboxVideoAMgrCtxAllocCreate(&pContext->AllocContext, &pAlocate->Alloc);
4053 Assert(Status == STATUS_SUCCESS);
4054 }
4055 else
4056 Status = STATUS_BUFFER_TOO_SMALL;
4057
4058 break;
4059 }
4060
4061 case VBOXESC_UHGSMI_DEALLOCATE:
4062 {
4063 if (pDevExt->fCmdVbvaEnabled)
4064 {
4065 WARN(("VBOXESC_UHGSMI_DEALLOCATE not supported for CmdVbva mode"));
4066 Status = STATUS_INVALID_PARAMETER;
4067 break;
4068 }
4069 /* deallocate VBOXUHGSMI buffer */
4070 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
4071 PVBOXDISPIFESCAPE_UHGSMI_DEALLOCATE pDealocate = (PVBOXDISPIFESCAPE_UHGSMI_DEALLOCATE)pEscapeHdr;
4072 Assert(pEscape->PrivateDriverDataSize == sizeof (VBOXDISPIFESCAPE_UHGSMI_DEALLOCATE));
4073 if (pEscape->PrivateDriverDataSize == sizeof (VBOXDISPIFESCAPE_UHGSMI_DEALLOCATE))
4074 {
4075 Status = vboxVideoAMgrCtxAllocDestroy(&pContext->AllocContext, pDealocate->hAlloc);
4076 Assert(Status == STATUS_SUCCESS);
4077 }
4078 else
4079 Status = STATUS_BUFFER_TOO_SMALL;
4080
4081 break;
4082 }
4083
4084 case VBOXESC_GETVBOXVIDEOCMCMD:
4085 {
4086 if (pDevExt->fCmdVbvaEnabled || pDevExt->fTexPresentEnabled)
4087 {
4088 WARN(("VBOXESC_GETVBOXVIDEOCMCMD not supported for CmdVbva or TexPresent mode"));
4089 Status = STATUS_INVALID_PARAMETER;
4090 break;
4091 }
4092
4093 /* get the list of r0->r3 commands (d3d window visible regions reporting )*/
4094 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
4095 PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD pRegions = (PVBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD)pEscapeHdr;
4096 Assert(pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD));
4097 if (pEscape->PrivateDriverDataSize >= sizeof (VBOXDISPIFESCAPE_GETVBOXVIDEOCMCMD))
4098 {
4099 if (pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D)
4100 {
4101 Status = vboxVideoCmEscape(&pContext->CmContext, pRegions, pEscape->PrivateDriverDataSize);
4102 Assert(Status == STATUS_SUCCESS);
4103 }
4104 else
4105 {
4106 WARN(("VBOXESC_GETVBOXVIDEOCMCMD recieved invalid context type %d", pContext->enmType));
4107 Status = STATUS_INVALID_PARAMETER;
4108 }
4109 }
4110 else
4111 Status = STATUS_BUFFER_TOO_SMALL;
4112
4113 break;
4114 }
4115
4116 case VBOXESC_CRHGSMICTLCON_CALL:
4117 {
4118 if (pDevExt->fCmdVbvaEnabled)
4119 {
4120 WARN(("VBOXESC_CRHGSMICTLCON_CALL not supported for CmdVbva mode"));
4121 Status = STATUS_INVALID_PARAMETER;
4122 break;
4123 }
4124
4125 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
4126 PVBOXDISPIFESCAPE_CRHGSMICTLCON_CALL pCall = (PVBOXDISPIFESCAPE_CRHGSMICTLCON_CALL)pEscapeHdr;
4127 if (pEscape->PrivateDriverDataSize >= sizeof (*pCall))
4128 {
4129 /* this is true due to the above condition */
4130 Assert(pEscape->PrivateDriverDataSize > RT_OFFSETOF(VBOXDISPIFESCAPE_CRHGSMICTLCON_CALL, CallInfo));
4131 int rc = VBoxMpCrCtlConCallUserData(&pDevExt->CrCtlCon, &pCall->CallInfo, pEscape->PrivateDriverDataSize - RT_OFFSETOF(VBOXDISPIFESCAPE_CRHGSMICTLCON_CALL, CallInfo));
4132 pEscapeHdr->u32CmdSpecific = (uint32_t)rc;
4133 Status = STATUS_SUCCESS; /* <- always return success here, otherwise the private data buffer modifications
4134 * i.e. rc status stored in u32CmdSpecific will not be copied to user mode */
4135 if (!RT_SUCCESS(rc))
4136 WARN(("VBoxMpCrUmCtlConCall failed, rc(%d)", rc));
4137 }
4138 else
4139 {
4140 WARN(("buffer too small!"));
4141 Status = STATUS_BUFFER_TOO_SMALL;
4142 }
4143
4144 break;
4145 }
4146
4147 case VBOXESC_CRHGSMICTLCON_GETCLIENTID:
4148 {
4149 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
4150 if (pEscape->PrivateDriverDataSize == sizeof (*pEscapeHdr))
4151 {
4152 pEscapeHdr->u32CmdSpecific = pContext->u32CrConClientID;
4153 Status = STATUS_SUCCESS;
4154 }
4155 else
4156 {
4157 WARN(("unexpected buffer size!"));
4158 Status = STATUS_INVALID_PARAMETER;
4159 }
4160
4161 break;
4162 }
4163
4164 case VBOXESC_SETVISIBLEREGION:
4165 {
4166 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
4167#ifdef VBOX_DISPIF_WITH_OPCONTEXT
4168 if (!pContext)
4169 {
4170 WARN(("VBOXESC_SETVISIBLEREGION no context supplied!"));
4171 Status = STATUS_INVALID_PARAMETER;
4172 break;
4173 }
4174
4175 if (pContext->enmType != VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_SEAMLESS)
4176 {
4177 WARN(("VBOXESC_SETVISIBLEREGION invalid context supplied %d!", pContext->enmType));
4178 Status = STATUS_INVALID_PARAMETER;
4179 break;
4180 }
4181#endif
4182 /* visible regions for seamless */
4183 LPRGNDATA lpRgnData = VBOXDISPIFESCAPE_DATA(pEscapeHdr, RGNDATA);
4184 uint32_t cbData = VBOXDISPIFESCAPE_DATA_SIZE(pEscape->PrivateDriverDataSize);
4185 uint32_t cbRects = cbData - RT_OFFSETOF(RGNDATA, Buffer);
4186 /* the lpRgnData->Buffer comes to us as RECT
4187 * to avoid extra memcpy we cast it to PRTRECT assuming
4188 * they are identical
4189 * see AssertCompile's above */
4190
4191 RTRECT *pRect = (RTRECT *)&lpRgnData->Buffer;
4192
4193 uint32_t cRects = cbRects/sizeof(RTRECT);
4194 int rc;
4195
4196 LOG(("IOCTL_VIDEO_VBOX_SETVISIBLEREGION cRects=%d", cRects));
4197 Assert(cbRects >= sizeof(RTRECT)
4198 && cbRects == cRects*sizeof(RTRECT)
4199 && cRects == lpRgnData->rdh.nCount);
4200 if ( cbRects >= sizeof(RTRECT)
4201 && cbRects == cRects*sizeof(RTRECT)
4202 && cRects == lpRgnData->rdh.nCount)
4203 {
4204 /*
4205 * Inform the host about the visible region
4206 */
4207 VMMDevVideoSetVisibleRegion *req = NULL;
4208
4209 rc = VbglGRAlloc ((VMMDevRequestHeader **)&req,
4210 sizeof (VMMDevVideoSetVisibleRegion) + (cRects-1)*sizeof(RTRECT),
4211 VMMDevReq_VideoSetVisibleRegion);
4212 AssertRC(rc);
4213 if (RT_SUCCESS(rc))
4214 {
4215 req->cRect = cRects;
4216 memcpy(&req->Rect, pRect, cRects*sizeof(RTRECT));
4217
4218 rc = VbglGRPerform (&req->header);
4219 AssertRC(rc);
4220 if (RT_SUCCESS(rc))
4221 Status = STATUS_SUCCESS;
4222 else
4223 {
4224 WARN(("VbglGRPerform failed rc (%d)", rc));
4225 Status = STATUS_UNSUCCESSFUL;
4226 }
4227 }
4228 else
4229 {
4230 WARN(("VbglGRAlloc failed rc (%d)", rc));
4231 Status = STATUS_UNSUCCESSFUL;
4232 }
4233 }
4234 else
4235 {
4236 WARN(("VBOXESC_SETVISIBLEREGION: incorrect buffer size (%d), reported count (%d)", cbRects, lpRgnData->rdh.nCount));
4237 Status = STATUS_INVALID_PARAMETER;
4238 }
4239 break;
4240 }
4241 case VBOXESC_ISVRDPACTIVE:
4242 /* @todo: implement */
4243 Status = STATUS_SUCCESS;
4244 break;
4245 case VBOXESC_SCREENLAYOUT:
4246 {
4247 /* set screen layout (unused currently) */
4248 if (pEscape->PrivateDriverDataSize < sizeof (VBOXDISPIFESCAPE_SCREENLAYOUT))
4249 {
4250 WARN(("VBOXESC_SCREENLAYOUT: incorrect buffer size (%d) < sizeof (VBOXDISPIFESCAPE_SCREENLAYOUT) (%d)",
4251 pEscape->PrivateDriverDataSize, sizeof (VBOXDISPIFESCAPE_SCREENLAYOUT)));
4252 Status = STATUS_INVALID_PARAMETER;
4253 break;
4254 }
4255
4256 PVBOXDISPIFESCAPE_SCREENLAYOUT pLo = (PVBOXDISPIFESCAPE_SCREENLAYOUT)pEscapeHdr;
4257 if (pLo->ScreenLayout.cScreens > (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays)
4258 {
4259 WARN(("VBOXESC_SCREENLAYOUT: number of screens too big (%d), should be <= (%d)",
4260 pLo->ScreenLayout.cScreens, VBoxCommonFromDeviceExt(pDevExt)->cDisplays));
4261 Status = STATUS_INVALID_PARAMETER;
4262 break;
4263 }
4264
4265 for (UINT i = 0; i < pLo->ScreenLayout.cScreens; ++i)
4266 {
4267 PVBOXSCREENLAYOUT_ELEMENT pEl = &pLo->ScreenLayout.aScreens[i];
4268 Assert(pEl->VidPnSourceId < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
4269 if (pEl->VidPnSourceId < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays)
4270 {
4271 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pEl->VidPnSourceId];
4272 NTSTATUS tmpStatus = vboxWddmGhDisplayUpdateScreenPos(pDevExt, pSource, &pEl->pos);
4273 Assert(tmpStatus == STATUS_SUCCESS);
4274 }
4275 }
4276
4277 Status = STATUS_SUCCESS;
4278 break;
4279 }
4280 case VBOXESC_SETCTXHOSTID:
4281 {
4282 /* set swapchain information */
4283 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
4284 if (!pContext)
4285 {
4286 WARN(("VBOXESC_SETCTXHOSTID: no context specified"));
4287 Status = STATUS_INVALID_PARAMETER;
4288 break;
4289 }
4290
4291 if (pEscape->PrivateDriverDataSize != sizeof (VBOXDISPIFESCAPE))
4292 {
4293 WARN(("VBOXESC_SETCTXHOSTID: invalid data size %d", pEscape->PrivateDriverDataSize));
4294 Status = STATUS_INVALID_PARAMETER;
4295 break;
4296 }
4297
4298 int32_t hostID = (int32_t)pEscapeHdr->u32CmdSpecific;
4299 if (hostID <= 0)
4300 {
4301 WARN(("VBOXESC_SETCTXHOSTID: invalid hostID %d", hostID));
4302 Status = STATUS_INVALID_PARAMETER;
4303 break;
4304 }
4305
4306 if (pContext->hostID)
4307 {
4308 WARN(("VBOXESC_SETCTXHOSTID: context already has hostID specified"));
4309 Status = STATUS_INVALID_PARAMETER;
4310 break;
4311 }
4312
4313 pContext->hostID = hostID;
4314 Status = STATUS_SUCCESS;
4315 break;
4316 }
4317 case VBOXESC_SWAPCHAININFO:
4318 {
4319 /* set swapchain information */
4320 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
4321 Status = vboxWddmSwapchainCtxEscape(pDevExt, pContext, (PVBOXDISPIFESCAPE_SWAPCHAININFO)pEscapeHdr, pEscape->PrivateDriverDataSize);
4322 Assert(Status == STATUS_SUCCESS);
4323 break;
4324 }
4325 case VBOXESC_REINITVIDEOMODES:
4326 {
4327 if (!pEscape->Flags.HardwareAccess)
4328 {
4329 WARN(("VBOXESC_REINITVIDEOMODESBYMASK called without HardwareAccess flag set, failing"));
4330 Status = STATUS_INVALID_PARAMETER;
4331 break;
4332 }
4333
4334#ifdef VBOX_DISPIF_WITH_OPCONTEXT
4335 /* win8.1 does not allow context-based escapes for display-only mode */
4336 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
4337 if (!pContext)
4338 {
4339 WARN(("VBOXESC_REINITVIDEOMODES no context supplied!"));
4340 Status = STATUS_INVALID_PARAMETER;
4341 break;
4342 }
4343
4344 if (pContext->enmType != VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_RESIZE)
4345 {
4346 WARN(("VBOXESC_REINITVIDEOMODES invalid context supplied %d!", pContext->enmType));
4347 Status = STATUS_INVALID_PARAMETER;
4348 break;
4349 }
4350#endif
4351
4352 WARN(("VBOXESC_REINITVIDEOMODESBYMASK should be called instead"));
4353 VBoxWddmUpdateVideoModesInfoByMask(pDevExt, NULL);
4354 Status = STATUS_SUCCESS;
4355 break;
4356 }
4357 case VBOXESC_REINITVIDEOMODESBYMASK:
4358 {
4359 if (!pEscape->Flags.HardwareAccess)
4360 {
4361 WARN(("VBOXESC_REINITVIDEOMODESBYMASK called without HardwareAccess flag set, failing"));
4362 Status = STATUS_INVALID_PARAMETER;
4363 break;
4364 }
4365
4366#ifdef VBOX_DISPIF_WITH_OPCONTEXT
4367 /* win8.1 does not allow context-based escapes for display-only mode */
4368 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
4369 if (!pContext)
4370 {
4371 WARN(("VBOXESC_REINITVIDEOMODESBYMASK no context supplied!"));
4372 Status = STATUS_INVALID_PARAMETER;
4373 break;
4374 }
4375
4376 if (pContext->enmType != VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_RESIZE)
4377 {
4378 WARN(("VBOXESC_REINITVIDEOMODESBYMASK invalid context supplied %d!", pContext->enmType));
4379 Status = STATUS_INVALID_PARAMETER;
4380 break;
4381 }
4382#endif
4383
4384 if (pEscape->PrivateDriverDataSize != sizeof (VBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK))
4385 {
4386 WARN(("invalid private driver size %d", pEscape->PrivateDriverDataSize));
4387 Status = STATUS_INVALID_PARAMETER;
4388 break;
4389 }
4390 LOG(("=> VBOXESC_REINITVIDEOMODESBYMASK"));
4391 PVBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK pData = (PVBOXDISPIFESCAPE_REINITVIDEOMODESBYMASK)pEscapeHdr;
4392 VBoxWddmUpdateVideoModesInfoByMask(pDevExt, pData->ScreenMask);
4393 Status = STATUS_SUCCESS;
4394 LOG(("<= VBOXESC_REINITVIDEOMODESBYMASK"));
4395 break;
4396 }
4397 case VBOXESC_CONFIGURETARGETS:
4398 {
4399 LOG(("=> VBOXESC_CONFIGURETARGETS"));
4400
4401 if (!pEscape->Flags.HardwareAccess)
4402 {
4403 WARN(("VBOXESC_CONFIGURETARGETS called without HardwareAccess flag set, failing"));
4404 Status = STATUS_INVALID_PARAMETER;
4405 break;
4406 }
4407
4408#ifdef VBOX_DISPIF_WITH_OPCONTEXT
4409 /* win8.1 does not allow context-based escapes for display-only mode */
4410 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)pEscape->hContext;
4411 if (!pContext)
4412 {
4413 WARN(("VBOXESC_CONFIGURETARGETS no context supplied!"));
4414 Status = STATUS_INVALID_PARAMETER;
4415 break;
4416 }
4417
4418 if (pContext->enmType != VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_RESIZE)
4419 {
4420 WARN(("VBOXESC_CONFIGURETARGETS invalid context supplied %d!", pContext->enmType));
4421 Status = STATUS_INVALID_PARAMETER;
4422 break;
4423 }
4424#endif
4425
4426 if (pEscape->PrivateDriverDataSize != sizeof (*pEscapeHdr))
4427 {
4428 WARN(("VBOXESC_CONFIGURETARGETS invalid private driver size %d", pEscape->PrivateDriverDataSize));
4429 Status = STATUS_INVALID_PARAMETER;
4430 break;
4431 }
4432
4433 if (pEscapeHdr->u32CmdSpecific)
4434 {
4435 WARN(("VBOXESC_CONFIGURETARGETS invalid command %d", pEscapeHdr->u32CmdSpecific));
4436 Status = STATUS_INVALID_PARAMETER;
4437 break;
4438 }
4439
4440 HANDLE hKey = NULL;
4441 WCHAR aNameBuf[100];
4442 uint32_t cAdjusted = 0;
4443
4444 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
4445 {
4446 VBOXWDDM_TARGET *pTarget = &pDevExt->aTargets[i];
4447 if (pTarget->fConfigured)
4448 continue;
4449
4450 pTarget->fConfigured = true;
4451
4452 if (!pTarget->fConnected)
4453 {
4454 Status = vboxWddmChildStatusConnect(pDevExt, (uint32_t)i, TRUE);
4455 if (NT_SUCCESS(Status))
4456 ++cAdjusted;
4457 else
4458 WARN(("VBOXESC_CONFIGURETARGETS vboxWddmChildStatusConnectSecondaries failed Status 0x%x\n", Status));
4459 }
4460
4461 if (!hKey)
4462 {
4463 Status = IoOpenDeviceRegistryKey(pDevExt->pPDO, PLUGPLAY_REGKEY_DRIVER, GENERIC_WRITE, &hKey);
4464 if (!NT_SUCCESS(Status))
4465 {
4466 WARN(("VBOXESC_CONFIGURETARGETS IoOpenDeviceRegistryKey failed, Status = 0x%x", Status));
4467 hKey = NULL;
4468 continue;
4469 }
4470 }
4471
4472 Assert(hKey);
4473
4474 swprintf(aNameBuf, L"%s%d", VBOXWDDM_REG_DRV_DISPFLAGS_PREFIX, i);
4475 Status = vboxWddmRegSetValueDword(hKey, aNameBuf, VBOXWDDM_CFG_DRVTARGET_CONNECTED);
4476 if (!NT_SUCCESS(Status))
4477 WARN(("VBOXESC_CONFIGURETARGETS vboxWddmRegSetValueDword (%d) failed Status 0x%x\n", aNameBuf, Status));
4478
4479 }
4480
4481 if (hKey)
4482 {
4483 NTSTATUS tmpStatus = ZwClose(hKey);
4484 Assert(tmpStatus == STATUS_SUCCESS);
4485 }
4486
4487 pEscapeHdr->u32CmdSpecific = cAdjusted;
4488
4489 Status = STATUS_SUCCESS;
4490
4491 LOG(("<= VBOXESC_CONFIGURETARGETS"));
4492 break;
4493 }
4494 case VBOXESC_ADJUSTVIDEOMODES:
4495 {
4496 if (!pEscape->Flags.HardwareAccess)
4497 {
4498 WARN(("VBOXESC_ADJUSTVIDEOMODES called without HardwareAccess flag set, failing"));
4499 Status = STATUS_INVALID_PARAMETER;
4500 break;
4501 }
4502
4503 uint32_t cModes = pEscapeHdr->u32CmdSpecific;
4504 if (cModes > VBOXWDDM_TRAILARRAY_MAXELEMENTSU32(VBOXDISPIFESCAPE_ADJUSTVIDEOMODES, aScreenInfos)
4505 || pEscape->PrivateDriverDataSize != RT_OFFSETOF(VBOXDISPIFESCAPE_ADJUSTVIDEOMODES, aScreenInfos[cModes]))
4506 {
4507 WARN(("invalid modes count passed"));
4508 Status = STATUS_INVALID_PARAMETER;
4509 break;
4510 }
4511
4512 PVBOXDISPIFESCAPE_ADJUSTVIDEOMODES pPodesInfo = (PVBOXDISPIFESCAPE_ADJUSTVIDEOMODES)pEscapeHdr;
4513 VBoxWddmAdjustModes(pDevExt, cModes, pPodesInfo->aScreenInfos);
4514 Status = STATUS_SUCCESS;
4515 break;
4516 }
4517 case VBOXESC_SETALLOCHOSTID:
4518 {
4519 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)pEscape->hDevice;
4520 if (!pDevice)
4521 {
4522 WARN(("VBOXESC_SETALLOCHOSTID called without no device specified, failing"));
4523 Status = STATUS_INVALID_PARAMETER;
4524 break;
4525 }
4526
4527 if (pEscape->PrivateDriverDataSize != sizeof (VBOXDISPIFESCAPE_SETALLOCHOSTID))
4528 {
4529 WARN(("invalid buffer size for VBOXDISPIFESCAPE_SHRC_REF, was(%d), but expected (%d)",
4530 pEscape->PrivateDriverDataSize, sizeof (VBOXDISPIFESCAPE_SHRC_REF)));
4531 Status = STATUS_INVALID_PARAMETER;
4532 break;
4533 }
4534
4535 PVBOXDISPIFESCAPE_SETALLOCHOSTID pSetHostID = (PVBOXDISPIFESCAPE_SETALLOCHOSTID)pEscapeHdr;
4536 PVBOXWDDM_ALLOCATION pAlloc = vboxWddmGetAllocationFromHandle(pDevExt, (D3DKMT_HANDLE)pSetHostID->hAlloc);
4537 if (!pAlloc)
4538 {
4539 WARN(("failed to get allocation from handle"));
4540 Status = STATUS_INVALID_PARAMETER;
4541 break;
4542 }
4543
4544 if (pAlloc->enmType != VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE)
4545 {
4546 WARN(("setHostID: invalid allocation type: %d", pAlloc->enmType));
4547 Status = STATUS_INVALID_PARAMETER;
4548 break;
4549 }
4550
4551 pSetHostID->rc = VBoxWddmOaSetHostID(pDevice, pAlloc, pSetHostID->hostID, &pSetHostID->EscapeHdr.u32CmdSpecific);
4552 Status = STATUS_SUCCESS;
4553 break;
4554 }
4555 case VBOXESC_SHRC_ADDREF:
4556 case VBOXESC_SHRC_RELEASE:
4557 {
4558 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)pEscape->hDevice;
4559 if (!pDevice)
4560 {
4561 WARN(("VBOXESC_SHRC_ADDREF|VBOXESC_SHRC_RELEASE called without no device specified, failing"));
4562 Status = STATUS_INVALID_PARAMETER;
4563 break;
4564 }
4565
4566 /* query whether the allocation represanted by the given [wine-generated] shared resource handle still exists */
4567 if (pEscape->PrivateDriverDataSize != sizeof (VBOXDISPIFESCAPE_SHRC_REF))
4568 {
4569 WARN(("invalid buffer size for VBOXDISPIFESCAPE_SHRC_REF, was(%d), but expected (%d)",
4570 pEscape->PrivateDriverDataSize, sizeof (VBOXDISPIFESCAPE_SHRC_REF)));
4571 Status = STATUS_INVALID_PARAMETER;
4572 break;
4573 }
4574
4575 PVBOXDISPIFESCAPE_SHRC_REF pShRcRef = (PVBOXDISPIFESCAPE_SHRC_REF)pEscapeHdr;
4576 PVBOXWDDM_ALLOCATION pAlloc = vboxWddmGetAllocationFromHandle(pDevExt, (D3DKMT_HANDLE)pShRcRef->hAlloc);
4577 if (!pAlloc)
4578 {
4579 WARN(("failed to get allocation from handle"));
4580 Status = STATUS_INVALID_PARAMETER;
4581 break;
4582 }
4583
4584 PVBOXWDDM_OPENALLOCATION pOa = VBoxWddmOaSearch(pDevice, pAlloc);
4585 if (!pOa)
4586 {
4587 WARN(("failed to get open allocation from alloc"));
4588 Status = STATUS_INVALID_PARAMETER;
4589 break;
4590 }
4591
4592 Assert(pAlloc->cShRcRefs >= pOa->cShRcRefs);
4593
4594 if (pEscapeHdr->escapeCode == VBOXESC_SHRC_ADDREF)
4595 {
4596#ifdef DEBUG
4597 Assert(!pAlloc->fAssumedDeletion);
4598#endif
4599 ++pAlloc->cShRcRefs;
4600 ++pOa->cShRcRefs;
4601 }
4602 else
4603 {
4604 Assert(pAlloc->cShRcRefs);
4605 Assert(pOa->cShRcRefs);
4606 --pAlloc->cShRcRefs;
4607 --pOa->cShRcRefs;
4608#ifdef DEBUG
4609 Assert(!pAlloc->fAssumedDeletion);
4610 if (!pAlloc->cShRcRefs)
4611 {
4612 pAlloc->fAssumedDeletion = TRUE;
4613 }
4614#endif
4615 }
4616
4617 pShRcRef->EscapeHdr.u32CmdSpecific = pAlloc->cShRcRefs;
4618 Status = STATUS_SUCCESS;
4619 break;
4620 }
4621 case VBOXESC_ISANYX:
4622 {
4623 if (pEscape->PrivateDriverDataSize != sizeof (VBOXDISPIFESCAPE_ISANYX))
4624 {
4625 WARN(("invalid private driver size %d", pEscape->PrivateDriverDataSize));
4626 Status = STATUS_INVALID_PARAMETER;
4627 break;
4628 }
4629
4630 PVBOXDISPIFESCAPE_ISANYX pIsAnyX = (PVBOXDISPIFESCAPE_ISANYX)pEscapeHdr;
4631 pIsAnyX->u32IsAnyX = VBoxCommonFromDeviceExt(pDevExt)->fAnyX;
4632 Status = STATUS_SUCCESS;
4633 break;
4634 }
4635 case VBOXESC_DBGPRINT:
4636 {
4637 /* use RT_OFFSETOF instead of sizeof since sizeof will give an aligned size that might
4638 * be bigger than the VBOXDISPIFESCAPE_DBGPRINT with a data containing just a few chars */
4639 Assert(pEscape->PrivateDriverDataSize >= RT_OFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1]));
4640 /* only do DbgPrint when pEscape->PrivateDriverDataSize > RT_OFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1])
4641 * since == RT_OFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1]) means the buffer contains just \0,
4642 * i.e. no need to print it */
4643 if (pEscape->PrivateDriverDataSize > RT_OFFSETOF(VBOXDISPIFESCAPE_DBGPRINT, aStringBuf[1]))
4644 {
4645 PVBOXDISPIFESCAPE_DBGPRINT pDbgPrint = (PVBOXDISPIFESCAPE_DBGPRINT)pEscapeHdr;
4646 /* ensure the last char is \0*/
4647 *((uint8_t*)pDbgPrint + pEscape->PrivateDriverDataSize - 1) = '\0';
4648 if (g_VBoxLogUm & VBOXWDDM_CFG_LOG_UM_DBGPRINT)
4649 DbgPrint("%s\n", pDbgPrint->aStringBuf);
4650 if (g_VBoxLogUm & VBOXWDDM_CFG_LOG_UM_BACKDOOR)
4651 LOGREL_EXACT(("%s\n", pDbgPrint->aStringBuf));
4652 }
4653 Status = STATUS_SUCCESS;
4654 break;
4655 }
4656 case VBOXESC_DBGDUMPBUF:
4657 {
4658 Status = vboxUmdDumpBuf((PVBOXDISPIFESCAPE_DBGDUMPBUF)pEscapeHdr, pEscape->PrivateDriverDataSize);
4659 break;
4660 }
4661 default:
4662 WARN(("unsupported escape code (0x%x)", pEscapeHdr->escapeCode));
4663 break;
4664 }
4665 }
4666 else
4667 {
4668 WARN(("pEscape->PrivateDriverDataSize(%d) < (%d)", pEscape->PrivateDriverDataSize, sizeof (VBOXDISPIFESCAPE)));
4669 Status = STATUS_BUFFER_TOO_SMALL;
4670 }
4671
4672// LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
4673
4674 return Status;
4675}
4676
4677NTSTATUS
4678APIENTRY
4679DxgkDdiCollectDbgInfo(
4680 CONST HANDLE hAdapter,
4681 CONST DXGKARG_COLLECTDBGINFO* pCollectDbgInfo
4682 )
4683{
4684 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
4685
4686 AssertBreakpoint();
4687
4688 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
4689
4690 return STATUS_SUCCESS;
4691}
4692
4693typedef struct VBOXWDDM_QUERYCURFENCE_CB
4694{
4695 PVBOXMP_DEVEXT pDevExt;
4696 ULONG MessageNumber;
4697 ULONG uLastCompletedCmdFenceId;
4698} VBOXWDDM_QUERYCURFENCE_CB, *PVBOXWDDM_QUERYCURFENCE_CB;
4699
4700static BOOLEAN vboxWddmQueryCurrentFenceCb(PVOID Context)
4701{
4702 PVBOXWDDM_QUERYCURFENCE_CB pdc = (PVBOXWDDM_QUERYCURFENCE_CB)Context;
4703 BOOL bRc = DxgkDdiInterruptRoutineLegacy(pdc->pDevExt, pdc->MessageNumber);
4704 pdc->uLastCompletedCmdFenceId = pdc->pDevExt->u.primary.Vdma.uLastCompletedPagingBufferCmdFenceId;
4705 return bRc;
4706}
4707
4708static NTSTATUS
4709APIENTRY
4710DxgkDdiQueryCurrentFenceNew(
4711 CONST HANDLE hAdapter,
4712 DXGKARG_QUERYCURRENTFENCE* pCurrentFence)
4713{
4714 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
4715
4716 vboxVDbgBreakF();
4717
4718 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
4719 pCurrentFence->CurrentFence = VBoxCmdVbvaCheckCompleted(pDevExt, &pDevExt->CmdVbva, false);
4720
4721 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
4722
4723 return STATUS_SUCCESS;
4724}
4725
4726
4727static NTSTATUS
4728APIENTRY
4729DxgkDdiQueryCurrentFenceLegacy(
4730 CONST HANDLE hAdapter,
4731 DXGKARG_QUERYCURRENTFENCE* pCurrentFence)
4732{
4733 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
4734
4735 vboxVDbgBreakF();
4736
4737 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
4738 VBOXWDDM_QUERYCURFENCE_CB context = {0};
4739 context.pDevExt = pDevExt;
4740 BOOLEAN bRet;
4741 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbSynchronizeExecution(
4742 pDevExt->u.primary.DxgkInterface.DeviceHandle,
4743 vboxWddmQueryCurrentFenceCb,
4744 &context,
4745 0, /* IN ULONG MessageNumber */
4746 &bRet);
4747 Assert(Status == STATUS_SUCCESS);
4748 if (Status == STATUS_SUCCESS)
4749 {
4750 pCurrentFence->CurrentFence = context.uLastCompletedCmdFenceId;
4751 }
4752
4753 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
4754
4755 return STATUS_SUCCESS;
4756}
4757
4758NTSTATUS
4759APIENTRY
4760DxgkDdiIsSupportedVidPn(
4761 CONST HANDLE hAdapter,
4762 OUT DXGKARG_ISSUPPORTEDVIDPN* pIsSupportedVidPnArg
4763 )
4764{
4765 /* The DxgkDdiIsSupportedVidPn should be made pageable. */
4766 PAGED_CODE();
4767
4768 LOGF(("ENTER, context(0x%x)", hAdapter));
4769
4770 vboxVDbgBreakFv();
4771
4772 NTSTATUS Status = STATUS_SUCCESS;
4773
4774 PVBOXMP_DEVEXT pContext = (PVBOXMP_DEVEXT)hAdapter;
4775 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
4776 Status = pContext->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pIsSupportedVidPnArg->hDesiredVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
4777 if (!NT_SUCCESS(Status))
4778 {
4779 WARN(("DxgkCbQueryVidPnInterface failed Status()0x%x\n", Status));
4780 return Status;
4781 }
4782
4783#ifdef VBOXWDDM_DEBUG_VIDPN
4784 vboxVidPnDumpVidPn("\n>>>>IS SUPPORTED VidPN : >>>>", pContext, pIsSupportedVidPnArg->hDesiredVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<");
4785#endif
4786
4787 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
4788 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
4789 Status = pVidPnInterface->pfnGetTopology(pIsSupportedVidPnArg->hDesiredVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
4790 if (!NT_SUCCESS(Status))
4791 {
4792 WARN(("pfnGetTopology failed Status()0x%x\n", Status));
4793 return Status;
4794 }
4795
4796 BOOLEAN fSupported = FALSE;
4797 Status = vboxVidPnCheckTopology(hVidPnTopology, pVidPnTopologyInterface, &fSupported);
4798 if (!NT_SUCCESS(Status))
4799 {
4800 WARN(("vboxVidPnCheckTopology failed Status()0x%x\n", Status));
4801 return Status;
4802 }
4803
4804 if (!fSupported)
4805 LOG(("found unsupported path"));
4806
4807 pIsSupportedVidPnArg->IsVidPnSupported = fSupported;
4808
4809#ifdef VBOXWDDM_DEBUG_VIDPN
4810 LOGREL(("The Given VidPn is %ssupported\n", pIsSupportedVidPnArg->IsVidPnSupported ? "" : "!!NOT!! "));
4811#endif
4812
4813 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
4814
4815 return Status;
4816}
4817
4818NTSTATUS
4819APIENTRY
4820DxgkDdiRecommendFunctionalVidPn(
4821 CONST HANDLE hAdapter,
4822 CONST DXGKARG_RECOMMENDFUNCTIONALVIDPN* CONST pRecommendFunctionalVidPnArg
4823 )
4824{
4825 /* The DxgkDdiRecommendFunctionalVidPn should be made pageable. */
4826 PAGED_CODE();
4827
4828 LOGF(("ENTER, context(0x%x)", hAdapter));
4829
4830 vboxVDbgBreakFv();
4831
4832#ifdef DEBUG_misha
4833 Assert(0);
4834#endif
4835
4836 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
4837 NTSTATUS Status;
4838 PVBOXWDDM_RECOMMENDVIDPN pVidPnInfo = pRecommendFunctionalVidPnArg->PrivateDriverDataSize >= sizeof (VBOXWDDM_RECOMMENDVIDPN) ?
4839 (PVBOXWDDM_RECOMMENDVIDPN)pRecommendFunctionalVidPnArg->pPrivateDriverData : NULL;
4840 PVBOXWDDM_VIDEOMODES_INFO pInfos = VBoxWddmGetAllVideoModesInfos(pDevExt);
4841 int i;
4842
4843 for (i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
4844 {
4845 /* @todo: check that we actually need the current source->target */
4846 PVBOXWDDM_VIDEOMODES_INFO pInfo = &pInfos[i];
4847 VIDEO_MODE_INFORMATION *pModeInfo = &pInfo->aModes[pInfo->iPreferredMode];
4848#if 0
4849 D3DKMDT_2DREGION Resolution;
4850 Resolution.cx = pModeInfo->VisScreenWidth;
4851 Resolution.cy = pModeInfo->VisScreenHeight;
4852 Status = vboxVidPnCheckAddMonitorModes(pDevExt, i, D3DKMDT_MCO_DRIVER, &Resolution, 1, 0);
4853#else
4854 Status = vboxVidPnCheckAddMonitorModes(pDevExt, i, D3DKMDT_MCO_DRIVER, pInfo->aResolutions, pInfo->cResolutions, pInfo->iPreferredResolution);
4855#endif
4856 if (Status != STATUS_SUCCESS)
4857 {
4858 WARN(("vboxVidPnCheckAddMonitorModes failed Status(0x%x)", Status));
4859 break;
4860 }
4861 }
4862
4863 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
4864 Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
4865 if (!NT_SUCCESS(Status))
4866 {
4867 WARN(("DxgkCbQueryVidPnInterface failed Status(0x%x)", Status));
4868 return Status;
4869 }
4870
4871 for (i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
4872 {
4873 Status = vboxVidPnPathAdd(pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, pVidPnInterface, i, i);
4874 if (!NT_SUCCESS(Status))
4875 {
4876 WARN(("vboxVidPnPathAdd failed Status(0x%x)", Status));
4877 return Status;
4878 }
4879 }
4880
4881 VIDEO_MODE_INFORMATION *pResModes = NULL;
4882 uint32_t cResModes = 0;
4883
4884 for (i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
4885 {
4886 D3DKMDT_2DREGION Resolution;
4887 PVBOXWDDM_VIDEOMODES_INFO pInfo = &pInfos[i];
4888 VIDEO_MODE_INFORMATION *pModeInfo = &pInfo->aModes[pInfo->iPreferredMode];
4889 Resolution.cx = pModeInfo->VisScreenWidth;
4890 Resolution.cy = pModeInfo->VisScreenHeight;
4891 int32_t iPreferableResMode;
4892 uint32_t cActualResModes;
4893
4894 Status = VBoxWddmGetModesForResolution(pInfo->aModes, pInfo->cModes, pInfo->iPreferredMode, &Resolution,
4895 pResModes, cResModes, &cActualResModes, &iPreferableResMode);
4896 Assert(Status == STATUS_SUCCESS || Status == STATUS_BUFFER_TOO_SMALL);
4897 if (Status == STATUS_BUFFER_TOO_SMALL)
4898 {
4899 Assert(cResModes < cActualResModes);
4900 if (pResModes)
4901 {
4902 vboxWddmMemFree(pResModes);
4903 }
4904 pResModes = (VIDEO_MODE_INFORMATION*)vboxWddmMemAllocZero(sizeof (*pResModes) * cActualResModes);
4905 Assert(pResModes);
4906 if (!pResModes)
4907 {
4908 Status = STATUS_NO_MEMORY;
4909 break;
4910 }
4911 cResModes = cActualResModes;
4912 Status = VBoxWddmGetModesForResolution(pInfo->aModes, pInfo->cModes, pInfo->iPreferredMode, &Resolution,
4913 pResModes, cResModes, &cActualResModes, &iPreferableResMode);
4914 Assert(Status == STATUS_SUCCESS);
4915 if (Status != STATUS_SUCCESS)
4916 break;
4917 }
4918 else if (Status != STATUS_SUCCESS)
4919 break;
4920
4921 Assert(iPreferableResMode >= 0);
4922 Assert(cActualResModes);
4923
4924 Status = vboxVidPnCreatePopulateVidPnPathFromLegacy(pDevExt, pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, pVidPnInterface,
4925 pResModes, cActualResModes, iPreferableResMode,
4926 &Resolution, 1 /* cResolutions */,
4927 i, i); /* srcId, tgtId */
4928 Assert(Status == STATUS_SUCCESS);
4929 if (Status != STATUS_SUCCESS)
4930 {
4931 LOGREL(("vboxVidPnCreatePopulateVidPnFromLegacy failed Status(0x%x)", Status));
4932 break;
4933 }
4934 }
4935
4936 if(pResModes)
4937 vboxWddmMemFree(pResModes);
4938
4939#ifdef VBOXWDDM_DEBUG_VIDPN
4940 vboxVidPnDumpVidPn("\n>>>>Recommended VidPN: >>>>", pDevExt, pRecommendFunctionalVidPnArg->hRecommendedFunctionalVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<\n");
4941#endif
4942
4943 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
4944
4945 return Status;
4946}
4947
4948NTSTATUS
4949APIENTRY
4950DxgkDdiEnumVidPnCofuncModality(
4951 CONST HANDLE hAdapter,
4952 CONST DXGKARG_ENUMVIDPNCOFUNCMODALITY* CONST pEnumCofuncModalityArg
4953 )
4954{
4955 /* The DxgkDdiEnumVidPnCofuncModality function should be made pageable. */
4956 PAGED_CODE();
4957
4958 LOGF(("ENTER, context(0x%x)", hAdapter));
4959
4960 vboxVDbgBreakFv();
4961
4962 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
4963 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
4964 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pEnumCofuncModalityArg->hConstrainingVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
4965 if (!NT_SUCCESS(Status))
4966 {
4967 WARN(("DxgkCbQueryVidPnInterface failed Status()0x%x\n", Status));
4968 return Status;
4969 }
4970#ifdef VBOXWDDM_DEBUG_VIDPN
4971 vboxVidPnDumpCofuncModalityArg(">>>>MODALITY Args: ", pEnumCofuncModalityArg, "\n");
4972 vboxVidPnDumpVidPn(">>>>MODALITY VidPN (IN) : >>>>\n", pDevExt, pEnumCofuncModalityArg->hConstrainingVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<\n");
4973#endif
4974
4975 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
4976 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
4977 Status = pVidPnInterface->pfnGetTopology(pEnumCofuncModalityArg->hConstrainingVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
4978 Assert(Status == STATUS_SUCCESS);
4979 if (!NT_SUCCESS(Status))
4980 {
4981 WARN(("pfnGetTopology failed Status()0x%x\n", Status));
4982 return Status;
4983 }
4984
4985#ifdef DEBUG_misha
4986 BOOLEAN fSupported = FALSE;
4987 Status = vboxVidPnCheckTopology(hVidPnTopology, pVidPnTopologyInterface, &fSupported);
4988 if (!NT_SUCCESS(Status))
4989 {
4990 WARN(("vboxVidPnCheckTopology failed Status()0x%x\n", Status));
4991 return Status;
4992 }
4993
4994 Assert(fSupported);
4995#endif
4996 VBOXVIDPNCOFUNCMODALITY CbContext = {0};
4997 CbContext.pDevExt = pDevExt;
4998 CbContext.pVidPnInterface = pVidPnInterface;
4999 CbContext.pEnumCofuncModalityArg = pEnumCofuncModalityArg;
5000 CbContext.pInfos = VBoxWddmGetAllVideoModesInfos(pDevExt);
5001
5002 Status = vboxVidPnEnumPaths(hVidPnTopology, pVidPnTopologyInterface,
5003 vboxVidPnCofuncModalityPathEnum, &CbContext);
5004 if (!NT_SUCCESS(Status))
5005 {
5006 WARN(("vboxVidPnEnumPaths failed Status()0x%x\n", Status));
5007 return Status;
5008 }
5009
5010 Status = CbContext.Status;
5011 if (!NT_SUCCESS(Status))
5012 {
5013 WARN(("vboxVidPnCofuncModalityPathEnum failed Status()0x%x\n", Status));
5014 return Status;
5015 }
5016
5017#ifdef VBOXWDDM_DEBUG_VIDPN
5018 vboxVidPnDumpVidPn("\n>>>>MODALITY VidPN (OUT) : >>>>\n", pDevExt, pEnumCofuncModalityArg->hConstrainingVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<\n\n");
5019#endif
5020
5021 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
5022
5023 return Status;
5024}
5025
5026NTSTATUS
5027APIENTRY
5028DxgkDdiSetVidPnSourceAddress(
5029 CONST HANDLE hAdapter,
5030 CONST DXGKARG_SETVIDPNSOURCEADDRESS* pSetVidPnSourceAddress
5031 )
5032{
5033 /* The DxgkDdiSetVidPnSourceAddress function should be made pageable. */
5034 PAGED_CODE();
5035
5036 vboxVDbgBreakFv();
5037
5038 LOGF(("ENTER, context(0x%x)", hAdapter));
5039
5040 NTSTATUS Status = STATUS_SUCCESS;
5041 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
5042 Assert((UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays > pSetVidPnSourceAddress->VidPnSourceId);
5043
5044 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pSetVidPnSourceAddress->VidPnSourceId];
5045 POINT Pos;
5046 Status= vboxWddmDisplaySettingsQueryPos(pDevExt, pSetVidPnSourceAddress->VidPnSourceId, &Pos);
5047 Assert(Status == STATUS_SUCCESS);
5048 if (NT_SUCCESS(Status))
5049 {
5050 if (memcmp(&pSource->VScreenPos, &Pos, sizeof (Pos)))
5051 {
5052 pSource->VScreenPos = Pos;
5053 pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
5054 }
5055 }
5056
5057 Status = STATUS_SUCCESS;
5058
5059 if ((UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays <= pSetVidPnSourceAddress->VidPnSourceId)
5060 {
5061 WARN(("invalid VidPnSourceId (%d), for displays(%d)", pSetVidPnSourceAddress->VidPnSourceId, VBoxCommonFromDeviceExt(pDevExt)->cDisplays));
5062 return STATUS_INVALID_PARAMETER;
5063 }
5064
5065 PVBOXWDDM_ALLOCATION pAllocation;
5066 Assert(pSetVidPnSourceAddress->hAllocation);
5067 Assert(pSetVidPnSourceAddress->hAllocation || pSource->pPrimaryAllocation);
5068 Assert (pSetVidPnSourceAddress->Flags.Value < 2); /* i.e. 0 or 1 (ModeChange) */
5069
5070 if (pSetVidPnSourceAddress->hAllocation)
5071 {
5072 pAllocation = (PVBOXWDDM_ALLOCATION)pSetVidPnSourceAddress->hAllocation;
5073 vboxWddmAssignPrimary(pDevExt, pSource, pAllocation, pSetVidPnSourceAddress->VidPnSourceId);
5074 }
5075 else
5076 pAllocation = pSource->pPrimaryAllocation;
5077
5078 if (pAllocation)
5079 {
5080 vboxWddmAddrSetVram(&pAllocation->AllocData.Addr, pSetVidPnSourceAddress->PrimarySegment, (VBOXVIDEOOFFSET)pSetVidPnSourceAddress->PrimaryAddress.QuadPart);
5081 }
5082
5083#ifdef VBOX_WDDM_WIN8
5084 if (g_VBoxDisplayOnly && !pAllocation)
5085 {
5086 /* the VRAM here is an absolute address, nto an offset!
5087 * convert to offset since all internal VBox functionality is offset-based */
5088 vboxWddmAddrSetVram(&pSource->AllocData.Addr, pSetVidPnSourceAddress->PrimarySegment,
5089 vboxWddmVramAddrToOffset(pDevExt, pSetVidPnSourceAddress->PrimaryAddress));
5090 }
5091 else
5092#endif
5093 {
5094#ifdef VBOX_WDDM_WIN8
5095 Assert(!g_VBoxDisplayOnly);
5096#endif
5097 vboxWddmAddrSetVram(&pSource->AllocData.Addr, pSetVidPnSourceAddress->PrimarySegment,
5098 pSetVidPnSourceAddress->PrimaryAddress.QuadPart);
5099 }
5100
5101 pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_LOCATION;
5102
5103 if (pSource->bVisible)
5104 {
5105 vboxWddmGhDisplayCheckSetInfoFromSource(pDevExt, pSource);
5106 }
5107
5108 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
5109
5110 return Status;
5111}
5112
5113NTSTATUS
5114APIENTRY
5115DxgkDdiSetVidPnSourceVisibility(
5116 CONST HANDLE hAdapter,
5117 CONST DXGKARG_SETVIDPNSOURCEVISIBILITY* pSetVidPnSourceVisibility
5118 )
5119{
5120 /* DxgkDdiSetVidPnSourceVisibility should be made pageable. */
5121 PAGED_CODE();
5122
5123 vboxVDbgBreakFv();
5124
5125 LOGF(("ENTER, context(0x%x)", hAdapter));
5126
5127 NTSTATUS Status = STATUS_SUCCESS;
5128 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
5129 Assert((UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays > pSetVidPnSourceVisibility->VidPnSourceId);
5130
5131 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pSetVidPnSourceVisibility->VidPnSourceId];
5132 POINT Pos;
5133 Status= vboxWddmDisplaySettingsQueryPos(pDevExt, pSetVidPnSourceVisibility->VidPnSourceId, &Pos);
5134 Assert(Status == STATUS_SUCCESS);
5135 if (NT_SUCCESS(Status))
5136 {
5137 if (memcmp(&pSource->VScreenPos, &Pos, sizeof (Pos)))
5138 {
5139 pSource->VScreenPos = Pos;
5140 pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
5141 }
5142 }
5143 Status = STATUS_SUCCESS;
5144
5145 if ((UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays <= pSetVidPnSourceVisibility->VidPnSourceId)
5146 {
5147 WARN(("invalid VidPnSourceId (%d), for displays(%d)", pSetVidPnSourceVisibility->VidPnSourceId, VBoxCommonFromDeviceExt(pDevExt)->cDisplays));
5148 return STATUS_INVALID_PARAMETER;
5149 }
5150
5151 PVBOXWDDM_ALLOCATION pAllocation = pSource->pPrimaryAllocation;
5152 if (pAllocation)
5153 pAllocation->bVisible = pSetVidPnSourceVisibility->Visible;
5154
5155 if (pSource->bVisible != pSetVidPnSourceVisibility->Visible)
5156 {
5157 pSource->bVisible = pSetVidPnSourceVisibility->Visible;
5158 if (pSource->bVisible)
5159 {
5160 vboxWddmGhDisplayCheckSetInfoFromSource(pDevExt, pSource);
5161 }
5162 }
5163
5164 LOGF(("LEAVE, status(0x%x), context(0x%x)", Status, hAdapter));
5165
5166 return Status;
5167}
5168
5169static DECLCALLBACK(BOOLEAN) vboxWddmVidPnCleanupTargetsForSrcEnum(PVBOXMP_DEVEXT pDevExt, D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface,
5170 CONST D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId, SIZE_T cTgtPaths, PVOID pContext)
5171{
5172 AssertRelease(VidPnTargetId < RT_ELEMENTS(pDevExt->aTargets));
5173 PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[VidPnTargetId];
5174 /* see comments in DxgkDdiCommitVidPn */
5175 pTarget->HeightVisible = 0;
5176 return TRUE;
5177}
5178
5179NTSTATUS
5180APIENTRY
5181DxgkDdiCommitVidPn(
5182 CONST HANDLE hAdapter,
5183 CONST DXGKARG_COMMITVIDPN* CONST pCommitVidPnArg
5184 )
5185{
5186 LOGF(("ENTER, context(0x%x)", hAdapter));
5187
5188 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
5189 NTSTATUS Status;
5190
5191 vboxVDbgBreakFv();
5192
5193 do {
5194 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
5195 Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pCommitVidPnArg->hFunctionalVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
5196 if (!NT_SUCCESS(Status))
5197 {
5198 WARN(("DxgkCbQueryVidPnInterface failed Status 0x%x", Status));
5199 break;
5200 }
5201
5202#ifdef VBOXWDDM_DEBUG_VIDPN
5203 vboxVidPnDumpVidPn("\n>>>>COMMIT VidPN: >>>>", pDevExt, pCommitVidPnArg->hFunctionalVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<\n");
5204#endif
5205
5206 if (pCommitVidPnArg->AffectedVidPnSourceId != D3DDDI_ID_ALL)
5207 {
5208 /* there is not VidPn on driver start, check that */
5209 if (pDevExt->u.primary.hCommittedVidPn)
5210 {
5211 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
5212 CONST DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
5213 const DXGK_VIDPN_INTERFACE* pOldVidPnInterface = NULL;
5214 Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(pDevExt->u.primary.hCommittedVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pOldVidPnInterface);
5215 if (!NT_SUCCESS(Status))
5216 {
5217 WARN(("DxgkCbQueryVidPnInterface for current VidPn failed Status 0x%x", Status));
5218 break;
5219 }
5220
5221 Status = pOldVidPnInterface->pfnGetTopology(pDevExt->u.primary.hCommittedVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
5222 if (!NT_SUCCESS(Status))
5223 {
5224 WARN(("pfnGetTopology for current VidPn failed Status 0x%x", Status));
5225 break;
5226 }
5227
5228 /* this will zero up visible height for all targets of the given source, see above comment */
5229 Status = vboxVidPnEnumTargetsForSource(pDevExt, hVidPnTopology, pVidPnTopologyInterface,
5230 pCommitVidPnArg->AffectedVidPnSourceId,
5231 vboxWddmVidPnCleanupTargetsForSrcEnum, NULL);
5232 if (Status == STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY)
5233 Status = STATUS_SUCCESS;
5234
5235 if (!NT_SUCCESS(Status))
5236 {
5237 WARN(("vboxVidPnEnumTargetsForSource for current VidPn failed Status 0x%x", Status));
5238 break;
5239 }
5240 }
5241
5242 Status = vboxVidPnCommitSourceModeForSrcId(
5243 pDevExt,
5244 pCommitVidPnArg->hFunctionalVidPn, pVidPnInterface,
5245 pCommitVidPnArg->AffectedVidPnSourceId, (PVBOXWDDM_ALLOCATION)pCommitVidPnArg->hPrimaryAllocation);
5246 if (!NT_SUCCESS(Status))
5247 {
5248 WARN(("vboxVidPnCommitSourceModeForSrcId for current VidPn failed Status 0x%x", Status));
5249 break;
5250 }
5251 }
5252 else
5253 {
5254 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
5255 {
5256 PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[i];
5257 /* see above comment */
5258 pTarget->HeightVisible = 0;
5259 }
5260
5261 /* clear all current primaries */
5262 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
5263 {
5264 vboxWddmAssignPrimary(pDevExt, &pDevExt->aSources[i], NULL, i);
5265 }
5266
5267 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
5268 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
5269 Status = pVidPnInterface->pfnGetTopology(pCommitVidPnArg->hFunctionalVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
5270 if (!NT_SUCCESS(Status))
5271 {
5272 WARN(("pfnGetTopology failed Status 0x%x", Status));
5273 break;
5274 }
5275
5276 VBOXVIDPNCOMMIT CbContext = {0};
5277 CbContext.pDevExt = pDevExt;
5278 CbContext.pVidPnInterface = pVidPnInterface;
5279 CbContext.pCommitVidPnArg = pCommitVidPnArg;
5280 Status = vboxVidPnEnumPaths(hVidPnTopology, pVidPnTopologyInterface,
5281 vboxVidPnCommitPathEnum, &CbContext);
5282 if (!NT_SUCCESS(Status))
5283 {
5284 WARN(("vboxVidPnEnumPaths failed Status 0x%x", Status));
5285 break;
5286 }
5287
5288 Status = CbContext.Status;
5289 if (!NT_SUCCESS(Status))
5290 {
5291 WARN(("vboxVidPnCommitPathEnum failed Status 0x%x", Status));
5292 break;
5293 }
5294 }
5295
5296 Assert(NT_SUCCESS(Status));
5297 pDevExt->u.primary.hCommittedVidPn = pCommitVidPnArg->hFunctionalVidPn;
5298
5299 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
5300 {
5301 PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[i];
5302 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[i];
5303 uint32_t cAutoresizes = pDevExt->cContextsDispIfResize;
5304 if (!cAutoresizes)
5305 {
5306 if (pSource->bVisible || !pTarget->HeightVisible)
5307 vboxWddmGhDisplayCheckSetInfoFromSource(pDevExt, pSource);
5308 }
5309 else
5310 pTarget->fStateSyncPening = true;
5311 }
5312
5313 LOGF(("LEAVE, SUCCESS status(0x%x), context(0x%x)", Status, hAdapter));
5314
5315 return Status;
5316 } while (0);
5317
5318 AssertRelease(!NT_SUCCESS(Status));
5319
5320 LOGF(("LEAVE, !!FAILURE!! status(0x%x), context(0x%x)", Status, hAdapter));
5321 return Status;
5322}
5323
5324NTSTATUS
5325APIENTRY
5326DxgkDdiUpdateActiveVidPnPresentPath(
5327 CONST HANDLE hAdapter,
5328 CONST DXGKARG_UPDATEACTIVEVIDPNPRESENTPATH* CONST pUpdateActiveVidPnPresentPathArg
5329 )
5330{
5331 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
5332
5333 AssertBreakpoint();
5334
5335 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
5336
5337 return STATUS_SUCCESS;
5338}
5339
5340NTSTATUS
5341APIENTRY
5342DxgkDdiRecommendMonitorModes(
5343 CONST HANDLE hAdapter,
5344 CONST DXGKARG_RECOMMENDMONITORMODES* CONST pRecommendMonitorModesArg
5345 )
5346{
5347 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
5348
5349 vboxVDbgBreakFv();
5350
5351 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
5352 NTSTATUS Status;
5353 PVBOXWDDM_VIDEOMODES_INFO pInfo = VBoxWddmGetVideoModesInfo(pDevExt, pRecommendMonitorModesArg->VideoPresentTargetId);
5354 PVIDEO_MODE_INFORMATION pPreferredMode = &pInfo->aModes[pInfo->iPreferredMode];
5355
5356
5357 for (uint32_t i = 0; i < pInfo->cResolutions; i++)
5358 {
5359 D3DKMDT_MONITOR_SOURCE_MODE * pNewMonitorSourceModeInfo;
5360 Status = pRecommendMonitorModesArg->pMonitorSourceModeSetInterface->pfnCreateNewModeInfo(
5361 pRecommendMonitorModesArg->hMonitorSourceModeSet, &pNewMonitorSourceModeInfo);
5362 Assert(Status == STATUS_SUCCESS);
5363 if (Status == STATUS_SUCCESS)
5364 {
5365 Status = vboxVidPnPopulateMonitorSourceModeInfoFromLegacy(pDevExt,
5366 pNewMonitorSourceModeInfo,
5367 &pInfo->aResolutions[i],
5368 D3DKMDT_MCO_DRIVER,
5369 pPreferredMode->VisScreenWidth == pInfo->aResolutions[i].cx
5370 && pPreferredMode->VisScreenHeight == pInfo->aResolutions[i].cy);
5371 Assert(Status == STATUS_SUCCESS);
5372 if (Status == STATUS_SUCCESS)
5373 {
5374 Status = pRecommendMonitorModesArg->pMonitorSourceModeSetInterface->pfnAddMode(
5375 pRecommendMonitorModesArg->hMonitorSourceModeSet, pNewMonitorSourceModeInfo);
5376 Assert(Status == STATUS_SUCCESS);
5377 if (Status == STATUS_SUCCESS)
5378 continue;
5379 }
5380
5381 /* error has occurred, release & break */
5382 pRecommendMonitorModesArg->pMonitorSourceModeSetInterface->pfnReleaseModeInfo(
5383 pRecommendMonitorModesArg->hMonitorSourceModeSet, pNewMonitorSourceModeInfo);
5384 break;
5385 }
5386 }
5387
5388 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
5389
5390 return Status;
5391}
5392
5393NTSTATUS
5394APIENTRY
5395DxgkDdiRecommendVidPnTopology(
5396 CONST HANDLE hAdapter,
5397 CONST DXGKARG_RECOMMENDVIDPNTOPOLOGY* CONST pRecommendVidPnTopologyArg
5398 )
5399{
5400 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
5401
5402 vboxVDbgBreakFv();
5403
5404 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
5405
5406 return STATUS_GRAPHICS_NO_RECOMMENDED_VIDPN_TOPOLOGY;
5407}
5408
5409NTSTATUS
5410APIENTRY
5411DxgkDdiGetScanLine(
5412 CONST HANDLE hAdapter,
5413 DXGKARG_GETSCANLINE* pGetScanLine)
5414{
5415 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
5416
5417 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
5418
5419#ifdef DEBUG_misha
5420 RT_BREAKPOINT();
5421#endif
5422
5423 NTSTATUS Status = VBoxWddmSlGetScanLine(pDevExt, pGetScanLine);
5424
5425 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
5426
5427 return Status;
5428}
5429
5430NTSTATUS
5431APIENTRY
5432DxgkDdiStopCapture(
5433 CONST HANDLE hAdapter,
5434 CONST DXGKARG_STOPCAPTURE* pStopCapture)
5435{
5436 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
5437
5438 AssertBreakpoint();
5439
5440 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
5441
5442 return STATUS_SUCCESS;
5443}
5444
5445NTSTATUS
5446APIENTRY
5447DxgkDdiControlInterrupt(
5448 CONST HANDLE hAdapter,
5449 CONST DXGK_INTERRUPT_TYPE InterruptType,
5450 BOOLEAN Enable
5451 )
5452{
5453 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
5454
5455 NTSTATUS Status = STATUS_NOT_IMPLEMENTED;
5456 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
5457
5458 switch (InterruptType)
5459 {
5460 case DXGK_INTERRUPT_CRTC_VSYNC:
5461 {
5462 Status = VBoxWddmSlEnableVSyncNotification(pDevExt, Enable);
5463 if (NT_SUCCESS(Status))
5464 Status = STATUS_SUCCESS; /* <- sanity */
5465 else
5466 WARN(("VSYNC Interrupt control failed Enable(%d), Status(0x%x)", Enable, Status));
5467 break;
5468 }
5469 case DXGK_INTERRUPT_DMA_COMPLETED:
5470 case DXGK_INTERRUPT_DMA_PREEMPTED:
5471 case DXGK_INTERRUPT_DMA_FAULTED:
5472 WARN(("Unexpected interrupt type! %d", InterruptType));
5473 break;
5474 default:
5475 WARN(("UNSUPPORTED interrupt type! %d", InterruptType));
5476 break;
5477 }
5478
5479 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
5480
5481 return Status;
5482}
5483
5484NTSTATUS
5485APIENTRY
5486DxgkDdiCreateOverlay(
5487 CONST HANDLE hAdapter,
5488 DXGKARG_CREATEOVERLAY *pCreateOverlay)
5489{
5490 LOGF(("ENTER, hAdapter(0x%p)", hAdapter));
5491
5492 NTSTATUS Status = STATUS_SUCCESS;
5493 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
5494 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)vboxWddmMemAllocZero(sizeof (VBOXWDDM_OVERLAY));
5495 Assert(pOverlay);
5496 if (pOverlay)
5497 {
5498 int rc = vboxVhwaHlpOverlayCreate(pDevExt, pCreateOverlay->VidPnSourceId, &pCreateOverlay->OverlayInfo, pOverlay);
5499 AssertRC(rc);
5500 if (RT_SUCCESS(rc))
5501 {
5502 pCreateOverlay->hOverlay = pOverlay;
5503 }
5504 else
5505 {
5506 vboxWddmMemFree(pOverlay);
5507 Status = STATUS_UNSUCCESSFUL;
5508 }
5509 }
5510 else
5511 Status = STATUS_NO_MEMORY;
5512
5513 LOGF(("LEAVE, hAdapter(0x%p)", hAdapter));
5514
5515 return Status;
5516}
5517
5518NTSTATUS
5519APIENTRY
5520DxgkDdiDestroyDevice(
5521 CONST HANDLE hDevice)
5522{
5523 /* DxgkDdiDestroyDevice should be made pageable. */
5524 PAGED_CODE();
5525
5526 LOGF(("ENTER, hDevice(0x%x)", hDevice));
5527
5528 vboxVDbgBreakFv();
5529
5530 vboxWddmMemFree(hDevice);
5531
5532 LOGF(("LEAVE, "));
5533
5534 return STATUS_SUCCESS;
5535}
5536
5537
5538
5539/*
5540 * DxgkDdiOpenAllocation
5541 */
5542NTSTATUS
5543APIENTRY
5544DxgkDdiOpenAllocation(
5545 CONST HANDLE hDevice,
5546 CONST DXGKARG_OPENALLOCATION *pOpenAllocation)
5547{
5548 /* DxgkDdiOpenAllocation should be made pageable. */
5549 PAGED_CODE();
5550
5551 LOGF(("ENTER, hDevice(0x%x)", hDevice));
5552
5553 vboxVDbgBreakFv();
5554
5555 NTSTATUS Status = STATUS_SUCCESS;
5556 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)hDevice;
5557 PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
5558 PVBOXWDDM_RCINFO pRcInfo = NULL;
5559 if (pOpenAllocation->PrivateDriverSize)
5560 {
5561 Assert(pOpenAllocation->pPrivateDriverData);
5562 if (pOpenAllocation->PrivateDriverSize == sizeof (VBOXWDDM_RCINFO))
5563 {
5564 pRcInfo = (PVBOXWDDM_RCINFO)pOpenAllocation->pPrivateDriverData;
5565 Assert(pRcInfo->cAllocInfos == pOpenAllocation->NumAllocations);
5566 }
5567 else
5568 {
5569 WARN(("Invalid PrivateDriverSize %d", pOpenAllocation->PrivateDriverSize));
5570 Status = STATUS_INVALID_PARAMETER;
5571 }
5572 }
5573
5574 if (Status == STATUS_SUCCESS)
5575 {
5576 UINT i = 0;
5577 for (; i < pOpenAllocation->NumAllocations; ++i)
5578 {
5579 DXGK_OPENALLOCATIONINFO* pInfo = &pOpenAllocation->pOpenAllocation[i];
5580 Assert(pInfo->PrivateDriverDataSize == sizeof (VBOXWDDM_ALLOCINFO));
5581 Assert(pInfo->pPrivateDriverData);
5582 PVBOXWDDM_ALLOCATION pAllocation = vboxWddmGetAllocationFromHandle(pDevExt, pInfo->hAllocation);
5583 if (!pAllocation)
5584 {
5585 WARN(("invalid handle"));
5586 Status = STATUS_INVALID_PARAMETER;
5587 break;
5588 }
5589
5590#ifdef DEBUG
5591 Assert(!pAllocation->fAssumedDeletion);
5592#endif
5593 if (pRcInfo)
5594 {
5595 Assert(pAllocation->enmType == VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC);
5596
5597 if (pInfo->PrivateDriverDataSize != sizeof (VBOXWDDM_ALLOCINFO)
5598 || !pInfo->pPrivateDriverData)
5599 {
5600 WARN(("invalid data size"));
5601 Status = STATUS_INVALID_PARAMETER;
5602 break;
5603 }
5604 PVBOXWDDM_ALLOCINFO pAllocInfo = (PVBOXWDDM_ALLOCINFO)pInfo->pPrivateDriverData;
5605
5606#ifdef VBOX_WITH_VIDEOHWACCEL
5607 if (pRcInfo->RcDesc.fFlags.Overlay)
5608 {
5609 /* we have queried host for some surface info, like pitch & size,
5610 * need to return it back to the UMD (User Mode Drive) */
5611 pAllocInfo->SurfDesc = pAllocation->AllocData.SurfDesc;
5612 /* success, just continue */
5613 }
5614#endif
5615 }
5616
5617 KIRQL OldIrql;
5618 PVBOXWDDM_OPENALLOCATION pOa;
5619 KeAcquireSpinLock(&pAllocation->OpenLock, &OldIrql);
5620 pOa = VBoxWddmOaSearchLocked(pDevice, pAllocation);
5621 if (pOa)
5622 {
5623 ++pOa->cOpens;
5624 ++pAllocation->cOpens;
5625 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
5626 }
5627 else
5628 {
5629 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
5630 pOa = (PVBOXWDDM_OPENALLOCATION)vboxWddmMemAllocZero(sizeof (VBOXWDDM_OPENALLOCATION));
5631 if (!pOa)
5632 {
5633 WARN(("failed to allocation alloc info"));
5634 Status = STATUS_INSUFFICIENT_RESOURCES;
5635 break;
5636 }
5637
5638 pOa->hAllocation = pInfo->hAllocation;
5639 pOa->pAllocation = pAllocation;
5640 pOa->pDevice = pDevice;
5641 pOa->cOpens = 1;
5642
5643 PVBOXWDDM_OPENALLOCATION pConcurrentOa;
5644 KeAcquireSpinLock(&pAllocation->OpenLock, &OldIrql);
5645 pConcurrentOa = VBoxWddmOaSearchLocked(pDevice, pAllocation);
5646 if (!pConcurrentOa)
5647 InsertHeadList(&pAllocation->OpenList, &pOa->ListEntry);
5648 else
5649 ++pConcurrentOa->cOpens;
5650 ++pAllocation->cOpens;
5651 KeReleaseSpinLock(&pAllocation->OpenLock, OldIrql);
5652 if (pConcurrentOa)
5653 {
5654 vboxWddmMemFree(pOa);
5655 pOa = pConcurrentOa;
5656 }
5657 }
5658
5659 pInfo->hDeviceSpecificAllocation = pOa;
5660 }
5661
5662 if (Status != STATUS_SUCCESS)
5663 {
5664 for (UINT j = 0; j < i; ++j)
5665 {
5666 DXGK_OPENALLOCATIONINFO* pInfo2Free = &pOpenAllocation->pOpenAllocation[j];
5667 PVBOXWDDM_OPENALLOCATION pOa2Free = (PVBOXWDDM_OPENALLOCATION)pInfo2Free->hDeviceSpecificAllocation;
5668 VBoxWddmOaRelease(pOa2Free);
5669 }
5670 }
5671 }
5672 LOGF(("LEAVE, hDevice(0x%x)", hDevice));
5673
5674 return Status;
5675}
5676
5677NTSTATUS
5678APIENTRY
5679DxgkDdiCloseAllocation(
5680 CONST HANDLE hDevice,
5681 CONST DXGKARG_CLOSEALLOCATION* pCloseAllocation)
5682{
5683 /* DxgkDdiCloseAllocation should be made pageable. */
5684 PAGED_CODE();
5685
5686 LOGF(("ENTER, hDevice(0x%x)", hDevice));
5687
5688 vboxVDbgBreakFv();
5689
5690 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)hDevice;
5691 PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
5692
5693 for (UINT i = 0; i < pCloseAllocation->NumAllocations; ++i)
5694 {
5695 PVBOXWDDM_OPENALLOCATION pOa2Free = (PVBOXWDDM_OPENALLOCATION)pCloseAllocation->pOpenHandleList[i];
5696 PVBOXWDDM_ALLOCATION pAllocation = pOa2Free->pAllocation;
5697 Assert(pAllocation->cShRcRefs >= pOa2Free->cShRcRefs);
5698 pAllocation->cShRcRefs -= pOa2Free->cShRcRefs;
5699 VBoxWddmOaRelease(pOa2Free);
5700 }
5701
5702 LOGF(("LEAVE, hDevice(0x%x)", hDevice));
5703
5704 return STATUS_SUCCESS;
5705}
5706
5707static NTSTATUS
5708APIENTRY
5709DxgkDdiRenderNew(
5710 CONST HANDLE hContext,
5711 DXGKARG_RENDER *pRender)
5712{
5713// LOGF(("ENTER, hContext(0x%x)", hContext));
5714
5715 if (pRender->DmaBufferPrivateDataSize < sizeof (VBOXCMDVBVA_HDR))
5716 {
5717 WARN(("pRender->DmaBufferPrivateDataSize(%d) < sizeof VBOXCMDVBVA_HDR (%d)",
5718 pRender->DmaBufferPrivateDataSize , sizeof (VBOXCMDVBVA_HDR)));
5719 /* @todo: can this actually happen? what status to return? */
5720 return STATUS_INVALID_PARAMETER;
5721 }
5722 if (pRender->CommandLength < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
5723 {
5724 WARN(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_BASEHDR (%d)",
5725 pRender->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
5726 /* @todo: can this actually happen? what status to return? */
5727 return STATUS_INVALID_PARAMETER;
5728 }
5729
5730 PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR pInputHdr = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)pRender->pCommand;
5731 NTSTATUS Status = STATUS_SUCCESS;
5732
5733 uint32_t cbBuffer = 0;
5734 uint32_t cbCmdDma = 0;
5735 VBOXCMDVBVA_HDR* pCmd = (VBOXCMDVBVA_HDR*)pRender->pDmaBufferPrivateData;
5736
5737 switch (pInputHdr->enmCmd)
5738 {
5739 case VBOXVDMACMD_TYPE_CHROMIUM_CMD:
5740 {
5741 if (pRender->AllocationListSize >= (UINT32_MAX - RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD, aBufInfos))/ RT_SIZEOFMEMB(VBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD, aBufInfos[0]))
5742 {
5743 WARN(("Invalid AllocationListSize %d", pRender->AllocationListSize));
5744 return STATUS_INVALID_PARAMETER;
5745 }
5746
5747 if (pRender->CommandLength != RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD, aBufInfos[pRender->AllocationListSize]))
5748 {
5749 WARN(("pRender->CommandLength (%d) != RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD, aBufInfos[pRender->AllocationListSize](%d)",
5750 pRender->CommandLength, RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD, aBufInfos[pRender->AllocationListSize])));
5751 return STATUS_INVALID_PARAMETER;
5752 }
5753
5754 if (pRender->AllocationListSize >= (UINT32_MAX - RT_OFFSETOF(VBOXCMDVBVA_CRCMD, Cmd.aBuffers))/ RT_SIZEOFMEMB(VBOXCMDVBVA_CRCMD, Cmd.aBuffers[0]))
5755 {
5756 WARN(("Invalid AllocationListSize %d", pRender->AllocationListSize));
5757 return STATUS_INVALID_PARAMETER;
5758 }
5759
5760 cbBuffer = RT_OFFSETOF(VBOXCMDVBVA_CRCMD, Cmd.aBuffers[pRender->AllocationListSize]);
5761 if (cbBuffer > 4096)
5762 {
5763 /* this should not be bigger actually */
5764 WARN(("too big command buffer %d", cbBuffer));
5765 return STATUS_INVALID_PARAMETER;
5766 }
5767
5768 cbCmdDma = VBOXWDDM_DUMMY_DMABUFFER_SIZE;
5769
5770 if (pRender->DmaBufferPrivateDataSize < cbBuffer)
5771 {
5772 WARN(("pRender->DmaBufferPrivateDataSize too small %d, requested %d", pRender->DmaBufferPrivateDataSize, cbBuffer));
5773 return STATUS_INVALID_PARAMETER;
5774 }
5775
5776 if (pRender->DmaSize < cbCmdDma)
5777 {
5778 WARN(("dma buffer %d too small", pRender->DmaSize));
5779 return STATUS_INVALID_PARAMETER;
5780 }
5781
5782 Assert(pRender->PatchLocationListOutSize == pRender->AllocationListSize);
5783
5784 if (pRender->PatchLocationListOutSize < pRender->AllocationListSize)
5785 {
5786 WARN(("pRender->PatchLocationListOutSize too small %d, requested %d", pRender->PatchLocationListOutSize, pRender->AllocationListSize));
5787 return STATUS_INVALID_PARAMETER;
5788 }
5789
5790 PVBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD pUmCmd = (PVBOXWDDM_DMA_PRIVATEDATA_UM_CHROMIUM_CMD)pInputHdr;
5791 VBOXCMDVBVA_CRCMD* pChromiumCmd = (VBOXCMDVBVA_CRCMD*)pRender->pDmaBufferPrivateData;
5792
5793 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
5794 PVBOXWDDM_DEVICE pDevice = pContext->pDevice;
5795 PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
5796
5797 pChromiumCmd->Hdr.u8OpCode = VBOXCMDVBVA_OPTYPE_CRCMD;
5798 pChromiumCmd->Hdr.u8Flags = 0;
5799 pChromiumCmd->Cmd.cBuffers = pRender->AllocationListSize;
5800
5801 DXGK_ALLOCATIONLIST *pAllocationList = pRender->pAllocationList;
5802 VBOXCMDVBVA_CRCMD_BUFFER *pSubmInfo = pChromiumCmd->Cmd.aBuffers;
5803 PVBOXWDDM_UHGSMI_BUFFER_UI_SUBMIT_INFO pSubmUmInfo = pUmCmd->aBufInfos;
5804
5805 for (UINT i = 0; i < pRender->AllocationListSize; ++i, ++pRender->pPatchLocationListOut, ++pAllocationList, ++pSubmInfo, ++pSubmUmInfo)
5806 {
5807 D3DDDI_PATCHLOCATIONLIST* pPLL = pRender->pPatchLocationListOut;
5808 PVBOXWDDM_ALLOCATION pAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pAllocationList);
5809 if (pSubmUmInfo->offData >= pAlloc->AllocData.SurfDesc.cbSize
5810 || pSubmUmInfo->cbData > pAlloc->AllocData.SurfDesc.cbSize
5811 || pSubmUmInfo->offData + pSubmUmInfo->cbData > pAlloc->AllocData.SurfDesc.cbSize)
5812 {
5813 WARN(("invalid data"));
5814 return STATUS_INVALID_PARAMETER;
5815 }
5816
5817 memset(pPLL, 0, sizeof (*pPLL));
5818
5819 if (pAllocationList->SegmentId)
5820 pSubmInfo->offBuffer = pAllocationList->PhysicalAddress.LowPart + pSubmUmInfo->offData;
5821
5822 pSubmInfo->cbBuffer = pSubmUmInfo->cbData;
5823
5824 pPLL->AllocationIndex = i;
5825 pPLL->PatchOffset = RT_OFFSETOF(VBOXCMDVBVA_CRCMD, Cmd.aBuffers[i].offBuffer);
5826 pPLL->AllocationOffset = pSubmUmInfo->offData;
5827 }
5828
5829 break;
5830 }
5831 case VBOXVDMACMD_TYPE_DMA_NOP:
5832 {
5833 cbBuffer = sizeof (VBOXCMDVBVA_HDR);
5834 cbCmdDma = VBOXWDDM_DUMMY_DMABUFFER_SIZE;
5835
5836 if (pRender->DmaBufferPrivateDataSize < cbBuffer)
5837 {
5838 WARN(("pRender->DmaBufferPrivateDataSize too small %d, requested %d", pRender->DmaBufferPrivateDataSize, cbBuffer));
5839 return STATUS_INVALID_PARAMETER;
5840 }
5841
5842 if (pRender->DmaSize < cbCmdDma)
5843 {
5844 WARN(("dma buffer %d too small", pRender->DmaSize));
5845 return STATUS_INVALID_PARAMETER;
5846 }
5847
5848 pCmd->u8OpCode = VBOXCMDVBVA_OPTYPE_NOPCMD;
5849 pCmd->u8Flags = 0;
5850
5851 for (UINT i = 0; i < pRender->AllocationListSize; ++i, ++pRender->pPatchLocationListOut)
5852 {
5853 D3DDDI_PATCHLOCATIONLIST* pPLL = pRender->pPatchLocationListOut;
5854 memset(pPLL, 0, sizeof (*pPLL));
5855 pPLL->AllocationIndex = i;
5856 pPLL->PatchOffset = ~0UL;
5857 pPLL->AllocationOffset = 0;
5858 }
5859
5860 break;
5861 }
5862 default:
5863 {
5864 WARN(("unsupported render command %d", pInputHdr->enmCmd));
5865 return STATUS_INVALID_PARAMETER;
5866 }
5867 }
5868
5869 pRender->pDmaBufferPrivateData = ((uint8_t*)pRender->pDmaBufferPrivateData) + cbBuffer;
5870 pRender->pDmaBuffer = ((uint8_t*)pRender->pDmaBuffer) + cbCmdDma;
5871
5872 pCmd->u8State = VBOXCMDVBVA_STATE_SUBMITTED;
5873 /* sanity */
5874 pCmd->u32FenceID = 0;
5875
5876// LOGF(("LEAVE, hContext(0x%x)", hContext));
5877
5878 return STATUS_SUCCESS;
5879}
5880
5881static void vboxWddmPatchLocationInit(D3DDDI_PATCHLOCATIONLIST *pPatchLocationListOut, UINT idx, UINT offPatch)
5882{
5883 memset(pPatchLocationListOut, 0, sizeof (*pPatchLocationListOut));
5884 pPatchLocationListOut->AllocationIndex = idx;
5885 pPatchLocationListOut->PatchOffset = offPatch;
5886}
5887
5888static NTSTATUS
5889APIENTRY
5890DxgkDdiRenderLegacy(
5891 CONST HANDLE hContext,
5892 DXGKARG_RENDER *pRender)
5893{
5894// LOGF(("ENTER, hContext(0x%x)", hContext));
5895
5896 Assert(pRender->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR));
5897 if (pRender->DmaBufferPrivateDataSize < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
5898 {
5899 WARN(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_BASEHDR (%d)",
5900 pRender->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
5901 return STATUS_INVALID_PARAMETER;
5902 }
5903 if (pRender->CommandLength < sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR))
5904 {
5905 WARN(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_BASEHDR (%d)",
5906 pRender->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR)));
5907 return STATUS_INVALID_PARAMETER;
5908 }
5909 if (pRender->DmaSize < pRender->CommandLength)
5910 {
5911 WARN(("pRender->DmaSize(%d) < pRender->CommandLength(%d)",
5912 pRender->DmaSize, pRender->CommandLength));
5913 return STATUS_INVALID_PARAMETER;
5914 }
5915 if (pRender->PatchLocationListOutSize < pRender->PatchLocationListInSize)
5916 {
5917 WARN(("pRender->PatchLocationListOutSize(%d) < pRender->PatchLocationListInSize(%d)",
5918 pRender->PatchLocationListOutSize, pRender->PatchLocationListInSize));
5919 return STATUS_INVALID_PARAMETER;
5920 }
5921 if (pRender->AllocationListSize != pRender->PatchLocationListInSize)
5922 {
5923 WARN(("pRender->AllocationListSize(%d) != pRender->PatchLocationListInSize(%d)",
5924 pRender->AllocationListSize, pRender->PatchLocationListInSize));
5925 return STATUS_INVALID_PARAMETER;
5926 }
5927
5928 NTSTATUS Status = STATUS_SUCCESS;
5929
5930 __try
5931 {
5932 PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR pInputHdr = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)pRender->pCommand;
5933 switch (pInputHdr->enmCmd)
5934 {
5935 case VBOXVDMACMD_TYPE_DMA_NOP:
5936 {
5937 PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR pPrivateData = (PVBOXWDDM_DMA_PRIVATEDATA_BASEHDR)pRender->pDmaBufferPrivateData;
5938 pPrivateData->enmCmd = VBOXVDMACMD_TYPE_DMA_NOP;
5939 pRender->pDmaBufferPrivateData = (uint8_t*)pRender->pDmaBufferPrivateData + sizeof (VBOXWDDM_DMA_PRIVATEDATA_BASEHDR);
5940 pRender->pDmaBuffer = ((uint8_t*)pRender->pDmaBuffer) + pRender->CommandLength;
5941 for (UINT i = 0; i < pRender->PatchLocationListInSize; ++i)
5942 {
5943 UINT offPatch = i * 4;
5944 if (offPatch + 4 > pRender->CommandLength)
5945 {
5946 WARN(("wrong offPatch"));
5947 return STATUS_INVALID_PARAMETER;
5948 }
5949 if (offPatch != pRender->pPatchLocationListIn[i].PatchOffset)
5950 {
5951 WARN(("wrong PatchOffset"));
5952 return STATUS_INVALID_PARAMETER;
5953 }
5954 if (i != pRender->pPatchLocationListIn[i].AllocationIndex)
5955 {
5956 WARN(("wrong AllocationIndex"));
5957 return STATUS_INVALID_PARAMETER;
5958 }
5959 vboxWddmPatchLocationInit(&pRender->pPatchLocationListOut[i], i, offPatch);
5960 }
5961 break;
5962 }
5963 default:
5964 {
5965 WARN(("unsupported command %d", pInputHdr->enmCmd));
5966 return STATUS_INVALID_PARAMETER;
5967 }
5968 }
5969 }
5970 __except (EXCEPTION_EXECUTE_HANDLER)
5971 {
5972 Status = STATUS_INVALID_PARAMETER;
5973 WARN(("invalid parameter"));
5974 }
5975// LOGF(("LEAVE, hContext(0x%x)", hContext));
5976
5977 return Status;
5978}
5979
5980#define VBOXVDMACMD_DMA_PRESENT_BLT_MINSIZE() (VBOXVDMACMD_SIZE(VBOXVDMACMD_DMA_PRESENT_BLT))
5981#define VBOXVDMACMD_DMA_PRESENT_BLT_SIZE(_c) (VBOXVDMACMD_BODY_FIELD_OFFSET(UINT, VBOXVDMACMD_DMA_PRESENT_BLT, aDstSubRects[_c]))
5982
5983#ifdef VBOX_WITH_VDMA
5984DECLINLINE(VOID) vboxWddmRectlFromRect(const RECT *pRect, PVBOXVDMA_RECTL pRectl)
5985{
5986 pRectl->left = (int16_t)pRect->left;
5987 pRectl->width = (uint16_t)(pRect->right - pRect->left);
5988 pRectl->top = (int16_t)pRect->top;
5989 pRectl->height = (uint16_t)(pRect->bottom - pRect->top);
5990}
5991
5992DECLINLINE(VBOXVDMA_PIXEL_FORMAT) vboxWddmFromPixFormat(D3DDDIFORMAT format)
5993{
5994 return (VBOXVDMA_PIXEL_FORMAT)format;
5995}
5996
5997DECLINLINE(VOID) vboxWddmSurfDescFromAllocation(PVBOXWDDM_ALLOCATION pAllocation, PVBOXVDMA_SURF_DESC pDesc)
5998{
5999 pDesc->width = pAllocation->AllocData.SurfDesc.width;
6000 pDesc->height = pAllocation->AllocData.SurfDesc.height;
6001 pDesc->format = vboxWddmFromPixFormat(pAllocation->AllocData.SurfDesc.format);
6002 pDesc->bpp = pAllocation->AllocData.SurfDesc.bpp;
6003 pDesc->pitch = pAllocation->AllocData.SurfDesc.pitch;
6004 pDesc->fFlags = 0;
6005}
6006#endif
6007
6008DECLINLINE(BOOLEAN) vboxWddmPixFormatConversionSupported(D3DDDIFORMAT From, D3DDDIFORMAT To)
6009{
6010 Assert(From != D3DDDIFMT_UNKNOWN);
6011 Assert(To != D3DDDIFMT_UNKNOWN);
6012 Assert(From == To);
6013 return From == To;
6014}
6015
6016DECLINLINE(bool) VBoxCVDdiFillAllocInfo(VBOXCMDVBVA_HDR* pHdr,
6017 VBOXCMDVBVA_ALLOCINFO *pInfo, PVBOXWDDM_ALLOCATION pAlloc, DXGK_ALLOCATIONLIST *pList, bool fDst)
6018{
6019 if (pAlloc->AllocData.hostID)
6020 {
6021 pHdr->u8Flags |= (fDst ? VBOXCMDVBVA_OPF_ALLOC_DSTID : VBOXCMDVBVA_OPF_ALLOC_SRCID);
6022 pInfo->id = pAlloc->AllocData.hostID;
6023 return false;
6024 }
6025
6026 Assert(!pList->PhysicalAddress.HighPart);
6027 pInfo->offVRAM = pList->PhysicalAddress.LowPart;
6028 return true;
6029}
6030
6031/**
6032 * DxgkDdiPresent
6033 */
6034static NTSTATUS
6035APIENTRY
6036DxgkDdiPresentNew(
6037 CONST HANDLE hContext,
6038 DXGKARG_PRESENT *pPresent)
6039{
6040 PAGED_CODE();
6041
6042// LOGF(("ENTER, hContext(0x%x)", hContext));
6043
6044 vboxVDbgBreakFv();
6045
6046 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
6047 PVBOXWDDM_DEVICE pDevice = pContext->pDevice;
6048 PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
6049
6050 if (pPresent->DmaBufferPrivateDataSize < sizeof (VBOXCMDVBVA_HDR))
6051 {
6052 WARN(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXCMDVBVA_HDR (%d)", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXCMDVBVA_HDR)));
6053 /* @todo: can this actually happen? what status to return? */
6054 return STATUS_INVALID_PARAMETER;
6055 }
6056
6057 VBOXCMDVBVA_HDR* pHdr = (VBOXCMDVBVA_HDR*)pPresent->pDmaBufferPrivateData;
6058
6059 UINT u32SrcPatch = ~0UL;
6060 UINT u32DstPatch = ~0UL;
6061 BOOLEAN fPatchSrc = false;
6062 BOOLEAN fPatchDst = false;
6063 VBOXCMDVBVA_RECT *paRects = NULL;
6064 uint32_t cbMaxRects;
6065
6066 if (pPresent->DmaSize < VBOXWDDM_DUMMY_DMABUFFER_SIZE)
6067 {
6068 WARN(("Present->DmaSize(%d) < VBOXWDDM_DUMMY_DMABUFFER_SIZE (%d)", pPresent->DmaSize , VBOXWDDM_DUMMY_DMABUFFER_SIZE));
6069 /* @todo: can this actually happen? what status to return? */
6070 return STATUS_INVALID_PARAMETER;
6071 }
6072
6073 if (pPresent->Flags.Blt)
6074 {
6075 Assert(pPresent->Flags.Value == 1); /* only Blt is set, we do not support anything else for now */
6076 DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
6077 DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
6078 PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pSrc);
6079 if (!pSrcAlloc)
6080 {
6081 /* this should not happen actually */
6082 WARN(("failed to get Src Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
6083 return STATUS_INVALID_HANDLE;
6084 }
6085
6086 PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pDst);
6087 if (!pDstAlloc)
6088 {
6089 /* this should not happen actually */
6090 WARN(("failed to get Dst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
6091 return STATUS_INVALID_HANDLE;
6092 }
6093
6094 fPatchSrc = TRUE;
6095 fPatchDst = TRUE;
6096
6097 BOOLEAN fDstPrimary = (!pDstAlloc->AllocData.hostID
6098 && pDstAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
6099 && pDstAlloc->bAssigned);
6100 BOOLEAN fSrcPrimary = (!pSrcAlloc->AllocData.hostID
6101 && pSrcAlloc->enmType == VBOXWDDM_ALLOC_TYPE_STD_SHAREDPRIMARYSURFACE
6102 && pSrcAlloc->bAssigned);
6103
6104 pHdr->u8OpCode = VBOXCMDVBVA_OPTYPE_BLT_OFFPRIMSZFMT_OR_ID;
6105 pHdr->u8Flags = 0;
6106
6107 if (fDstPrimary || fSrcPrimary)
6108 {
6109 if (pPresent->DmaBufferPrivateDataSize < sizeof (VBOXCMDVBVA_BLT_PRIMARY))
6110 {
6111 WARN(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXCMDVBVA_BLT_PRIMARY (%d)", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXCMDVBVA_BLT_PRIMARY)));
6112 /* @todo: can this actually happen? what status to return? */
6113 return STATUS_INVALID_PARAMETER;
6114 }
6115
6116 VBOXCMDVBVA_BLT_PRIMARY *pBlt = (VBOXCMDVBVA_BLT_PRIMARY*)pHdr;
6117
6118 /* this is the most common case, so we optimize it a bit with VBOXCMDVBVA_BLT_PRIMARY */
6119
6120 if (fSrcPrimary)
6121 {
6122 pBlt->Hdr.u8Flags |= VBOXCMDVBVA_OPF_ALLOC_SRCPRIMARY;
6123 pBlt->Hdr.u8PrimaryID = pSrcAlloc->AllocData.SurfDesc.VidPnSourceId;
6124
6125 if (fDstPrimary)
6126 {
6127 pBlt->Hdr.u8Flags |= VBOXCMDVBVA_OPF_ALLOC_DSTPRIMARY;
6128 pBlt->alloc.id = pDstAlloc->AllocData.SurfDesc.VidPnSourceId;
6129 }
6130 else if (VBoxCVDdiFillAllocInfo(pHdr, &pBlt->alloc, pDstAlloc, pDst, true))
6131 u32DstPatch = RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, alloc.offVRAM);
6132 }
6133 else
6134 {
6135 Assert(fDstPrimary);
6136 pBlt->Hdr.u8Flags |= VBOXCMDVBVA_OPF_ALLOC_DSTPRIMARY;
6137 pBlt->Hdr.u8PrimaryID = pDstAlloc->AllocData.SurfDesc.VidPnSourceId;
6138
6139 if (VBoxCVDdiFillAllocInfo(pHdr, &pBlt->alloc, pSrcAlloc, pSrc, false))
6140 u32SrcPatch = RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, alloc.offVRAM);
6141 }
6142
6143 pBlt->Pos.x = (int16_t)(pPresent->DstRect.left - pPresent->SrcRect.left);
6144 pBlt->Pos.y = (int16_t)(pPresent->DstRect.top - pPresent->SrcRect.top);
6145
6146 paRects = pBlt->aRects;
6147 cbMaxRects = pPresent->DmaBufferPrivateDataSize - RT_OFFSETOF(VBOXCMDVBVA_BLT_PRIMARY, aRects);
6148 }
6149 else
6150 {
6151 if (pPresent->DmaBufferPrivateDataSize < sizeof (VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID))
6152 {
6153 WARN(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID (%d)", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID)));
6154 /* @todo: can this actually happen? what status to return? */
6155 return STATUS_INVALID_PARAMETER;
6156 }
6157
6158 VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID *pBlt = (VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID*)pHdr;
6159
6160 if (VBoxCVDdiFillAllocInfo(pHdr, &pBlt->src, pSrcAlloc, pSrc, false))
6161 u32SrcPatch = RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, src.offVRAM);
6162
6163 if (VBoxCVDdiFillAllocInfo(pHdr, &pBlt->dst, pDstAlloc, pDst, true))
6164 u32DstPatch = RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, dst.offVRAM);
6165
6166 pBlt->Pos.x = (int16_t)(pPresent->DstRect.left - pPresent->SrcRect.left);
6167 pBlt->Pos.y = (int16_t)(pPresent->DstRect.top - pPresent->SrcRect.top);
6168
6169 paRects = pBlt->aRects;
6170 cbMaxRects = pPresent->DmaBufferPrivateDataSize - RT_OFFSETOF(VBOXCMDVBVA_BLT_OFFPRIMSZFMT_OR_ID, aRects);
6171 }
6172 }
6173 else if (pPresent->Flags.Flip)
6174 {
6175 if (pPresent->DmaBufferPrivateDataSize < sizeof (VBOXCMDVBVA_FLIP))
6176 {
6177 WARN(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXCMDVBVA_FLIP (%d)", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXCMDVBVA_FLIP)));
6178 /* @todo: can this actually happen? what status to return? */
6179 return STATUS_INVALID_PARAMETER;
6180 }
6181
6182 fPatchSrc = TRUE;
6183
6184 Assert(pPresent->Flags.Value == 4); /* only Blt is set, we do not support anything else for now */
6185 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D);
6186 DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
6187 PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pSrc);
6188
6189 if (!pSrcAlloc)
6190 {
6191 /* this should not happen actually */
6192 WARN(("failed to get pSrc Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
6193 return STATUS_INVALID_HANDLE;
6194 }
6195
6196 Assert(pDevExt->cContexts3D);
6197 pHdr->u8OpCode = VBOXCMDVBVA_OPTYPE_FLIP;
6198 pHdr->u8Flags = 0;
6199 VBOXCMDVBVA_FLIP *pFlip = (VBOXCMDVBVA_FLIP*)pHdr;
6200
6201 if (VBoxCVDdiFillAllocInfo(pHdr, &pFlip->src, pSrcAlloc, pSrc, false))
6202 u32SrcPatch = RT_OFFSETOF(VBOXCMDVBVA_FLIP, src.offVRAM);
6203 }
6204 else if (pPresent->Flags.ColorFill)
6205 {
6206 if (pPresent->DmaBufferPrivateDataSize < sizeof (VBOXCMDVBVA_CLRFILL))
6207 {
6208 WARN(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXCMDVBVA_CLRFILL (%d)", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXCMDVBVA_CLRFILL)));
6209 /* @todo: can this actually happen? what status to return? */
6210 return STATUS_INVALID_PARAMETER;
6211 }
6212
6213 fPatchDst = TRUE;
6214
6215 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D);
6216 Assert(pPresent->Flags.Value == 2); /* only ColorFill is set, we do not support anything else for now */
6217 DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
6218 PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pDst);
6219 if (!pDstAlloc)
6220 {
6221 /* this should not happen actually */
6222 WARN(("failed to get pDst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
6223 return STATUS_INVALID_HANDLE;
6224 }
6225
6226 pHdr->u8OpCode = VBOXCMDVBVA_OPTYPE_CLRFILL;
6227 pHdr->u8Flags = 0;
6228 VBOXCMDVBVA_CLRFILL *pCFill = (VBOXCMDVBVA_CLRFILL*)pHdr;
6229
6230 if (VBoxCVDdiFillAllocInfo(pHdr, &pCFill->dst, pDstAlloc, pDst, true))
6231 u32DstPatch = RT_OFFSETOF(VBOXCMDVBVA_CLRFILL, dst.offVRAM);
6232
6233 paRects = pCFill->aRects;
6234 cbMaxRects = pPresent->DmaBufferPrivateDataSize - RT_OFFSETOF(VBOXCMDVBVA_CLRFILL, aRects);
6235 }
6236 else
6237 {
6238 WARN(("cmd NOT IMPLEMENTED!! Flags(0x%x)", pPresent->Flags.Value));
6239 return STATUS_NOT_SUPPORTED;
6240 }
6241
6242 if (paRects)
6243 {
6244 UINT iStartRect = pPresent->MultipassOffset;
6245 UINT cMaxRects = cbMaxRects / sizeof (VBOXCMDVBVA_RECT);
6246 Assert(pPresent->SubRectCnt > iStartRect);
6247 UINT cRects = pPresent->SubRectCnt - iStartRect;
6248 if (cRects > cMaxRects)
6249 {
6250 pPresent->MultipassOffset += cMaxRects;
6251 cRects = cMaxRects;
6252 }
6253 else
6254 pPresent->MultipassOffset = 0;
6255
6256 const RECT *paDstSubRects = &pPresent->pDstSubRects[iStartRect];
6257 VBoxCVDdiPackRects(paRects, paDstSubRects, cRects);
6258 }
6259
6260 if (fPatchSrc)
6261 {
6262 memset(pPresent->pPatchLocationListOut, 0, sizeof (D3DDDI_PATCHLOCATIONLIST));
6263 pPresent->pPatchLocationListOut->PatchOffset = u32SrcPatch;
6264 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
6265 ++pPresent->pPatchLocationListOut;
6266 }
6267
6268 if (fPatchDst)
6269 {
6270 memset(pPresent->pPatchLocationListOut, 0, sizeof (D3DDDI_PATCHLOCATIONLIST));
6271 pPresent->pPatchLocationListOut->PatchOffset = u32DstPatch;
6272 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
6273 ++pPresent->pPatchLocationListOut;
6274 }
6275
6276 pHdr->u8State = VBOXCMDVBVA_STATE_SUBMITTED;
6277 /* sanity */
6278 pHdr->u32FenceID = 0;
6279
6280 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
6281
6282 if (pPresent->MultipassOffset)
6283 return STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
6284 return STATUS_SUCCESS;
6285}
6286
6287/**
6288 * DxgkDdiPresent
6289 */
6290static NTSTATUS
6291APIENTRY
6292DxgkDdiPresentLegacy(
6293 CONST HANDLE hContext,
6294 DXGKARG_PRESENT *pPresent)
6295{
6296 PAGED_CODE();
6297
6298// LOGF(("ENTER, hContext(0x%x)", hContext));
6299
6300 vboxVDbgBreakFv();
6301
6302 NTSTATUS Status = STATUS_SUCCESS;
6303 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
6304 PVBOXWDDM_DEVICE pDevice = pContext->pDevice;
6305 PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
6306
6307 Assert(pPresent->DmaBufferPrivateDataSize >= sizeof (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR));
6308 if (pPresent->DmaBufferPrivateDataSize < sizeof (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR))
6309 {
6310 LOGREL(("Present->DmaBufferPrivateDataSize(%d) < sizeof VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR (%d)", pPresent->DmaBufferPrivateDataSize , sizeof (VBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR)));
6311 /* @todo: can this actually happen? what status tu return? */
6312 return STATUS_INVALID_PARAMETER;
6313 }
6314
6315 PVBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR pPrivateData = (PVBOXWDDM_DMA_PRIVATEDATA_PRESENTHDR)pPresent->pDmaBufferPrivateData;
6316 pPrivateData->BaseHdr.fFlags.Value = 0;
6317 uint32_t cContexts2D = ASMAtomicReadU32(&pDevExt->cContexts2D);
6318
6319 if (pPresent->Flags.Blt)
6320 {
6321 Assert(pPresent->Flags.Value == 1); /* only Blt is set, we do not support anything else for now */
6322 DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
6323 DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
6324 PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pSrc);
6325 if (!pSrcAlloc)
6326 {
6327 /* this should not happen actually */
6328 WARN(("failed to get Src Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
6329 Status = STATUS_INVALID_HANDLE;
6330 goto done;
6331 }
6332
6333 PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pDst);
6334 if (!pDstAlloc)
6335 {
6336 /* this should not happen actually */
6337 WARN(("failed to get Dst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
6338 Status = STATUS_INVALID_HANDLE;
6339 goto done;
6340 }
6341
6342
6343 UINT cbCmd = pPresent->DmaBufferPrivateDataSize;
6344 pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_BLT;
6345
6346 PVBOXWDDM_DMA_PRIVATEDATA_BLT pBlt = (PVBOXWDDM_DMA_PRIVATEDATA_BLT)pPrivateData;
6347
6348 vboxWddmPopulateDmaAllocInfo(&pBlt->Blt.SrcAlloc, pSrcAlloc, pSrc);
6349 vboxWddmPopulateDmaAllocInfo(&pBlt->Blt.DstAlloc, pDstAlloc, pDst);
6350
6351 ASSERT_WARN(!pSrcAlloc->fRcFlags.SharedResource, ("Shared Allocatoin used in Present!"));
6352
6353 pBlt->Blt.SrcRect = pPresent->SrcRect;
6354 pBlt->Blt.DstRects.ContextRect = pPresent->DstRect;
6355 pBlt->Blt.DstRects.UpdateRects.cRects = 0;
6356 UINT cbHead = RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_BLT, Blt.DstRects.UpdateRects.aRects[0]);
6357 Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
6358 UINT cbRects = (pPresent->SubRectCnt - pPresent->MultipassOffset) * sizeof (RECT);
6359 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbHead + cbRects;
6360 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
6361 Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
6362 cbCmd -= cbHead;
6363 Assert(cbCmd < UINT32_MAX/2);
6364 Assert(cbCmd > sizeof (RECT));
6365 if (cbCmd >= cbRects)
6366 {
6367 cbCmd -= cbRects;
6368 memcpy(&pBlt->Blt.DstRects.UpdateRects.aRects[pPresent->MultipassOffset], &pPresent->pDstSubRects[pPresent->MultipassOffset], cbRects);
6369 pBlt->Blt.DstRects.UpdateRects.cRects += cbRects/sizeof (RECT);
6370 }
6371 else
6372 {
6373 UINT cbFitingRects = (cbCmd/sizeof (RECT)) * sizeof (RECT);
6374 Assert(cbFitingRects);
6375 memcpy(&pBlt->Blt.DstRects.UpdateRects.aRects[pPresent->MultipassOffset], &pPresent->pDstSubRects[pPresent->MultipassOffset], cbFitingRects);
6376 cbCmd -= cbFitingRects;
6377 pPresent->MultipassOffset += cbFitingRects/sizeof (RECT);
6378 pBlt->Blt.DstRects.UpdateRects.cRects += cbFitingRects/sizeof (RECT);
6379 Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
6380 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
6381 }
6382
6383 memset(pPresent->pPatchLocationListOut, 0, 2*sizeof (D3DDDI_PATCHLOCATIONLIST));
6384 pPresent->pPatchLocationListOut->PatchOffset = 0;
6385 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
6386 ++pPresent->pPatchLocationListOut;
6387 pPresent->pPatchLocationListOut->PatchOffset = 4;
6388 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
6389 ++pPresent->pPatchLocationListOut;
6390 }
6391 else if (pPresent->Flags.Flip)
6392 {
6393 Assert(pPresent->Flags.Value == 4); /* only Blt is set, we do not support anything else for now */
6394 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D);
6395 DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
6396 PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pSrc);
6397
6398 if (!pSrcAlloc)
6399 {
6400 /* this should not happen actually */
6401 WARN(("failed to get pSrc Allocation info for hDeviceSpecificAllocation(0x%x)",pSrc->hDeviceSpecificAllocation));
6402 Status = STATUS_INVALID_HANDLE;
6403 goto done;
6404 }
6405
6406 Assert(pDevExt->cContexts3D);
6407 pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_FLIP;
6408 PVBOXWDDM_DMA_PRIVATEDATA_FLIP pFlip = (PVBOXWDDM_DMA_PRIVATEDATA_FLIP)pPrivateData;
6409
6410 vboxWddmPopulateDmaAllocInfo(&pFlip->Flip.Alloc, pSrcAlloc, pSrc);
6411
6412 UINT cbCmd = sizeof (VBOXWDDM_DMA_PRIVATEDATA_FLIP);
6413 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbCmd;
6414 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
6415 Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
6416
6417 memset(pPresent->pPatchLocationListOut, 0, sizeof (D3DDDI_PATCHLOCATIONLIST));
6418 pPresent->pPatchLocationListOut->PatchOffset = 0;
6419 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_SOURCE_INDEX;
6420 ++pPresent->pPatchLocationListOut;
6421 }
6422 else if (pPresent->Flags.ColorFill)
6423 {
6424 Assert(pContext->enmType == VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D);
6425 Assert(pPresent->Flags.Value == 2); /* only ColorFill is set, we do not support anything else for now */
6426 DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
6427 PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDevExt, pDst);
6428 if (!pDstAlloc)
6429 {
6430
6431 /* this should not happen actually */
6432 WARN(("failed to get pDst Allocation info for hDeviceSpecificAllocation(0x%x)",pDst->hDeviceSpecificAllocation));
6433 Status = STATUS_INVALID_HANDLE;
6434 goto done;
6435 }
6436
6437 UINT cbCmd = pPresent->DmaBufferPrivateDataSize;
6438 pPrivateData->BaseHdr.enmCmd = VBOXVDMACMD_TYPE_DMA_PRESENT_CLRFILL;
6439 PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL pCF = (PVBOXWDDM_DMA_PRIVATEDATA_CLRFILL)pPrivateData;
6440
6441 vboxWddmPopulateDmaAllocInfo(&pCF->ClrFill.Alloc, pDstAlloc, pDst);
6442
6443 pCF->ClrFill.Color = pPresent->Color;
6444 pCF->ClrFill.Rects.cRects = 0;
6445 UINT cbHead = RT_OFFSETOF(VBOXWDDM_DMA_PRIVATEDATA_CLRFILL, ClrFill.Rects.aRects[0]);
6446 Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
6447 UINT cbRects = (pPresent->SubRectCnt - pPresent->MultipassOffset) * sizeof (RECT);
6448 pPresent->pDmaBufferPrivateData = (uint8_t*)pPresent->pDmaBufferPrivateData + cbHead + cbRects;
6449 pPresent->pDmaBuffer = ((uint8_t*)pPresent->pDmaBuffer) + VBOXWDDM_DUMMY_DMABUFFER_SIZE;
6450 Assert(pPresent->DmaSize >= VBOXWDDM_DUMMY_DMABUFFER_SIZE);
6451 cbCmd -= cbHead;
6452 Assert(cbCmd < UINT32_MAX/2);
6453 Assert(cbCmd > sizeof (RECT));
6454 if (cbCmd >= cbRects)
6455 {
6456 cbCmd -= cbRects;
6457 memcpy(&pCF->ClrFill.Rects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbRects);
6458 pCF->ClrFill.Rects.cRects += cbRects/sizeof (RECT);
6459 }
6460 else
6461 {
6462 UINT cbFitingRects = (cbCmd/sizeof (RECT)) * sizeof (RECT);
6463 Assert(cbFitingRects);
6464 memcpy(&pCF->ClrFill.Rects.aRects[pPresent->MultipassOffset], pPresent->pDstSubRects, cbFitingRects);
6465 cbCmd -= cbFitingRects;
6466 pPresent->MultipassOffset += cbFitingRects/sizeof (RECT);
6467 pCF->ClrFill.Rects.cRects += cbFitingRects/sizeof (RECT);
6468 Assert(pPresent->SubRectCnt > pPresent->MultipassOffset);
6469 Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
6470 }
6471
6472 memset(pPresent->pPatchLocationListOut, 0, sizeof (D3DDDI_PATCHLOCATIONLIST));
6473 pPresent->pPatchLocationListOut->PatchOffset = 0;
6474 pPresent->pPatchLocationListOut->AllocationIndex = DXGK_PRESENT_DESTINATION_INDEX;
6475 ++pPresent->pPatchLocationListOut;
6476 }
6477 else
6478 {
6479 WARN(("cmd NOT IMPLEMENTED!! Flags(0x%x)", pPresent->Flags.Value));
6480 Status = STATUS_NOT_SUPPORTED;
6481 }
6482
6483done:
6484// LOGF(("LEAVE, hContext(0x%x), Status(0x%x)", hContext, Status));
6485
6486 return Status;
6487}
6488
6489NTSTATUS
6490APIENTRY
6491DxgkDdiUpdateOverlay(
6492 CONST HANDLE hOverlay,
6493 CONST DXGKARG_UPDATEOVERLAY *pUpdateOverlay)
6494{
6495 LOGF(("ENTER, hOverlay(0x%p)", hOverlay));
6496
6497 NTSTATUS Status = STATUS_SUCCESS;
6498 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)hOverlay;
6499 Assert(pOverlay);
6500 int rc = vboxVhwaHlpOverlayUpdate(pOverlay, &pUpdateOverlay->OverlayInfo);
6501 AssertRC(rc);
6502 if (RT_SUCCESS(rc))
6503 {
6504 RECT DstRect;
6505 vboxVhwaHlpOverlayDstRectGet(pOverlay->pDevExt, pOverlay, &DstRect);
6506 Status = vboxVdmaHlpUpdatePrimary(pOverlay->pDevExt, pOverlay->VidPnSourceId, &DstRect);
6507 Assert(Status == STATUS_SUCCESS);
6508 }
6509 else
6510 Status = STATUS_UNSUCCESSFUL;
6511
6512 LOGF(("LEAVE, hOverlay(0x%p)", hOverlay));
6513
6514 return Status;
6515}
6516
6517NTSTATUS
6518APIENTRY
6519DxgkDdiFlipOverlay(
6520 CONST HANDLE hOverlay,
6521 CONST DXGKARG_FLIPOVERLAY *pFlipOverlay)
6522{
6523 LOGF(("ENTER, hOverlay(0x%p)", hOverlay));
6524
6525 NTSTATUS Status = STATUS_SUCCESS;
6526 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)hOverlay;
6527 Assert(pOverlay);
6528 int rc = vboxVhwaHlpOverlayFlip(pOverlay, pFlipOverlay);
6529 AssertRC(rc);
6530 if (RT_FAILURE(rc))
6531 Status = STATUS_UNSUCCESSFUL;
6532
6533 LOGF(("LEAVE, hOverlay(0x%p)", hOverlay));
6534
6535 return Status;
6536}
6537
6538NTSTATUS
6539APIENTRY
6540DxgkDdiDestroyOverlay(
6541 CONST HANDLE hOverlay)
6542{
6543 LOGF(("ENTER, hOverlay(0x%p)", hOverlay));
6544
6545 NTSTATUS Status = STATUS_SUCCESS;
6546 PVBOXWDDM_OVERLAY pOverlay = (PVBOXWDDM_OVERLAY)hOverlay;
6547 Assert(pOverlay);
6548 int rc = vboxVhwaHlpOverlayDestroy(pOverlay);
6549 AssertRC(rc);
6550 if (RT_SUCCESS(rc))
6551 vboxWddmMemFree(pOverlay);
6552 else
6553 Status = STATUS_UNSUCCESSFUL;
6554
6555 LOGF(("LEAVE, hOverlay(0x%p)", hOverlay));
6556
6557 return Status;
6558}
6559
6560/**
6561 * DxgkDdiCreateContext
6562 */
6563NTSTATUS
6564APIENTRY
6565DxgkDdiCreateContext(
6566 CONST HANDLE hDevice,
6567 DXGKARG_CREATECONTEXT *pCreateContext)
6568{
6569 /* DxgkDdiCreateContext should be made pageable */
6570 PAGED_CODE();
6571
6572 LOGF(("ENTER, hDevice(0x%x)", hDevice));
6573
6574 vboxVDbgBreakFv();
6575
6576 if (pCreateContext->NodeOrdinal >= VBOXWDDM_NUM_NODES)
6577 {
6578 WARN(("Invalid NodeOrdinal (%d), expected to be less that (%d)\n", pCreateContext->NodeOrdinal, VBOXWDDM_NUM_NODES));
6579 return STATUS_INVALID_PARAMETER;
6580 }
6581
6582 NTSTATUS Status = STATUS_SUCCESS;
6583 PVBOXWDDM_DEVICE pDevice = (PVBOXWDDM_DEVICE)hDevice;
6584 PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
6585 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)vboxWddmMemAllocZero(sizeof (VBOXWDDM_CONTEXT));
6586 Assert(pContext);
6587 if (pContext)
6588 {
6589 pContext->pDevice = pDevice;
6590 pContext->hContext = pCreateContext->hContext;
6591 pContext->EngineAffinity = pCreateContext->EngineAffinity;
6592 pContext->NodeOrdinal = pCreateContext->NodeOrdinal;
6593 vboxVideoCmCtxInitEmpty(&pContext->CmContext);
6594 if (pCreateContext->Flags.SystemContext || pCreateContext->PrivateDriverDataSize == 0)
6595 {
6596 Assert(pCreateContext->PrivateDriverDataSize == 0);
6597 Assert(!pCreateContext->pPrivateDriverData);
6598 Assert(pCreateContext->Flags.Value <= 2); /* 2 is a GDI context in Win7 */
6599 pContext->enmType = VBOXWDDM_CONTEXT_TYPE_SYSTEM;
6600 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
6601 {
6602 pDevExt->aSources[i].u8SyncState = 0;
6603 NTSTATUS tmpStatus= vboxWddmDisplaySettingsQueryPos(pDevExt, i, &pDevExt->aSources[i].VScreenPos);
6604 Assert(tmpStatus == STATUS_SUCCESS);
6605 }
6606
6607 if (!VBOXWDDM_IS_DISPLAYONLY() && pDevExt->f3DEnabled)
6608 {
6609 VBoxMpCrPackerInit(&pContext->CrPacker);
6610 int rc = VBoxMpCrCtlConConnect(&pDevExt->CrCtlCon, CR_PROTOCOL_VERSION_MAJOR, CR_PROTOCOL_VERSION_MINOR, &pContext->u32CrConClientID);
6611 if (!RT_SUCCESS(rc))
6612 WARN(("VBoxMpCrCtlConConnect failed rc (%d), ignoring for system context", rc));
6613 }
6614
6615 Status = STATUS_SUCCESS;
6616 }
6617 else
6618 {
6619 Assert(pCreateContext->Flags.Value == 0);
6620 Assert(pCreateContext->PrivateDriverDataSize == sizeof (VBOXWDDM_CREATECONTEXT_INFO));
6621 Assert(pCreateContext->pPrivateDriverData);
6622 if (pCreateContext->PrivateDriverDataSize == sizeof (VBOXWDDM_CREATECONTEXT_INFO))
6623 {
6624 PVBOXWDDM_CREATECONTEXT_INFO pInfo = (PVBOXWDDM_CREATECONTEXT_INFO)pCreateContext->pPrivateDriverData;
6625 switch (pInfo->enmType)
6626 {
6627 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D:
6628 {
6629 Status = vboxVideoAMgrCtxCreate(&pDevExt->AllocMgr, &pContext->AllocContext);
6630 Assert(Status == STATUS_SUCCESS);
6631 if (Status == STATUS_SUCCESS)
6632 {
6633 Status = vboxWddmSwapchainCtxInit(pDevExt, pContext);
6634 Assert(Status == STATUS_SUCCESS);
6635 if (Status == STATUS_SUCCESS)
6636 {
6637 pContext->enmType = VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D;
6638 Status = vboxVideoCmCtxAdd(&pDevice->pAdapter->CmMgr, &pContext->CmContext, (HANDLE)pInfo->hUmEvent, pInfo->u64UmInfo);
6639 Assert(Status == STATUS_SUCCESS);
6640 if (Status == STATUS_SUCCESS)
6641 {
6642 if (pInfo->crVersionMajor || pInfo->crVersionMinor)
6643 {
6644 if (pDevExt->f3DEnabled)
6645 {
6646 int rc = VBoxMpCrCtlConConnect(&pDevExt->CrCtlCon,
6647 pInfo->crVersionMajor, pInfo->crVersionMinor,
6648 &pContext->u32CrConClientID);
6649 if (RT_SUCCESS(rc))
6650 {
6651 VBoxMpCrPackerInit(&pContext->CrPacker);
6652 }
6653 else
6654 {
6655 WARN(("VBoxMpCrCtlConConnect failed rc (%d)", rc));
6656 Status = STATUS_UNSUCCESSFUL;
6657 }
6658 }
6659 else
6660 {
6661 LOG(("3D Not Enabled, failing 3D context creation"));
6662 Status = STATUS_UNSUCCESSFUL;
6663 }
6664 }
6665
6666 if (NT_SUCCESS(Status))
6667 {
6668 ASMAtomicIncU32(&pDevExt->cContexts3D);
6669 break;
6670 }
6671 }
6672
6673 vboxWddmSwapchainCtxTerm(pDevExt, pContext);
6674 }
6675 vboxVideoAMgrCtxDestroy(&pContext->AllocContext);
6676 }
6677 break;
6678 }
6679 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_3D:
6680 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_GL:
6681 {
6682 pContext->enmType = pInfo->enmType;
6683 Status = vboxVideoAMgrCtxCreate(&pDevExt->AllocMgr, &pContext->AllocContext);
6684 Assert(Status == STATUS_SUCCESS);
6685 if (Status == STATUS_SUCCESS)
6686 {
6687 if (pInfo->crVersionMajor || pInfo->crVersionMinor)
6688 {
6689 if (pDevExt->f3DEnabled)
6690 {
6691 int rc = VBoxMpCrCtlConConnect(&pDevExt->CrCtlCon,
6692 pInfo->crVersionMajor, pInfo->crVersionMinor,
6693 &pContext->u32CrConClientID);
6694 if (!RT_SUCCESS(rc))
6695 {
6696 WARN(("VBoxMpCrCtlConConnect failed rc (%d)", rc));
6697 Status = STATUS_UNSUCCESSFUL;
6698 }
6699 }
6700 else
6701 {
6702 LOG(("3D Not Enabled, failing 3D (hgsmi) context creation"));
6703 Status = STATUS_UNSUCCESSFUL;
6704 }
6705 }
6706
6707 if (NT_SUCCESS(Status))
6708 {
6709 ASMAtomicIncU32(&pDevExt->cContexts3D);
6710 break;
6711 }
6712 vboxVideoAMgrCtxDestroy(&pContext->AllocContext);
6713 }
6714 break;
6715 }
6716 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D:
6717 {
6718 pContext->enmType = pInfo->enmType;
6719 ASMAtomicIncU32(&pDevExt->cContexts2D);
6720 break;
6721 }
6722 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_RESIZE:
6723 {
6724 pContext->enmType = pInfo->enmType;
6725 ASMAtomicIncU32(&pDevExt->cContextsDispIfResize);
6726 break;
6727 }
6728 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_SEAMLESS:
6729 {
6730 pContext->enmType = pInfo->enmType;
6731 Status = vboxVideoCmCtxAdd(&pDevice->pAdapter->SeamlessCtxMgr, &pContext->CmContext, (HANDLE)pInfo->hUmEvent, pInfo->u64UmInfo);
6732 if (!NT_SUCCESS(Status))
6733 {
6734 WARN(("vboxVideoCmCtxAdd failed, Status 0x%x", Status));
6735 }
6736 break;
6737 }
6738 default:
6739 {
6740 WARN(("unsupported context type %d", pInfo->enmType));
6741 Status = STATUS_INVALID_PARAMETER;
6742 break;
6743 }
6744 }
6745 }
6746 }
6747
6748 if (Status == STATUS_SUCCESS)
6749 {
6750 pCreateContext->hContext = pContext;
6751 pCreateContext->ContextInfo.DmaBufferSize = VBOXWDDM_C_DMA_BUFFER_SIZE;
6752 pCreateContext->ContextInfo.DmaBufferSegmentSet = 0;
6753 pCreateContext->ContextInfo.DmaBufferPrivateDataSize = VBOXWDDM_C_DMA_PRIVATEDATA_SIZE;
6754 pCreateContext->ContextInfo.AllocationListSize = VBOXWDDM_C_ALLOC_LIST_SIZE;
6755 pCreateContext->ContextInfo.PatchLocationListSize = VBOXWDDM_C_PATH_LOCATION_LIST_SIZE;
6756 //#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
6757 //# error port to Win7 DDI
6758 // //pCreateContext->ContextInfo.DmaBufferAllocationGroup = ???;
6759 //#endif // DXGKDDI_INTERFACE_VERSION
6760 }
6761 else
6762 vboxWddmMemFree(pContext);
6763 }
6764 else
6765 Status = STATUS_NO_MEMORY;
6766
6767 LOGF(("LEAVE, hDevice(0x%x)", hDevice));
6768
6769 return Status;
6770}
6771
6772NTSTATUS
6773APIENTRY
6774DxgkDdiDestroyContext(
6775 CONST HANDLE hContext)
6776{
6777 LOGF(("ENTER, hContext(0x%x)", hContext));
6778 vboxVDbgBreakFv();
6779 PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
6780 PVBOXMP_DEVEXT pDevExt = pContext->pDevice->pAdapter;
6781 NTSTATUS Status = STATUS_SUCCESS;
6782
6783 switch(pContext->enmType)
6784 {
6785 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_3D:
6786 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_3D:
6787 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_UHGSMI_GL:
6788 {
6789 uint32_t cContexts = ASMAtomicDecU32(&pDevExt->cContexts3D);
6790 Assert(cContexts < UINT32_MAX/2);
6791 break;
6792 }
6793 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_2D:
6794 {
6795 uint32_t cContexts = ASMAtomicDecU32(&pDevExt->cContexts2D);
6796 Assert(cContexts < UINT32_MAX/2);
6797 break;
6798 }
6799 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_RESIZE:
6800 {
6801 uint32_t cContexts = ASMAtomicDecU32(&pDevExt->cContextsDispIfResize);
6802 Assert(cContexts < UINT32_MAX/2);
6803 if (!cContexts)
6804 {
6805 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
6806 {
6807 vboxWddmGhDisplayCheckCompletePeningScreenInfo(pDevExt, i);
6808 }
6809 }
6810 break;
6811 }
6812 case VBOXWDDM_CONTEXT_TYPE_CUSTOM_DISPIF_SEAMLESS:
6813 {
6814 Status = vboxVideoCmCtxRemove(&pContext->pDevice->pAdapter->SeamlessCtxMgr, &pContext->CmContext);
6815 if (!NT_SUCCESS(Status))
6816 WARN(("vboxVideoCmCtxRemove failed, Status 0x%x", Status));
6817
6818 Assert(pContext->CmContext.pSession == NULL);
6819 break;
6820 }
6821 default:
6822 break;
6823 }
6824
6825 if (pContext->u32CrConClientID)
6826 {
6827 VBoxMpCrCtlConDisconnect(&pDevExt->CrCtlCon, pContext->u32CrConClientID);
6828 }
6829
6830 vboxWddmModeRenderFromShadowDisableUnregister(pDevExt, pContext);
6831
6832 /* first terminate the swapchain, this will also ensure
6833 * all currently pending driver->user Cm commands
6834 * (i.e. visible regions commands) are completed */
6835 vboxWddmSwapchainCtxTerm(pDevExt, pContext);
6836
6837 Status = vboxVideoAMgrCtxDestroy(&pContext->AllocContext);
6838 if (NT_SUCCESS(Status))
6839 {
6840 Status = vboxVideoCmCtxRemove(&pContext->pDevice->pAdapter->CmMgr, &pContext->CmContext);
6841 if (NT_SUCCESS(Status))
6842 vboxWddmMemFree(pContext);
6843 else
6844 WARN(("vboxVideoCmCtxRemove failed, Status 0x%x", Status));
6845 }
6846 else
6847 WARN(("vboxVideoAMgrCtxDestroy failed, Status 0x%x", Status));
6848
6849 LOGF(("LEAVE, hContext(0x%x)", hContext));
6850
6851 return Status;
6852}
6853
6854NTSTATUS
6855APIENTRY
6856DxgkDdiLinkDevice(
6857 __in CONST PDEVICE_OBJECT PhysicalDeviceObject,
6858 __in CONST PVOID MiniportDeviceContext,
6859 __inout PLINKED_DEVICE LinkedDevice
6860 )
6861{
6862 LOGF(("ENTER, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
6863 vboxVDbgBreakFv();
6864 AssertBreakpoint();
6865 LOGF(("LEAVE, MiniportDeviceContext(0x%x)", MiniportDeviceContext));
6866 return STATUS_NOT_IMPLEMENTED;
6867}
6868
6869NTSTATUS
6870APIENTRY
6871DxgkDdiSetDisplayPrivateDriverFormat(
6872 CONST HANDLE hAdapter,
6873 /*CONST*/ DXGKARG_SETDISPLAYPRIVATEDRIVERFORMAT* pSetDisplayPrivateDriverFormat
6874 )
6875{
6876 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
6877 vboxVDbgBreakFv();
6878 AssertBreakpoint();
6879 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
6880 return STATUS_SUCCESS;
6881}
6882
6883NTSTATUS APIENTRY CALLBACK DxgkDdiRestartFromTimeout(IN_CONST_HANDLE hAdapter)
6884{
6885 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
6886 vboxVDbgBreakFv();
6887 AssertBreakpoint();
6888 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
6889 return STATUS_SUCCESS;
6890}
6891
6892#ifdef VBOX_WDDM_WIN8
6893
6894static NTSTATUS APIENTRY DxgkDdiQueryVidPnHWCapability(
6895 __in const HANDLE hAdapter,
6896 __inout DXGKARG_QUERYVIDPNHWCAPABILITY *pVidPnHWCaps
6897 )
6898{
6899 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
6900 vboxVDbgBreakF();
6901 pVidPnHWCaps->VidPnHWCaps.DriverRotation = 0;
6902 pVidPnHWCaps->VidPnHWCaps.DriverScaling = 0;
6903 pVidPnHWCaps->VidPnHWCaps.DriverCloning = 0;
6904 pVidPnHWCaps->VidPnHWCaps.DriverColorConvert = 0;
6905 pVidPnHWCaps->VidPnHWCaps.DriverLinkedAdapaterOutput = 0;
6906 pVidPnHWCaps->VidPnHWCaps.DriverRemoteDisplay = 0;
6907 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
6908 return STATUS_SUCCESS;
6909}
6910
6911static NTSTATUS APIENTRY DxgkDdiPresentDisplayOnly(
6912 _In_ const HANDLE hAdapter,
6913 _In_ const DXGKARG_PRESENT_DISPLAYONLY *pPresentDisplayOnly
6914 )
6915{
6916 LOGF(("ENTER, hAdapter(0x%x)", hAdapter));
6917 vboxVDbgBreakF();
6918
6919 PVBOXMP_DEVEXT pDevExt = (PVBOXMP_DEVEXT)hAdapter;
6920 PVBOXWDDM_SOURCE pSource = &pDevExt->aSources[pPresentDisplayOnly->VidPnSourceId];
6921 Assert(pSource->AllocData.Addr.SegmentId);
6922 VBOXWDDM_ALLOC_DATA SrcAllocData;
6923 SrcAllocData.SurfDesc.width = pPresentDisplayOnly->Pitch * pPresentDisplayOnly->BytesPerPixel;
6924 SrcAllocData.SurfDesc.height = ~0UL;
6925 switch (pPresentDisplayOnly->BytesPerPixel)
6926 {
6927 case 4:
6928 SrcAllocData.SurfDesc.format = D3DDDIFMT_A8R8G8B8;
6929 break;
6930 case 3:
6931 SrcAllocData.SurfDesc.format = D3DDDIFMT_R8G8B8;
6932 break;
6933 case 2:
6934 SrcAllocData.SurfDesc.format = D3DDDIFMT_R5G6B5;
6935 break;
6936 case 1:
6937 SrcAllocData.SurfDesc.format = D3DDDIFMT_P8;
6938 break;
6939 default:
6940 WARN(("Unknown format"));
6941 SrcAllocData.SurfDesc.format = D3DDDIFMT_UNKNOWN;
6942 break;
6943 }
6944 SrcAllocData.SurfDesc.bpp = pPresentDisplayOnly->BytesPerPixel >> 3;
6945 SrcAllocData.SurfDesc.pitch = pPresentDisplayOnly->Pitch;
6946 SrcAllocData.SurfDesc.depth = 1;
6947 SrcAllocData.SurfDesc.slicePitch = pPresentDisplayOnly->Pitch;
6948 SrcAllocData.SurfDesc.cbSize = ~0UL;
6949 SrcAllocData.Addr.SegmentId = 0;
6950 SrcAllocData.Addr.pvMem = pPresentDisplayOnly->pSource;
6951 SrcAllocData.hostID = 0;
6952 SrcAllocData.pSwapchain = NULL;
6953
6954 RECT UpdateRect;
6955 BOOLEAN bUpdateRectInited = FALSE;
6956
6957 for (UINT i = 0; i < pPresentDisplayOnly->NumMoves; ++i)
6958 {
6959 if (!bUpdateRectInited)
6960 {
6961 UpdateRect = pPresentDisplayOnly->pMoves[i].DestRect;
6962 bUpdateRectInited = TRUE;
6963 }
6964 else
6965 vboxWddmRectUnite(&UpdateRect, &pPresentDisplayOnly->pMoves[i].DestRect);
6966 vboxVdmaGgDmaBltPerform(pDevExt, &SrcAllocData, &pPresentDisplayOnly->pMoves[i].DestRect, &pSource->AllocData, &pPresentDisplayOnly->pMoves[i].DestRect);
6967 }
6968
6969 for (UINT i = 0; i < pPresentDisplayOnly->NumDirtyRects; ++i)
6970 {
6971 vboxVdmaGgDmaBltPerform(pDevExt, &SrcAllocData, &pPresentDisplayOnly->pDirtyRect[i], &pSource->AllocData, &pPresentDisplayOnly->pDirtyRect[i]);
6972 if (!bUpdateRectInited)
6973 {
6974 UpdateRect = pPresentDisplayOnly->pDirtyRect[i];
6975 bUpdateRectInited = TRUE;
6976 }
6977 else
6978 vboxWddmRectUnite(&UpdateRect, &pPresentDisplayOnly->pDirtyRect[i]);
6979 }
6980
6981 if (bUpdateRectInited && pSource->bVisible)
6982 {
6983 VBOXVBVA_OP_WITHLOCK(ReportDirtyRect, pDevExt, pSource, &UpdateRect);
6984 }
6985
6986 LOGF(("LEAVE, hAdapter(0x%x)", hAdapter));
6987 return STATUS_SUCCESS;
6988}
6989
6990static NTSTATUS DxgkDdiStopDeviceAndReleasePostDisplayOwnership(
6991 _In_ PVOID MiniportDeviceContext,
6992 _In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
6993 _Out_ PDXGK_DISPLAY_INFORMATION DisplayInfo
6994)
6995{
6996 LOGF(("ENTER, hAdapter(0x%x)", MiniportDeviceContext));
6997 vboxVDbgBreakFv();
6998 AssertBreakpoint();
6999 LOGF(("LEAVE, hAdapter(0x%x)", MiniportDeviceContext));
7000 return STATUS_NOT_SUPPORTED;
7001}
7002
7003static NTSTATUS DxgkDdiSystemDisplayEnable(
7004 _In_ PVOID MiniportDeviceContext,
7005 _In_ D3DDDI_VIDEO_PRESENT_TARGET_ID TargetId,
7006 _In_ PDXGKARG_SYSTEM_DISPLAY_ENABLE_FLAGS Flags,
7007 _Out_ UINT *Width,
7008 _Out_ UINT *Height,
7009 _Out_ D3DDDIFORMAT *ColorFormat
7010 )
7011{
7012 LOGF(("ENTER, hAdapter(0x%x)", MiniportDeviceContext));
7013 vboxVDbgBreakFv();
7014 AssertBreakpoint();
7015 LOGF(("LEAVE, hAdapter(0x%x)", MiniportDeviceContext));
7016 return STATUS_NOT_SUPPORTED;
7017}
7018
7019static VOID DxgkDdiSystemDisplayWrite(
7020 _In_ PVOID MiniportDeviceContext,
7021 _In_ PVOID Source,
7022 _In_ UINT SourceWidth,
7023 _In_ UINT SourceHeight,
7024 _In_ UINT SourceStride,
7025 _In_ UINT PositionX,
7026 _In_ UINT PositionY
7027)
7028{
7029 LOGF(("ENTER, hAdapter(0x%x)", MiniportDeviceContext));
7030 vboxVDbgBreakFv();
7031 AssertBreakpoint();
7032 LOGF(("LEAVE, hAdapter(0x%x)", MiniportDeviceContext));
7033}
7034
7035static NTSTATUS DxgkDdiGetChildContainerId(
7036 _In_ PVOID MiniportDeviceContext,
7037 _In_ ULONG ChildUid,
7038 _Inout_ PDXGK_CHILD_CONTAINER_ID ContainerId
7039)
7040{
7041 LOGF(("ENTER, hAdapter(0x%x)", MiniportDeviceContext));
7042 vboxVDbgBreakFv();
7043 AssertBreakpoint();
7044 LOGF(("LEAVE, hAdapter(0x%x)", MiniportDeviceContext));
7045 return STATUS_SUCCESS;
7046}
7047
7048static NTSTATUS APIENTRY DxgkDdiSetPowerComponentFState(
7049 _In_ const HANDLE DriverContext,
7050 UINT ComponentIndex,
7051 UINT FState
7052)
7053{
7054 LOGF(("ENTER, DriverContext(0x%x)", DriverContext));
7055 vboxVDbgBreakFv();
7056 AssertBreakpoint();
7057 LOGF(("LEAVE, DriverContext(0x%x)", DriverContext));
7058 return STATUS_SUCCESS;
7059}
7060
7061static NTSTATUS APIENTRY DxgkDdiPowerRuntimeControlRequest(
7062 _In_ const HANDLE DriverContext,
7063 _In_ LPCGUID PowerControlCode,
7064 _In_opt_ PVOID InBuffer,
7065 _In_ SIZE_T InBufferSize,
7066 _Out_opt_ PVOID OutBuffer,
7067 _In_ SIZE_T OutBufferSize,
7068 _Out_opt_ PSIZE_T BytesReturned
7069)
7070{
7071 LOGF(("ENTER, DriverContext(0x%x)", DriverContext));
7072 vboxVDbgBreakFv();
7073 AssertBreakpoint();
7074 LOGF(("LEAVE, DriverContext(0x%x)", DriverContext));
7075 return STATUS_SUCCESS;
7076}
7077
7078static NTSTATUS DxgkDdiNotifySurpriseRemoval(
7079 _In_ PVOID MiniportDeviceContext,
7080 _In_ DXGK_SURPRISE_REMOVAL_TYPE RemovalType
7081 )
7082{
7083 LOGF(("ENTER, hAdapter(0x%x)", MiniportDeviceContext));
7084 vboxVDbgBreakFv();
7085 AssertBreakpoint();
7086 LOGF(("LEAVE, hAdapter(0x%x)", MiniportDeviceContext));
7087 return STATUS_SUCCESS;
7088}
7089
7090static NTSTATUS vboxWddmInitDisplayOnlyDriver(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath)
7091{
7092 KMDDOD_INITIALIZATION_DATA DriverInitializationData = {'\0'};
7093
7094 DriverInitializationData.Version = DXGKDDI_INTERFACE_VERSION_WIN8;
7095
7096 DriverInitializationData.DxgkDdiAddDevice = DxgkDdiAddDevice;
7097 DriverInitializationData.DxgkDdiStartDevice = DxgkDdiStartDevice;
7098 DriverInitializationData.DxgkDdiStopDevice = DxgkDdiStopDevice;
7099 DriverInitializationData.DxgkDdiRemoveDevice = DxgkDdiRemoveDevice;
7100 DriverInitializationData.DxgkDdiDispatchIoRequest = DxgkDdiDispatchIoRequest;
7101 DriverInitializationData.DxgkDdiInterruptRoutine = DxgkDdiInterruptRoutineNew;
7102 DriverInitializationData.DxgkDdiDpcRoutine = DxgkDdiDpcRoutineNew;
7103 DriverInitializationData.DxgkDdiQueryChildRelations = DxgkDdiQueryChildRelations;
7104 DriverInitializationData.DxgkDdiQueryChildStatus = DxgkDdiQueryChildStatus;
7105 DriverInitializationData.DxgkDdiQueryDeviceDescriptor = DxgkDdiQueryDeviceDescriptor;
7106 DriverInitializationData.DxgkDdiSetPowerState = DxgkDdiSetPowerState;
7107 DriverInitializationData.DxgkDdiNotifyAcpiEvent = DxgkDdiNotifyAcpiEvent;
7108 DriverInitializationData.DxgkDdiResetDevice = DxgkDdiResetDevice;
7109 DriverInitializationData.DxgkDdiUnload = DxgkDdiUnload;
7110 DriverInitializationData.DxgkDdiQueryInterface = DxgkDdiQueryInterface;
7111 DriverInitializationData.DxgkDdiControlEtwLogging = DxgkDdiControlEtwLogging;
7112 DriverInitializationData.DxgkDdiQueryAdapterInfo = DxgkDdiQueryAdapterInfo;
7113 DriverInitializationData.DxgkDdiSetPalette = DxgkDdiSetPalette;
7114 DriverInitializationData.DxgkDdiSetPointerPosition = DxgkDdiSetPointerPosition;
7115 DriverInitializationData.DxgkDdiSetPointerShape = DxgkDdiSetPointerShape;
7116 DriverInitializationData.DxgkDdiEscape = DxgkDdiEscape;
7117 DriverInitializationData.DxgkDdiCollectDbgInfo = DxgkDdiCollectDbgInfo;
7118 DriverInitializationData.DxgkDdiIsSupportedVidPn = DxgkDdiIsSupportedVidPn;
7119 DriverInitializationData.DxgkDdiRecommendFunctionalVidPn = DxgkDdiRecommendFunctionalVidPn;
7120 DriverInitializationData.DxgkDdiEnumVidPnCofuncModality = DxgkDdiEnumVidPnCofuncModality;
7121 DriverInitializationData.DxgkDdiSetVidPnSourceVisibility = DxgkDdiSetVidPnSourceVisibility;
7122 DriverInitializationData.DxgkDdiCommitVidPn = DxgkDdiCommitVidPn;
7123 DriverInitializationData.DxgkDdiUpdateActiveVidPnPresentPath = DxgkDdiUpdateActiveVidPnPresentPath;
7124 DriverInitializationData.DxgkDdiRecommendMonitorModes = DxgkDdiRecommendMonitorModes;
7125 DriverInitializationData.DxgkDdiGetScanLine = DxgkDdiGetScanLine;
7126 DriverInitializationData.DxgkDdiQueryVidPnHWCapability = DxgkDdiQueryVidPnHWCapability;
7127 DriverInitializationData.DxgkDdiPresentDisplayOnly = DxgkDdiPresentDisplayOnly;
7128 DriverInitializationData.DxgkDdiStopDeviceAndReleasePostDisplayOwnership = DxgkDdiStopDeviceAndReleasePostDisplayOwnership;
7129 DriverInitializationData.DxgkDdiSystemDisplayEnable = DxgkDdiSystemDisplayEnable;
7130 DriverInitializationData.DxgkDdiSystemDisplayWrite = DxgkDdiSystemDisplayWrite;
7131// DriverInitializationData.DxgkDdiGetChildContainerId = DxgkDdiGetChildContainerId;
7132 DriverInitializationData.DxgkDdiControlInterrupt = DxgkDdiControlInterrupt;
7133// DriverInitializationData.DxgkDdiSetPowerComponentFState = DxgkDdiSetPowerComponentFState;
7134// DriverInitializationData.DxgkDdiPowerRuntimeControlRequest = DxgkDdiPowerRuntimeControlRequest;
7135// DriverInitializationData.DxgkDdiNotifySurpriseRemoval = DxgkDdiNotifySurpriseRemoval;
7136
7137 NTSTATUS Status = DxgkInitializeDisplayOnlyDriver(pDriverObject,
7138 pRegistryPath,
7139 &DriverInitializationData);
7140 if (!NT_SUCCESS(Status))
7141 {
7142 WARN(("DxgkInitializeDisplayOnlyDriver failed! Status 0x%x", Status));
7143 }
7144 return Status;
7145}
7146#endif
7147
7148static NTSTATUS vboxWddmInitFullGraphicsDriver(IN PDRIVER_OBJECT pDriverObject, IN PUNICODE_STRING pRegistryPath, BOOLEAN fCmdVbva)
7149{
7150#define VBOXWDDM_CALLBACK_NAME(_base, _fCmdVbva) ((_fCmdVbva) ? _base##New : _base##Legacy)
7151
7152 DRIVER_INITIALIZATION_DATA DriverInitializationData = {'\0'};
7153
7154 // Fill in the DriverInitializationData structure and call DxgkInitialize()
7155 DriverInitializationData.Version = DXGKDDI_INTERFACE_VERSION;
7156
7157 DriverInitializationData.DxgkDdiAddDevice = DxgkDdiAddDevice;
7158 DriverInitializationData.DxgkDdiStartDevice = DxgkDdiStartDevice;
7159 DriverInitializationData.DxgkDdiStopDevice = DxgkDdiStopDevice;
7160 DriverInitializationData.DxgkDdiRemoveDevice = DxgkDdiRemoveDevice;
7161 DriverInitializationData.DxgkDdiDispatchIoRequest = DxgkDdiDispatchIoRequest;
7162 DriverInitializationData.DxgkDdiInterruptRoutine = VBOXWDDM_CALLBACK_NAME(DxgkDdiInterruptRoutine, fCmdVbva);
7163 DriverInitializationData.DxgkDdiDpcRoutine = VBOXWDDM_CALLBACK_NAME(DxgkDdiDpcRoutine, fCmdVbva);
7164 DriverInitializationData.DxgkDdiQueryChildRelations = DxgkDdiQueryChildRelations;
7165 DriverInitializationData.DxgkDdiQueryChildStatus = DxgkDdiQueryChildStatus;
7166 DriverInitializationData.DxgkDdiQueryDeviceDescriptor = DxgkDdiQueryDeviceDescriptor;
7167 DriverInitializationData.DxgkDdiSetPowerState = DxgkDdiSetPowerState;
7168 DriverInitializationData.DxgkDdiNotifyAcpiEvent = DxgkDdiNotifyAcpiEvent;
7169 DriverInitializationData.DxgkDdiResetDevice = DxgkDdiResetDevice;
7170 DriverInitializationData.DxgkDdiUnload = DxgkDdiUnload;
7171 DriverInitializationData.DxgkDdiQueryInterface = DxgkDdiQueryInterface;
7172 DriverInitializationData.DxgkDdiControlEtwLogging = DxgkDdiControlEtwLogging;
7173
7174 DriverInitializationData.DxgkDdiQueryAdapterInfo = DxgkDdiQueryAdapterInfo;
7175 DriverInitializationData.DxgkDdiCreateDevice = DxgkDdiCreateDevice;
7176 DriverInitializationData.DxgkDdiCreateAllocation = DxgkDdiCreateAllocation;
7177 DriverInitializationData.DxgkDdiDestroyAllocation = DxgkDdiDestroyAllocation;
7178 DriverInitializationData.DxgkDdiDescribeAllocation = DxgkDdiDescribeAllocation;
7179 DriverInitializationData.DxgkDdiGetStandardAllocationDriverData = DxgkDdiGetStandardAllocationDriverData;
7180 DriverInitializationData.DxgkDdiAcquireSwizzlingRange = DxgkDdiAcquireSwizzlingRange;
7181 DriverInitializationData.DxgkDdiReleaseSwizzlingRange = DxgkDdiReleaseSwizzlingRange;
7182 DriverInitializationData.DxgkDdiPatch = VBOXWDDM_CALLBACK_NAME(DxgkDdiPatch, fCmdVbva);
7183 DriverInitializationData.DxgkDdiSubmitCommand = VBOXWDDM_CALLBACK_NAME(DxgkDdiSubmitCommand, fCmdVbva);
7184 DriverInitializationData.DxgkDdiPreemptCommand = VBOXWDDM_CALLBACK_NAME(DxgkDdiPreemptCommand, fCmdVbva);
7185 DriverInitializationData.DxgkDdiBuildPagingBuffer = VBOXWDDM_CALLBACK_NAME(DxgkDdiBuildPagingBuffer, fCmdVbva);
7186 DriverInitializationData.DxgkDdiSetPalette = DxgkDdiSetPalette;
7187 DriverInitializationData.DxgkDdiSetPointerPosition = DxgkDdiSetPointerPosition;
7188 DriverInitializationData.DxgkDdiSetPointerShape = DxgkDdiSetPointerShape;
7189 DriverInitializationData.DxgkDdiResetFromTimeout = DxgkDdiResetFromTimeout;
7190 DriverInitializationData.DxgkDdiRestartFromTimeout = DxgkDdiRestartFromTimeout;
7191 DriverInitializationData.DxgkDdiEscape = DxgkDdiEscape;
7192 DriverInitializationData.DxgkDdiCollectDbgInfo = DxgkDdiCollectDbgInfo;
7193 DriverInitializationData.DxgkDdiQueryCurrentFence = VBOXWDDM_CALLBACK_NAME(DxgkDdiQueryCurrentFence, fCmdVbva);
7194 DriverInitializationData.DxgkDdiIsSupportedVidPn = DxgkDdiIsSupportedVidPn;
7195 DriverInitializationData.DxgkDdiRecommendFunctionalVidPn = DxgkDdiRecommendFunctionalVidPn;
7196 DriverInitializationData.DxgkDdiEnumVidPnCofuncModality = DxgkDdiEnumVidPnCofuncModality;
7197 DriverInitializationData.DxgkDdiSetVidPnSourceAddress = DxgkDdiSetVidPnSourceAddress;
7198 DriverInitializationData.DxgkDdiSetVidPnSourceVisibility = DxgkDdiSetVidPnSourceVisibility;
7199 DriverInitializationData.DxgkDdiCommitVidPn = DxgkDdiCommitVidPn;
7200 DriverInitializationData.DxgkDdiUpdateActiveVidPnPresentPath = DxgkDdiUpdateActiveVidPnPresentPath;
7201 DriverInitializationData.DxgkDdiRecommendMonitorModes = DxgkDdiRecommendMonitorModes;
7202 DriverInitializationData.DxgkDdiRecommendVidPnTopology = DxgkDdiRecommendVidPnTopology;
7203 DriverInitializationData.DxgkDdiGetScanLine = DxgkDdiGetScanLine;
7204 DriverInitializationData.DxgkDdiStopCapture = DxgkDdiStopCapture;
7205 DriverInitializationData.DxgkDdiControlInterrupt = DxgkDdiControlInterrupt;
7206 DriverInitializationData.DxgkDdiCreateOverlay = DxgkDdiCreateOverlay;
7207
7208 DriverInitializationData.DxgkDdiDestroyDevice = DxgkDdiDestroyDevice;
7209 DriverInitializationData.DxgkDdiOpenAllocation = DxgkDdiOpenAllocation;
7210 DriverInitializationData.DxgkDdiCloseAllocation = DxgkDdiCloseAllocation;
7211 DriverInitializationData.DxgkDdiRender = VBOXWDDM_CALLBACK_NAME(DxgkDdiRender, fCmdVbva);
7212 DriverInitializationData.DxgkDdiPresent = VBOXWDDM_CALLBACK_NAME(DxgkDdiPresent, fCmdVbva);
7213
7214 DriverInitializationData.DxgkDdiUpdateOverlay = DxgkDdiUpdateOverlay;
7215 DriverInitializationData.DxgkDdiFlipOverlay = DxgkDdiFlipOverlay;
7216 DriverInitializationData.DxgkDdiDestroyOverlay = DxgkDdiDestroyOverlay;
7217
7218 DriverInitializationData.DxgkDdiCreateContext = DxgkDdiCreateContext;
7219 DriverInitializationData.DxgkDdiDestroyContext = DxgkDdiDestroyContext;
7220
7221 DriverInitializationData.DxgkDdiLinkDevice = NULL; //DxgkDdiLinkDevice;
7222 DriverInitializationData.DxgkDdiSetDisplayPrivateDriverFormat = DxgkDdiSetDisplayPrivateDriverFormat;
7223//#if (DXGKDDI_INTERFACE_VERSION >= DXGKDDI_INTERFACE_VERSION_WIN7)
7224//# error port to Win7 DDI
7225// DriverInitializationData.DxgkDdiRenderKm = DxgkDdiRenderKm;
7226// DriverInitializationData.DxgkDdiRestartFromTimeout = DxgkDdiRestartFromTimeout;
7227// DriverInitializationData.DxgkDdiSetVidPnSourceVisibility = DxgkDdiSetVidPnSourceVisibility;
7228// DriverInitializationData.DxgkDdiUpdateActiveVidPnPresentPath = DxgkDdiUpdateActiveVidPnPresentPath;
7229// DriverInitializationData.DxgkDdiQueryVidPnHWCapability = DxgkDdiQueryVidPnHWCapability;
7230//#endif
7231
7232 NTSTATUS Status = DxgkInitialize(pDriverObject,
7233 pRegistryPath,
7234 &DriverInitializationData);
7235 if (!NT_SUCCESS(Status))
7236 {
7237 WARN(("DxgkInitialize failed! Status 0x%x", Status));
7238 }
7239 return Status;
7240}
7241
7242NTSTATUS
7243DriverEntry(
7244 IN PDRIVER_OBJECT DriverObject,
7245 IN PUNICODE_STRING RegistryPath
7246 )
7247{
7248 PAGED_CODE();
7249
7250 vboxVDbgBreakFv();
7251
7252#if 0//def DEBUG_misha
7253 RTLogGroupSettings(0, "+default.e.l.f.l2.l3");
7254#endif
7255
7256#ifdef VBOX_WDDM_WIN8
7257 LOGREL(("VBox WDDM Driver for Windows 8, %d bit; Built %s %s", (sizeof (void*) << 3), __DATE__, __TIME__));
7258#else
7259 LOGREL(("VBox WDDM Driver for Windows Vista and 7, %d bit; Built %s %s", (sizeof (void*) << 3), __DATE__, __TIME__));
7260#endif
7261
7262 if (! ARGUMENT_PRESENT(DriverObject) ||
7263 ! ARGUMENT_PRESENT(RegistryPath))
7264 {
7265 return STATUS_INVALID_PARAMETER;
7266 }
7267
7268 vboxWddmDrvCfgInit(RegistryPath);
7269
7270 ULONG major, minor, build;
7271 BOOLEAN checkedBuild = PsGetVersion(&major, &minor, &build, NULL);
7272 BOOLEAN f3DRequired = FALSE;
7273
7274 LOGREL(("OsVersion( %d, %d, %d )", major, minor, build));
7275
7276 NTSTATUS Status = STATUS_SUCCESS;
7277 /* Initialize VBoxGuest library, which is used for requests which go through VMMDev. */
7278 int rc = VbglInit();
7279 if (RT_SUCCESS(rc))
7280 {
7281 if (major > 6)
7282 {
7283 WARN(("Unknow win version, newer major release, assuming 3D check is required"));
7284 f3DRequired = TRUE;
7285 }
7286 else if (major == 6)
7287 {
7288 if (minor > 3)
7289 {
7290 WARN(("Unknow win version, newer minor release, assuming 3D check is required"));
7291 f3DRequired = TRUE;
7292 }
7293 else if (minor >= 2)
7294 {
7295 LOG(("3D check is required!"));
7296 f3DRequired = TRUE;
7297 }
7298 else
7299 {
7300 LOG(("3D is NOT required!"));
7301 f3DRequired = FALSE;
7302 }
7303 }
7304 else
7305 {
7306 WARN(("Unsupported OLDER win version, ignore and assume 3D is NOT required"));
7307 f3DRequired = FALSE;
7308 }
7309
7310 Status = STATUS_SUCCESS;
7311
7312 VBoxMpCrCtlConInit();
7313
7314 /* always need to do the check to request host caps */
7315 LOG(("Doing the 3D check.."));
7316 if (!VBoxMpCrCtlConIs3DSupported())
7317 {
7318#ifdef VBOX_WDDM_WIN8
7319 Assert(f3DRequired);
7320 LOGREL(("3D is NOT supported by the host, falling back to display-only mode.."));
7321 g_VBoxDisplayOnly = 1;
7322#else
7323 if (f3DRequired)
7324 {
7325 LOGREL(("3D is NOT supported by the host, but is required for the current guest version using this driver.."));
7326 Status = STATUS_UNSUCCESSFUL;
7327 }
7328 else
7329 LOGREL(("3D is NOT supported by the host, but is NOT required for the current guest version using this driver, continuing with Disabled 3D.."));
7330#endif
7331 }
7332
7333#if 0 //defined(DEBUG_misha) && defined(VBOX_WDDM_WIN8)
7334 /* force g_VBoxDisplayOnly for debugging purposes */
7335 LOGREL(("Current win8 video driver only supports display-only mode no matter whether or not host 3D is enabled!"));
7336 g_VBoxDisplayOnly = 1;
7337#endif
7338
7339 if (NT_SUCCESS(Status))
7340 {
7341 rc = VBoxVrInit();
7342 if (RT_SUCCESS(rc))
7343 {
7344#ifdef VBOX_WDDM_WIN8
7345 if (g_VBoxDisplayOnly)
7346 {
7347 Status = vboxWddmInitDisplayOnlyDriver(DriverObject, RegistryPath);
7348 }
7349 else
7350#endif
7351 {
7352 Status = vboxWddmInitFullGraphicsDriver(DriverObject, RegistryPath, !!(VBoxMpCrGetHostCaps() & CR_VBOX_CAP_CMDVBVA));
7353 }
7354
7355 if (NT_SUCCESS(Status))
7356 return Status;
7357
7358 VBoxVrTerm();
7359 }
7360 else
7361 {
7362 WARN(("VBoxVrInit failed, rc(%d)", rc));
7363 Status = STATUS_UNSUCCESSFUL;
7364 }
7365 }
7366 else
7367 LOGREL(("Aborting the video driver load due to 3D support missing"));
7368
7369 VbglTerminate();
7370 }
7371 else
7372 {
7373 WARN(("VbglInit failed, rc(%d)", rc));
7374 Status = STATUS_UNSUCCESSFUL;
7375 }
7376
7377 AssertRelease(!NT_SUCCESS(Status));
7378
7379 PRTLOGGER pLogger = RTLogRelSetDefaultInstance(NULL);
7380 if (pLogger)
7381 {
7382 RTLogDestroy(pLogger);
7383 }
7384 pLogger = RTLogSetDefaultInstance(NULL);
7385 if (pLogger)
7386 {
7387 RTLogDestroy(pLogger);
7388 }
7389
7390 return Status;
7391}
7392
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