VirtualBox

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

Last change on this file since 85817 was 85058, checked in by vboxsync, 5 years ago

WDDM: fixed HSyncFreq calculation

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 125.8 KB
Line 
1/* $Id: VBoxMPVidPn.cpp 85058 2020-07-03 19:36:39Z vboxsync $ */
2/** @file
3 * VBox WDDM Miniport driver
4 */
5
6/*
7 * Copyright (C) 2011-2020 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 "VBoxMPVidPn.h"
20#include "common/VBoxMPCommon.h"
21
22
23static NTSTATUS vboxVidPnCheckMonitorModes(PVBOXMP_DEVEXT pDevExt, uint32_t u32Target, const CR_SORTARRAY *pSupportedTargetModes = NULL);
24
25static D3DDDIFORMAT vboxWddmCalcPixelFormat(const VIDEO_MODE_INFORMATION *pInfo)
26{
27 switch (pInfo->BitsPerPlane)
28 {
29 case 32:
30 if(!(pInfo->AttributeFlags & VIDEO_MODE_PALETTE_DRIVEN) && !(pInfo->AttributeFlags & VIDEO_MODE_MANAGED_PALETTE))
31 {
32 if (pInfo->RedMask == 0xFF0000 && pInfo->GreenMask == 0xFF00 && pInfo->BlueMask == 0xFF)
33 return D3DDDIFMT_A8R8G8B8;
34 WARN(("unsupported format: bpp(%d), rmask(%d), gmask(%d), bmask(%d)",
35 pInfo->BitsPerPlane, pInfo->RedMask, pInfo->GreenMask, pInfo->BlueMask));
36 AssertBreakpoint();
37 }
38 else
39 {
40 WARN(("unsupported AttributeFlags(0x%x)", pInfo->AttributeFlags));
41 AssertBreakpoint();
42 }
43 break;
44 case 24:
45 if(!(pInfo->AttributeFlags & VIDEO_MODE_PALETTE_DRIVEN) && !(pInfo->AttributeFlags & VIDEO_MODE_MANAGED_PALETTE))
46 {
47 if (pInfo->RedMask == 0xFF0000 && pInfo->GreenMask == 0xFF00 && pInfo->BlueMask == 0xFF)
48 return D3DDDIFMT_R8G8B8;
49 WARN(("unsupported format: bpp(%d), rmask(%d), gmask(%d), bmask(%d)",
50 pInfo->BitsPerPlane, pInfo->RedMask, pInfo->GreenMask, pInfo->BlueMask));
51 AssertBreakpoint();
52 }
53 else
54 {
55 WARN(("unsupported AttributeFlags(0x%x)", pInfo->AttributeFlags));
56 AssertBreakpoint();
57 }
58 break;
59 case 16:
60 if(!(pInfo->AttributeFlags & VIDEO_MODE_PALETTE_DRIVEN) && !(pInfo->AttributeFlags & VIDEO_MODE_MANAGED_PALETTE))
61 {
62 if (pInfo->RedMask == 0xF800 && pInfo->GreenMask == 0x7E0 && pInfo->BlueMask == 0x1F)
63 return D3DDDIFMT_R5G6B5;
64 WARN(("unsupported format: bpp(%d), rmask(%d), gmask(%d), bmask(%d)",
65 pInfo->BitsPerPlane, pInfo->RedMask, pInfo->GreenMask, pInfo->BlueMask));
66 AssertBreakpoint();
67 }
68 else
69 {
70 WARN(("unsupported AttributeFlags(0x%x)", pInfo->AttributeFlags));
71 AssertBreakpoint();
72 }
73 break;
74 case 8:
75 if((pInfo->AttributeFlags & VIDEO_MODE_PALETTE_DRIVEN) && (pInfo->AttributeFlags & VIDEO_MODE_MANAGED_PALETTE))
76 {
77 return D3DDDIFMT_P8;
78 }
79 else
80 {
81 WARN(("unsupported AttributeFlags(0x%x)", pInfo->AttributeFlags));
82 AssertBreakpoint();
83 }
84 break;
85 default:
86 WARN(("unsupported bpp(%d)", pInfo->BitsPerPlane));
87 AssertBreakpoint();
88 break;
89 }
90
91 return D3DDDIFMT_UNKNOWN;
92}
93
94static int vboxWddmResolutionFind(const D3DKMDT_2DREGION *pResolutions, int cResolutions, const D3DKMDT_2DREGION *pRes)
95{
96 for (int i = 0; i < cResolutions; ++i)
97 {
98 const D3DKMDT_2DREGION *pResolution = &pResolutions[i];
99 if (pResolution->cx == pRes->cx && pResolution->cy == pRes->cy)
100 return i;
101 }
102 return -1;
103}
104
105static bool vboxWddmVideoModesMatch(const VIDEO_MODE_INFORMATION *pMode1, const VIDEO_MODE_INFORMATION *pMode2)
106{
107 return pMode1->VisScreenHeight == pMode2->VisScreenHeight
108 && pMode1->VisScreenWidth == pMode2->VisScreenWidth
109 && pMode1->BitsPerPlane == pMode2->BitsPerPlane;
110}
111
112static int vboxWddmVideoModeFind(const VIDEO_MODE_INFORMATION *pModes, int cModes, const VIDEO_MODE_INFORMATION *pM)
113{
114 for (int i = 0; i < cModes; ++i)
115 {
116 const VIDEO_MODE_INFORMATION *pMode = &pModes[i];
117 if (vboxWddmVideoModesMatch(pMode, pM))
118 return i;
119 }
120 return -1;
121}
122
123static NTSTATUS vboxVidPnPopulateVideoSignalInfo(D3DKMDT_VIDEO_SIGNAL_INFO *pVsi,
124 const RTRECTSIZE *pResolution,
125 ULONG VSync)
126{
127 NTSTATUS Status = STATUS_SUCCESS;
128
129 pVsi->VideoStandard = D3DKMDT_VSS_OTHER;
130 pVsi->ActiveSize.cx = pResolution->cx;
131 pVsi->ActiveSize.cy = pResolution->cy;
132 pVsi->TotalSize = pVsi->ActiveSize;
133 if (VBOXWDDM_IS_DISPLAYONLY())
134 {
135 /* VSYNC is not implemented in display-only mode (#8228).
136 * In this case Windows checks that frequencies are not specified.
137 */
138 pVsi->VSyncFreq.Numerator = D3DKMDT_FREQUENCY_NOTSPECIFIED;
139 pVsi->VSyncFreq.Denominator = D3DKMDT_FREQUENCY_NOTSPECIFIED;
140 pVsi->PixelRate = D3DKMDT_FREQUENCY_NOTSPECIFIED;
141 pVsi->HSyncFreq.Numerator = D3DKMDT_FREQUENCY_NOTSPECIFIED;
142 pVsi->HSyncFreq.Denominator = D3DKMDT_FREQUENCY_NOTSPECIFIED;
143 }
144 else
145 {
146 pVsi->VSyncFreq.Numerator = VSync * 1000;
147 pVsi->VSyncFreq.Denominator = 1000;
148 pVsi->PixelRate = pVsi->TotalSize.cx * pVsi->TotalSize.cy * VSync;
149 pVsi->HSyncFreq.Numerator = (UINT)((VSync * pVsi->TotalSize.cy) * 1000);
150 pVsi->HSyncFreq.Denominator = 1000;
151 }
152 pVsi->ScanLineOrdering = D3DDDI_VSSLO_PROGRESSIVE;
153
154 return Status;
155}
156
157BOOLEAN vboxVidPnMatchVideoSignal(const D3DKMDT_VIDEO_SIGNAL_INFO *pVsi1, const D3DKMDT_VIDEO_SIGNAL_INFO *pVsi2)
158{
159 if (pVsi1->VideoStandard != pVsi2->VideoStandard)
160 return FALSE;
161 if (pVsi1->TotalSize.cx != pVsi2->TotalSize.cx)
162 return FALSE;
163 if (pVsi1->TotalSize.cy != pVsi2->TotalSize.cy)
164 return FALSE;
165 if (pVsi1->ActiveSize.cx != pVsi2->ActiveSize.cx)
166 return FALSE;
167 if (pVsi1->ActiveSize.cy != pVsi2->ActiveSize.cy)
168 return FALSE;
169 if (pVsi1->VSyncFreq.Numerator != pVsi2->VSyncFreq.Numerator)
170 return FALSE;
171 if (pVsi1->VSyncFreq.Denominator != pVsi2->VSyncFreq.Denominator)
172 return FALSE;
173 if (pVsi1->HSyncFreq.Numerator != pVsi2->HSyncFreq.Numerator)
174 return FALSE;
175 if (pVsi1->HSyncFreq.Denominator != pVsi2->HSyncFreq.Denominator)
176 return FALSE;
177 if (pVsi1->PixelRate != pVsi2->PixelRate)
178 return FALSE;
179 if (pVsi1->ScanLineOrdering != pVsi2->ScanLineOrdering)
180 return FALSE;
181
182 return TRUE;
183}
184
185static void vboxVidPnPopulateSourceModeInfo(D3DKMDT_VIDPN_SOURCE_MODE *pNewVidPnSourceModeInfo, const RTRECTSIZE *pSize)
186{
187 /* this is a graphics mode */
188 pNewVidPnSourceModeInfo->Type = D3DKMDT_RMT_GRAPHICS;
189 pNewVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cx = pSize->cx;
190 pNewVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy = pSize->cy;
191 pNewVidPnSourceModeInfo->Format.Graphics.VisibleRegionSize = pNewVidPnSourceModeInfo->Format.Graphics.PrimSurfSize;
192 pNewVidPnSourceModeInfo->Format.Graphics.Stride = pSize->cx * 4;
193 pNewVidPnSourceModeInfo->Format.Graphics.PixelFormat = D3DDDIFMT_A8R8G8B8;
194 Assert(pNewVidPnSourceModeInfo->Format.Graphics.PixelFormat != D3DDDIFMT_UNKNOWN);
195 pNewVidPnSourceModeInfo->Format.Graphics.ColorBasis = D3DKMDT_CB_SRGB;
196 if (pNewVidPnSourceModeInfo->Format.Graphics.PixelFormat == D3DDDIFMT_P8)
197 pNewVidPnSourceModeInfo->Format.Graphics.PixelValueAccessMode = D3DKMDT_PVAM_SETTABLEPALETTE;
198 else
199 pNewVidPnSourceModeInfo->Format.Graphics.PixelValueAccessMode = D3DKMDT_PVAM_DIRECT;
200}
201
202static void vboxVidPnPopulateMonitorModeInfo(D3DKMDT_MONITOR_SOURCE_MODE *pMonitorSourceMode, const RTRECTSIZE *pResolution)
203{
204 vboxVidPnPopulateVideoSignalInfo(&pMonitorSourceMode->VideoSignalInfo, pResolution, g_RefreshRate);
205 pMonitorSourceMode->ColorBasis = D3DKMDT_CB_SRGB;
206 pMonitorSourceMode->ColorCoeffDynamicRanges.FirstChannel = 8;
207 pMonitorSourceMode->ColorCoeffDynamicRanges.SecondChannel = 8;
208 pMonitorSourceMode->ColorCoeffDynamicRanges.ThirdChannel = 8;
209 pMonitorSourceMode->ColorCoeffDynamicRanges.FourthChannel = 0;
210 pMonitorSourceMode->Origin = D3DKMDT_MCO_DRIVER;
211 pMonitorSourceMode->Preference = D3DKMDT_MP_NOTPREFERRED;
212}
213
214static NTSTATUS vboxVidPnPopulateTargetModeInfo(D3DKMDT_VIDPN_TARGET_MODE *pNewVidPnTargetModeInfo, const RTRECTSIZE *pResolution)
215{
216 pNewVidPnTargetModeInfo->Preference = D3DKMDT_MP_NOTPREFERRED;
217 return vboxVidPnPopulateVideoSignalInfo(&pNewVidPnTargetModeInfo->VideoSignalInfo, pResolution, g_RefreshRate);
218}
219
220void VBoxVidPnStTargetCleanup(PVBOXWDDM_SOURCE paSources, uint32_t cScreens, PVBOXWDDM_TARGET pTarget)
221{
222 RT_NOREF(cScreens);
223 if (pTarget->VidPnSourceId == D3DDDI_ID_UNINITIALIZED)
224 return;
225
226 Assert(pTarget->VidPnSourceId < cScreens);
227
228 PVBOXWDDM_SOURCE pSource = &paSources[pTarget->VidPnSourceId];
229 if (!pSource)
230 return;
231 Assert(pSource->cTargets);
232 Assert(ASMBitTest(pSource->aTargetMap, pTarget->u32Id));
233 ASMBitClear(pSource->aTargetMap, pTarget->u32Id);
234 pSource->cTargets--;
235 pTarget->VidPnSourceId = D3DDDI_ID_UNINITIALIZED;
236
237 pTarget->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_TOPOLOGY;
238 pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_TOPOLOGY;
239}
240
241void VBoxVidPnStSourceTargetAdd(PVBOXWDDM_SOURCE paSources, uint32_t cScreens, PVBOXWDDM_SOURCE pSource, PVBOXWDDM_TARGET pTarget)
242{
243 if (pTarget->VidPnSourceId == pSource->AllocData.SurfDesc.VidPnSourceId)
244 return;
245
246 VBoxVidPnStTargetCleanup(paSources, cScreens, pTarget);
247
248 ASMBitSet(pSource->aTargetMap, pTarget->u32Id);
249 pSource->cTargets++;
250 pTarget->VidPnSourceId = pSource->AllocData.SurfDesc.VidPnSourceId;
251
252 pTarget->fBlankedByPowerOff = RT_BOOL(pSource->bBlankedByPowerOff);
253 LOG(("src %d and tgt %d are now blank %d",
254 pSource->AllocData.SurfDesc.VidPnSourceId, pTarget->u32Id, pTarget->fBlankedByPowerOff));
255
256 pTarget->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_TOPOLOGY;
257 pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_TOPOLOGY;
258}
259
260void VBoxVidPnStTIterInit(PVBOXWDDM_SOURCE pSource, PVBOXWDDM_TARGET paTargets, uint32_t cTargets, VBOXWDDM_TARGET_ITER *pIter)
261{
262 pIter->pSource = pSource;
263 pIter->paTargets = paTargets;
264 pIter->cTargets = cTargets;
265 pIter->i = 0;
266 pIter->c = 0;
267}
268
269PVBOXWDDM_TARGET VBoxVidPnStTIterNext(VBOXWDDM_TARGET_ITER *pIter)
270{
271 PVBOXWDDM_SOURCE pSource = pIter->pSource;
272 if (pSource->cTargets <= pIter->c)
273 return NULL;
274
275 int i = (!pIter->c) ? ASMBitFirstSet(pSource->aTargetMap, pIter->cTargets)
276 : ASMBitNextSet(pSource->aTargetMap, pIter->cTargets, pIter->i);
277 if (i < 0)
278 STOP_FATAL();
279
280 pIter->i = (uint32_t)i;
281 pIter->c++;
282 return &pIter->paTargets[i];
283}
284
285void VBoxVidPnStSourceCleanup(PVBOXWDDM_SOURCE paSources, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, PVBOXWDDM_TARGET paTargets, uint32_t cTargets)
286{
287 PVBOXWDDM_SOURCE pSource = &paSources[VidPnSourceId];
288 VBOXWDDM_TARGET_ITER Iter;
289 VBoxVidPnStTIterInit(pSource, paTargets, cTargets, &Iter);
290 for (PVBOXWDDM_TARGET pTarget = VBoxVidPnStTIterNext(&Iter);
291 pTarget;
292 pTarget = VBoxVidPnStTIterNext(&Iter))
293 {
294 Assert(pTarget->VidPnSourceId == pSource->AllocData.SurfDesc.VidPnSourceId);
295 VBoxVidPnStTargetCleanup(paSources, cTargets, pTarget);
296 /* iterator is not safe wrt target removal, reinit it */
297 VBoxVidPnStTIterInit(pSource, paTargets, cTargets, &Iter);
298 }
299}
300
301void VBoxVidPnStCleanup(PVBOXWDDM_SOURCE paSources, PVBOXWDDM_TARGET paTargets, uint32_t cScreens)
302{
303 for (UINT i = 0; i < cScreens; ++i)
304 {
305 PVBOXWDDM_TARGET pTarget = &paTargets[i];
306 VBoxVidPnStTargetCleanup(paSources, cScreens, pTarget);
307 }
308}
309
310void VBoxVidPnAllocDataInit(VBOXWDDM_ALLOC_DATA *pData, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
311{
312 memset(pData, 0, sizeof (*pData));
313 pData->SurfDesc.VidPnSourceId = VidPnSourceId;
314 pData->Addr.offVram = VBOXVIDEOOFFSET_VOID;
315}
316
317void VBoxVidPnSourceInit(PVBOXWDDM_SOURCE pSource, const D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, uint8_t u8SyncState)
318{
319 memset(pSource, 0, sizeof (*pSource));
320 VBoxVidPnAllocDataInit(&pSource->AllocData, VidPnSourceId);
321 pSource->u8SyncState = (u8SyncState & VBOXWDDM_HGSYNC_F_SYNCED_ALL);
322}
323
324void VBoxVidPnTargetInit(PVBOXWDDM_TARGET pTarget, const D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId, uint8_t u8SyncState)
325{
326 memset(pTarget, 0, sizeof (*pTarget));
327 pTarget->u32Id = VidPnTargetId;
328 pTarget->VidPnSourceId = D3DDDI_ID_UNINITIALIZED;
329 pTarget->u8SyncState = (u8SyncState & VBOXWDDM_HGSYNC_F_SYNCED_ALL);
330}
331
332void VBoxVidPnSourcesInit(PVBOXWDDM_SOURCE pSources, uint32_t cScreens, uint8_t u8SyncState)
333{
334 for (uint32_t i = 0; i < cScreens; ++i)
335 VBoxVidPnSourceInit(&pSources[i], i, u8SyncState);
336}
337
338void VBoxVidPnTargetsInit(PVBOXWDDM_TARGET pTargets, uint32_t cScreens, uint8_t u8SyncState)
339{
340 for (uint32_t i = 0; i < cScreens; ++i)
341 VBoxVidPnTargetInit(&pTargets[i], i, u8SyncState);
342}
343
344void VBoxVidPnSourceCopy(VBOXWDDM_SOURCE *pDst, const VBOXWDDM_SOURCE *pSrc)
345{
346 uint8_t u8SyncState = pDst->u8SyncState;
347 *pDst = *pSrc;
348 pDst->u8SyncState &= u8SyncState;
349}
350
351void VBoxVidPnTargetCopy(VBOXWDDM_TARGET *pDst, const VBOXWDDM_TARGET *pSrc)
352{
353 uint8_t u8SyncState = pDst->u8SyncState;
354 *pDst = *pSrc;
355 pDst->u8SyncState &= u8SyncState;
356}
357
358void VBoxVidPnSourcesCopy(VBOXWDDM_SOURCE *pDst, const VBOXWDDM_SOURCE *pSrc, uint32_t cScreens)
359{
360 for (uint32_t i = 0; i < cScreens; ++i)
361 VBoxVidPnSourceCopy(&pDst[i], &pSrc[i]);
362}
363
364void VBoxVidPnTargetsCopy(VBOXWDDM_TARGET *pDst, const VBOXWDDM_TARGET *pSrc, uint32_t cScreens)
365{
366 for (uint32_t i = 0; i < cScreens; ++i)
367 VBoxVidPnTargetCopy(&pDst[i], &pSrc[i]);
368}
369
370void VBoxDumpSourceTargetArrays(VBOXWDDM_SOURCE *paSources, VBOXWDDM_TARGET *paTargets, uint32_t cScreens)
371{
372 RT_NOREF(paSources, paTargets, cScreens);
373
374 for (uint32_t i = 0; i < cScreens; i++)
375 {
376 LOG_EXACT(("source [%d] Sync 0x%x, cTgt %d, TgtMap0 0x%x, TgtRep %d, blanked %d\n",
377 i, paSources[i].u8SyncState, paSources[i].cTargets, paSources[i].aTargetMap[0], paSources[i].fTargetsReported, paSources[i].bBlankedByPowerOff));
378
379 LOG_EXACT(("target [%d] Sync 0x%x, VidPnSourceId %d, blanked %d\n",
380 i, paTargets[i].u8SyncState, paTargets[i].VidPnSourceId, paTargets[i].fBlankedByPowerOff));
381 }
382}
383
384static D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE vboxVidPnCofuncModalityCurrentPathPivot(D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE enmPivot,
385 const DXGK_ENUM_PIVOT *pPivot,
386 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
387{
388 switch (enmPivot)
389 {
390 case D3DKMDT_EPT_VIDPNSOURCE:
391 if (pPivot->VidPnSourceId == VidPnSourceId)
392 return D3DKMDT_EPT_VIDPNSOURCE;
393 if (pPivot->VidPnSourceId == D3DDDI_ID_ALL)
394 {
395#ifdef DEBUG_misha
396 AssertFailed();
397#endif
398 return D3DKMDT_EPT_VIDPNSOURCE;
399 }
400 return D3DKMDT_EPT_NOPIVOT;
401 case D3DKMDT_EPT_VIDPNTARGET:
402 if (pPivot->VidPnTargetId == VidPnTargetId)
403 return D3DKMDT_EPT_VIDPNTARGET;
404 if (pPivot->VidPnTargetId == D3DDDI_ID_ALL)
405 {
406#ifdef DEBUG_misha
407 AssertFailed();
408#endif
409 return D3DKMDT_EPT_VIDPNTARGET;
410 }
411 return D3DKMDT_EPT_NOPIVOT;
412 case D3DKMDT_EPT_SCALING:
413 case D3DKMDT_EPT_ROTATION:
414 case D3DKMDT_EPT_NOPIVOT:
415 return D3DKMDT_EPT_NOPIVOT;
416 default:
417 WARN(("unexpected pivot"));
418 return D3DKMDT_EPT_NOPIVOT;
419 }
420}
421
422NTSTATUS vboxVidPnQueryPinnedTargetMode(D3DKMDT_HVIDPN hVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface,
423 D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId, RTRECTSIZE *pSize)
424{
425 D3DKMDT_HVIDPNTARGETMODESET hCurVidPnTargetModeSet;
426 const DXGK_VIDPNTARGETMODESET_INTERFACE *pCurVidPnTargetModeSetInterface;
427 pSize->cx = 0;
428 pSize->cy = 0;
429 NTSTATUS Status = pVidPnInterface->pfnAcquireTargetModeSet(hVidPn,
430 VidPnTargetId,
431 &hCurVidPnTargetModeSet,
432 &pCurVidPnTargetModeSetInterface);
433 if (!NT_SUCCESS(Status))
434 {
435 WARN(("pfnAcquireTargetModeSet failed Status(0x%x)", Status));
436 return Status;
437 }
438
439 CONST D3DKMDT_VIDPN_TARGET_MODE* pPinnedVidPnTargetModeInfo;
440 Status = pCurVidPnTargetModeSetInterface->pfnAcquirePinnedModeInfo(hCurVidPnTargetModeSet, &pPinnedVidPnTargetModeInfo);
441 if (Status == STATUS_GRAPHICS_MODE_NOT_PINNED)
442 {
443 pPinnedVidPnTargetModeInfo = NULL;
444 Status = STATUS_SUCCESS;
445 }
446 else if (!NT_SUCCESS(Status))
447 {
448 WARN(("pfnAcquirePinnedModeInfo failed Status(0x%x)", Status));
449 }
450 else
451 {
452 Assert(pPinnedVidPnTargetModeInfo);
453 pSize->cx = pPinnedVidPnTargetModeInfo->VideoSignalInfo.ActiveSize.cx;
454 pSize->cy = pPinnedVidPnTargetModeInfo->VideoSignalInfo.ActiveSize.cy;
455 NTSTATUS rcNt2 = pCurVidPnTargetModeSetInterface->pfnReleaseModeInfo(hCurVidPnTargetModeSet, pPinnedVidPnTargetModeInfo);
456 AssertNtStatus(rcNt2);
457 }
458
459 NTSTATUS rcNt2 = pVidPnInterface->pfnReleaseTargetModeSet(hVidPn, hCurVidPnTargetModeSet);
460 AssertNtStatusSuccess(rcNt2);
461
462 return Status;
463}
464
465NTSTATUS vboxVidPnQueryPinnedSourceMode(D3DKMDT_HVIDPN hVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface,
466 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, RTRECTSIZE *pSize)
467{
468 D3DKMDT_HVIDPNSOURCEMODESET hCurVidPnSourceModeSet;
469 const DXGK_VIDPNSOURCEMODESET_INTERFACE *pCurVidPnSourceModeSetInterface;
470 pSize->cx = 0;
471 pSize->cy = 0;
472 NTSTATUS Status = pVidPnInterface->pfnAcquireSourceModeSet(hVidPn,
473 VidPnSourceId,
474 &hCurVidPnSourceModeSet,
475 &pCurVidPnSourceModeSetInterface);
476 if (!NT_SUCCESS(Status))
477 {
478 WARN(("pfnAcquireSourceModeSet failed Status(0x%x)", Status));
479 return Status;
480 }
481
482 CONST D3DKMDT_VIDPN_SOURCE_MODE* pPinnedVidPnSourceModeInfo;
483 Status = pCurVidPnSourceModeSetInterface->pfnAcquirePinnedModeInfo(hCurVidPnSourceModeSet, &pPinnedVidPnSourceModeInfo);
484 if (Status == STATUS_GRAPHICS_MODE_NOT_PINNED)
485 {
486 pPinnedVidPnSourceModeInfo = NULL;
487 Status = STATUS_SUCCESS;
488 }
489 else if (!NT_SUCCESS(Status))
490 {
491 WARN(("pfnAcquirePinnedModeInfo failed Status(0x%x)", Status));
492 }
493 else
494 {
495 Assert(pPinnedVidPnSourceModeInfo);
496 pSize->cx = pPinnedVidPnSourceModeInfo->Format.Graphics.VisibleRegionSize.cx;
497 pSize->cy = pPinnedVidPnSourceModeInfo->Format.Graphics.VisibleRegionSize.cy;
498 NTSTATUS rcNt2 = pCurVidPnSourceModeSetInterface->pfnReleaseModeInfo(hCurVidPnSourceModeSet, pPinnedVidPnSourceModeInfo);
499 AssertNtStatus(rcNt2);
500 }
501
502 NTSTATUS rcNt2 = pVidPnInterface->pfnReleaseSourceModeSet(hVidPn, hCurVidPnSourceModeSet);
503 AssertNtStatusSuccess(rcNt2);
504
505 return Status;
506}
507
508static NTSTATUS vboxVidPnSourceModeSetToArray(D3DKMDT_HVIDPNSOURCEMODESET hVidPnModeSet,
509 const DXGK_VIDPNSOURCEMODESET_INTERFACE *pVidPnModeSetInterface,
510 CR_SORTARRAY *pArray)
511{
512 VBOXVIDPN_SOURCEMODE_ITER Iter;
513 const D3DKMDT_VIDPN_SOURCE_MODE *pVidPnModeInfo;
514
515 VBoxVidPnSourceModeIterInit(&Iter, hVidPnModeSet, pVidPnModeSetInterface);
516
517 while ((pVidPnModeInfo = VBoxVidPnSourceModeIterNext(&Iter)) != NULL)
518 {
519 RTRECTSIZE size;
520 size.cx = pVidPnModeInfo->Format.Graphics.VisibleRegionSize.cx;
521 size.cy = pVidPnModeInfo->Format.Graphics.VisibleRegionSize.cy;
522 int rc = CrSaAdd(pArray, CR_RSIZE2U64(size));
523 if (RT_FAILURE(rc))
524 {
525 WARN(("CrSaAdd failed %d", rc));
526 VBoxVidPnSourceModeIterTerm(&Iter);
527 return STATUS_UNSUCCESSFUL;
528 }
529 }
530
531 VBoxVidPnSourceModeIterTerm(&Iter);
532
533 return VBoxVidPnSourceModeIterStatus(&Iter);
534}
535
536static NTSTATUS vboxVidPnSourceModeSetFromArray(D3DKMDT_HVIDPNSOURCEMODESET hVidPnModeSet,
537 const DXGK_VIDPNSOURCEMODESET_INTERFACE *pVidPnModeSetInterface,
538 const CR_SORTARRAY *pArray)
539{
540 for (uint32_t i = 0; i < CrSaGetSize(pArray); ++i)
541 {
542 RTRECTSIZE size = CR_U642RSIZE(CrSaGetVal(pArray, i));
543
544 D3DKMDT_VIDPN_SOURCE_MODE *pVidPnModeInfo;
545 NTSTATUS Status = pVidPnModeSetInterface->pfnCreateNewModeInfo(hVidPnModeSet, &pVidPnModeInfo);
546 if (!NT_SUCCESS(Status))
547 {
548 WARN(("pfnCreateNewModeInfo failed, Status 0x%x", Status));
549 return Status;
550 }
551
552 vboxVidPnPopulateSourceModeInfo(pVidPnModeInfo, &size);
553
554 Status = pVidPnModeSetInterface->pfnAddMode(hVidPnModeSet, pVidPnModeInfo);
555 if (!NT_SUCCESS(Status))
556 {
557 WARN(("pfnAddMode (%d x %d) failed, Status 0x%x", size.cx, size.cy, Status));
558 VBoxVidPnDumpSourceMode("SourceMode: ", pVidPnModeInfo, "\n");
559 NTSTATUS rcNt2 = pVidPnModeSetInterface->pfnReleaseModeInfo(hVidPnModeSet, pVidPnModeInfo);
560 AssertNtStatusSuccess(rcNt2);
561 // Continue adding modes into modeset even if a mode was rejected
562 continue;
563 }
564 }
565
566 return STATUS_SUCCESS;
567}
568
569static NTSTATUS vboxVidPnTargetModeSetToArray(D3DKMDT_HVIDPNTARGETMODESET hVidPnModeSet,
570 const DXGK_VIDPNTARGETMODESET_INTERFACE *pVidPnModeSetInterface,
571 CR_SORTARRAY *pArray)
572{
573 VBOXVIDPN_TARGETMODE_ITER Iter;
574 const D3DKMDT_VIDPN_TARGET_MODE *pVidPnModeInfo;
575
576 VBoxVidPnTargetModeIterInit(&Iter, hVidPnModeSet, pVidPnModeSetInterface);
577
578 while ((pVidPnModeInfo = VBoxVidPnTargetModeIterNext(&Iter)) != NULL)
579 {
580 RTRECTSIZE size;
581 size.cx = pVidPnModeInfo->VideoSignalInfo.ActiveSize.cx;
582 size.cy = pVidPnModeInfo->VideoSignalInfo.ActiveSize.cy;
583 int rc = CrSaAdd(pArray, CR_RSIZE2U64(size));
584 if (RT_FAILURE(rc))
585 {
586 WARN(("CrSaAdd failed %d", rc));
587 VBoxVidPnTargetModeIterTerm(&Iter);
588 return STATUS_UNSUCCESSFUL;
589 }
590 }
591
592 VBoxVidPnTargetModeIterTerm(&Iter);
593
594 return VBoxVidPnTargetModeIterStatus(&Iter);
595}
596
597static NTSTATUS vboxVidPnTargetModeSetFromArray(D3DKMDT_HVIDPNTARGETMODESET hVidPnModeSet,
598 const DXGK_VIDPNTARGETMODESET_INTERFACE *pVidPnModeSetInterface,
599 const CR_SORTARRAY *pArray)
600{
601 for (uint32_t i = 0; i < CrSaGetSize(pArray); ++i)
602 {
603 RTRECTSIZE size = CR_U642RSIZE(CrSaGetVal(pArray, i));
604
605 D3DKMDT_VIDPN_TARGET_MODE *pVidPnModeInfo;
606 NTSTATUS Status = pVidPnModeSetInterface->pfnCreateNewModeInfo(hVidPnModeSet, &pVidPnModeInfo);
607 if (!NT_SUCCESS(Status))
608 {
609 WARN(("pfnCreateNewModeInfo failed, Status 0x%x", Status));
610 return Status;
611 }
612
613 vboxVidPnPopulateTargetModeInfo(pVidPnModeInfo, &size);
614
615 Status = pVidPnModeSetInterface->pfnAddMode(hVidPnModeSet, pVidPnModeInfo);
616 if (!NT_SUCCESS(Status))
617 {
618 WARN(("pfnAddMode (%d x %d) failed, Status 0x%x", size.cx, size.cy, Status));
619 VBoxVidPnDumpTargetMode("TargetMode: ", pVidPnModeInfo, "\n");
620 NTSTATUS rcNt2 = pVidPnModeSetInterface->pfnReleaseModeInfo(hVidPnModeSet, pVidPnModeInfo);
621 AssertNtStatusSuccess(rcNt2);
622 // Continue adding modes into modeset even if a mode was rejected
623 continue;
624 }
625 }
626
627 return STATUS_SUCCESS;
628}
629
630static NTSTATUS vboxVidPnMonitorModeSetToArray(D3DKMDT_HMONITORSOURCEMODESET hVidPnModeSet,
631 const DXGK_MONITORSOURCEMODESET_INTERFACE *pVidPnModeSetInterface,
632 CR_SORTARRAY *pArray)
633{
634 VBOXVIDPN_MONITORMODE_ITER Iter;
635 const D3DKMDT_MONITOR_SOURCE_MODE *pVidPnModeInfo;
636
637 VBoxVidPnMonitorModeIterInit(&Iter, hVidPnModeSet, pVidPnModeSetInterface);
638
639 while ((pVidPnModeInfo = VBoxVidPnMonitorModeIterNext(&Iter)) != NULL)
640 {
641 RTRECTSIZE size;
642 size.cx = pVidPnModeInfo->VideoSignalInfo.ActiveSize.cx;
643 size.cy = pVidPnModeInfo->VideoSignalInfo.ActiveSize.cy;
644 int rc = CrSaAdd(pArray, CR_RSIZE2U64(size));
645 if (RT_FAILURE(rc))
646 {
647 WARN(("CrSaAdd failed %d", rc));
648 VBoxVidPnMonitorModeIterTerm(&Iter);
649 return STATUS_UNSUCCESSFUL;
650 }
651 }
652
653 VBoxVidPnMonitorModeIterTerm(&Iter);
654
655 return VBoxVidPnMonitorModeIterStatus(&Iter);
656}
657
658static NTSTATUS vboxVidPnMonitorModeSetFromArray(D3DKMDT_HMONITORSOURCEMODESET hVidPnModeSet,
659 const DXGK_MONITORSOURCEMODESET_INTERFACE *pVidPnModeSetInterface,
660 const CR_SORTARRAY *pArray)
661{
662 for (uint32_t i = 0; i < CrSaGetSize(pArray); ++i)
663 {
664 RTRECTSIZE size = CR_U642RSIZE(CrSaGetVal(pArray, i));
665
666 D3DKMDT_MONITOR_SOURCE_MODE *pVidPnModeInfo;
667 NTSTATUS Status = pVidPnModeSetInterface->pfnCreateNewModeInfo(hVidPnModeSet, &pVidPnModeInfo);
668 if (!NT_SUCCESS(Status))
669 {
670 WARN(("pfnCreateNewModeInfo failed, Status 0x%x", Status));
671 return Status;
672 }
673
674 vboxVidPnPopulateMonitorModeInfo(pVidPnModeInfo, &size);
675
676 Status = pVidPnModeSetInterface->pfnAddMode(hVidPnModeSet, pVidPnModeInfo);
677 if (!NT_SUCCESS(Status))
678 {
679 WARN(("pfnAddMode (%d x %d) failed, Status 0x%x", size.cx, size.cy, Status));
680 NTSTATUS rcNt2 = pVidPnModeSetInterface->pfnReleaseModeInfo(hVidPnModeSet, pVidPnModeInfo);
681 AssertNtStatusSuccess(rcNt2);
682 // Continue adding modes into modeset even if a mode was rejected
683 continue;
684 }
685
686 LOGF(("mode (%d x %d) added to monitor modeset", size.cx, size.cy));
687 }
688
689 return STATUS_SUCCESS;
690}
691
692
693static NTSTATUS vboxVidPnCollectInfoForPathTarget(PVBOXMP_DEVEXT pDevExt,
694 D3DKMDT_HVIDPN hVidPn,
695 const DXGK_VIDPN_INTERFACE* pVidPnInterface,
696 D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE enmCurPivot,
697 uint32_t *aAdjustedModeMap,
698 CR_SORTARRAY *aModes,
699 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
700{
701 const CR_SORTARRAY* pSupportedModes = VBoxWddmVModesGet(pDevExt, VidPnTargetId);
702 NTSTATUS Status;
703 if (enmCurPivot == D3DKMDT_EPT_VIDPNTARGET)
704 {
705 D3DKMDT_HVIDPNTARGETMODESET hVidPnModeSet;
706 const DXGK_VIDPNTARGETMODESET_INTERFACE *pVidPnModeSetInterface;
707 Status = pVidPnInterface->pfnAcquireTargetModeSet(hVidPn,
708 VidPnTargetId,
709 &hVidPnModeSet,
710 &pVidPnModeSetInterface);
711 if (!NT_SUCCESS(Status))
712 {
713 WARN(("pfnAcquireTargetModeSet failed %#x", Status));
714 return Status;
715 }
716
717 /* intersect modes from target */
718 if (!ASMBitTest(aAdjustedModeMap, VidPnTargetId))
719 {
720 Status = vboxVidPnTargetModeSetToArray(hVidPnModeSet, pVidPnModeSetInterface, &aModes[VidPnTargetId]);
721 ASMBitSet(aAdjustedModeMap, VidPnTargetId);
722 }
723 else
724 {
725 CR_SORTARRAY Arr;
726 CrSaInit(&Arr, 0);
727 Status = vboxVidPnTargetModeSetToArray(hVidPnModeSet, pVidPnModeSetInterface, &aModes[VidPnTargetId]);
728 CrSaIntersect(&aModes[VidPnTargetId], &Arr);
729 CrSaCleanup(&Arr);
730 }
731
732 NTSTATUS rcNt2 = pVidPnInterface->pfnReleaseTargetModeSet(hVidPn, hVidPnModeSet);
733 AssertNtStatusSuccess(rcNt2);
734
735 if (!NT_SUCCESS(Status))
736 {
737 WARN(("vboxVidPnTargetModeSetToArray failed %#x", Status));
738 return Status;
739 }
740
741 return STATUS_SUCCESS;
742 }
743
744 RTRECTSIZE pinnedSize = {0};
745 Status = vboxVidPnQueryPinnedTargetMode(hVidPn, pVidPnInterface, VidPnTargetId, &pinnedSize);
746 if (!NT_SUCCESS(Status))
747 {
748 WARN(("vboxVidPnQueryPinnedTargetMode failed %#x", Status));
749 return Status;
750 }
751
752 if (pinnedSize.cx)
753 {
754 Assert(CrSaContains(pSupportedModes, CR_RSIZE2U64(pinnedSize)));
755
756 if (!ASMBitTest(aAdjustedModeMap, VidPnTargetId))
757 {
758 Assert(CrSaGetSize(&aModes[VidPnTargetId]) == 0);
759 int rc = CrSaAdd(&aModes[VidPnTargetId], CR_RSIZE2U64(pinnedSize));
760 if (!RT_SUCCESS(rc))
761 {
762 WARN(("CrSaAdd failed %d", rc));
763 return STATUS_UNSUCCESSFUL;
764 }
765 ASMBitSet(aAdjustedModeMap, VidPnTargetId);
766 }
767 else
768 {
769 CrSaClear(&aModes[VidPnTargetId]);
770 int rc = CrSaAdd(&aModes[VidPnTargetId], CR_RSIZE2U64(pinnedSize));
771 if (!RT_SUCCESS(rc))
772 {
773 WARN(("CrSaAdd failed %d", rc));
774 return STATUS_UNSUCCESSFUL;
775 }
776 }
777
778 return STATUS_SUCCESS;
779 }
780
781
782 Status = vboxVidPnQueryPinnedSourceMode(hVidPn, pVidPnInterface, VidPnSourceId, &pinnedSize);
783 if (!NT_SUCCESS(Status))
784 {
785 WARN(("vboxVidPnQueryPinnedSourceMode failed %#x", Status));
786 return Status;
787 }
788
789 if (pinnedSize.cx)
790 {
791 if (!ASMBitTest(aAdjustedModeMap, VidPnTargetId))
792 {
793 Assert(CrSaGetSize(&aModes[VidPnTargetId]) == 0);
794 if (CrSaContains(pSupportedModes, CR_RSIZE2U64(pinnedSize)))
795 {
796 int rc = CrSaAdd(&aModes[VidPnTargetId], CR_RSIZE2U64(pinnedSize));
797 if (!RT_SUCCESS(rc))
798 {
799 WARN(("CrSaAdd failed %d", rc));
800 return STATUS_UNSUCCESSFUL;
801 }
802 }
803 ASMBitSet(aAdjustedModeMap, VidPnTargetId);
804 }
805 else
806 {
807 CrSaClear(&aModes[VidPnTargetId]);
808 if (CrSaContains(pSupportedModes, CR_RSIZE2U64(pinnedSize)))
809 {
810 int rc = CrSaAdd(&aModes[VidPnTargetId], CR_RSIZE2U64(pinnedSize));
811 if (!RT_SUCCESS(rc))
812 {
813 WARN(("CrSaAdd failed %d", rc));
814 return STATUS_UNSUCCESSFUL;
815 }
816 }
817 }
818
819 return STATUS_SUCCESS;
820 }
821
822 /* now we are here because no pinned info is specified, we need to populate it based on the supported info
823 * and modes already configured,
824 * this is pretty simple actually */
825
826 if (!ASMBitTest(aAdjustedModeMap, VidPnTargetId))
827 {
828 Assert(CrSaGetSize(&aModes[VidPnTargetId]) == 0);
829 int rc = CrSaClone(pSupportedModes, &aModes[VidPnTargetId]);
830 if (!RT_SUCCESS(rc))
831 {
832 WARN(("CrSaClone failed %d", rc));
833 return STATUS_UNSUCCESSFUL;
834 }
835 ASMBitSet(aAdjustedModeMap, VidPnTargetId);
836 }
837 else
838 {
839 CrSaIntersect(&aModes[VidPnTargetId], pSupportedModes);
840 }
841
842 /* we are done */
843 return STATUS_SUCCESS;
844}
845
846static NTSTATUS vboxVidPnApplyInfoForPathTarget(PVBOXMP_DEVEXT pDevExt,
847 D3DKMDT_HVIDPN hVidPn,
848 const DXGK_VIDPN_INTERFACE* pVidPnInterface,
849 D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE enmCurPivot,
850 uint32_t *aAdjustedModeMap,
851 const CR_SORTARRAY *aModes,
852 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId,
853 D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
854{
855 RT_NOREF(aAdjustedModeMap, VidPnSourceId);
856 Assert(ASMBitTest(aAdjustedModeMap, VidPnTargetId));
857
858 if (enmCurPivot == D3DKMDT_EPT_VIDPNTARGET)
859 return STATUS_SUCCESS;
860
861 RTRECTSIZE pinnedSize = {0};
862 NTSTATUS Status = vboxVidPnQueryPinnedTargetMode(hVidPn, pVidPnInterface, VidPnTargetId, &pinnedSize);
863 if (!NT_SUCCESS(Status))
864 {
865 WARN(("vboxVidPnQueryPinnedTargetMode failed %#x", Status));
866 return Status;
867 }
868
869 if (pinnedSize.cx)
870 return STATUS_SUCCESS;
871
872 /* now just create the new source mode set and apply it */
873 D3DKMDT_HVIDPNTARGETMODESET hVidPnModeSet;
874 const DXGK_VIDPNTARGETMODESET_INTERFACE *pVidPnModeSetInterface;
875 Status = pVidPnInterface->pfnCreateNewTargetModeSet(hVidPn,
876 VidPnTargetId,
877 &hVidPnModeSet,
878 &pVidPnModeSetInterface);
879 if (!NT_SUCCESS(Status))
880 {
881 WARN(("pfnCreateNewTargetModeSet failed Status(0x%x)", Status));
882 return Status;
883 }
884
885 Status = vboxVidPnTargetModeSetFromArray(hVidPnModeSet,
886 pVidPnModeSetInterface,
887 &aModes[VidPnTargetId]);
888 if (!NT_SUCCESS(Status))
889 {
890 WARN(("vboxVidPnTargetModeSetFromArray failed Status(0x%x)", Status));
891 vboxVidPnDumpVidPn("\nVidPn: ---------\n", pDevExt, hVidPn, pVidPnInterface, "\n------\n");
892 VBoxVidPnDumpMonitorModeSet("MonModeSet: --------\n", pDevExt, VidPnTargetId, "\n------\n");
893 NTSTATUS rcNt2 = pVidPnInterface->pfnReleaseTargetModeSet(hVidPn, hVidPnModeSet);
894 AssertNtStatusSuccess(rcNt2);
895 return Status;
896 }
897
898 Status = pVidPnInterface->pfnAssignTargetModeSet(hVidPn, VidPnTargetId, hVidPnModeSet);
899 if (!NT_SUCCESS(Status))
900 {
901 WARN(("\n\n!!!!!!!\n\n pfnAssignTargetModeSet failed, Status(0x%x)", Status));
902 vboxVidPnDumpVidPn("\nVidPn: ---------\n", pDevExt, hVidPn, pVidPnInterface, "\n------\n");
903 VBoxVidPnDumpMonitorModeSet("MonModeSet: --------\n", pDevExt, VidPnTargetId, "\n------\n");
904 NTSTATUS rcNt2 = pVidPnInterface->pfnReleaseTargetModeSet(hVidPn, hVidPnModeSet);
905 AssertNtStatusSuccess(rcNt2);
906 return Status;
907 }
908
909 Status = vboxVidPnCheckMonitorModes(pDevExt, VidPnTargetId, &aModes[VidPnTargetId]);
910
911 if (!NT_SUCCESS(Status))
912 {
913 WARN(("vboxVidPnCheckMonitorModes failed, Status(0x%x)", Status));
914 return Status;
915 }
916
917 return STATUS_SUCCESS;
918}
919
920static NTSTATUS vboxVidPnApplyInfoForPathSource(PVBOXMP_DEVEXT pDevExt,
921 D3DKMDT_HVIDPN hVidPn,
922 const DXGK_VIDPN_INTERFACE* pVidPnInterface,
923 D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE enmCurPivot,
924 uint32_t *aAdjustedModeMap,
925 const CR_SORTARRAY *aModes,
926 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
927{
928 RT_NOREF(aAdjustedModeMap);
929 Assert(ASMBitTest(aAdjustedModeMap, VidPnTargetId));
930
931 if (enmCurPivot == D3DKMDT_EPT_VIDPNSOURCE)
932 return STATUS_SUCCESS;
933
934 RTRECTSIZE pinnedSize = {0};
935 NTSTATUS Status = vboxVidPnQueryPinnedSourceMode(hVidPn, pVidPnInterface, VidPnSourceId, &pinnedSize);
936 if (!NT_SUCCESS(Status))
937 {
938 WARN(("vboxVidPnQueryPinnedSourceMode failed %#x", Status));
939 return Status;
940 }
941
942 if (pinnedSize.cx)
943 return STATUS_SUCCESS;
944
945 /* now just create the new source mode set and apply it */
946 D3DKMDT_HVIDPNSOURCEMODESET hVidPnModeSet;
947 const DXGK_VIDPNSOURCEMODESET_INTERFACE *pVidPnModeSetInterface;
948 Status = pVidPnInterface->pfnCreateNewSourceModeSet(hVidPn,
949 VidPnSourceId,
950 &hVidPnModeSet,
951 &pVidPnModeSetInterface);
952 if (!NT_SUCCESS(Status))
953 {
954 WARN(("pfnCreateNewSourceModeSet failed Status(0x%x)", Status));
955 return Status;
956 }
957
958 Status = vboxVidPnSourceModeSetFromArray(hVidPnModeSet,
959 pVidPnModeSetInterface,
960 &aModes[VidPnTargetId]); /* <- target modes always! */
961 if (!NT_SUCCESS(Status))
962 {
963 WARN(("vboxVidPnSourceModeSetFromArray failed Status(0x%x)", Status));
964 vboxVidPnDumpVidPn("\nVidPn: ---------\n", pDevExt, hVidPn, pVidPnInterface, "\n------\n");
965 VBoxVidPnDumpMonitorModeSet("MonModeSet: --------\n", pDevExt, VidPnTargetId, "\n------\n");
966 NTSTATUS rcNt2 = pVidPnInterface->pfnReleaseSourceModeSet(hVidPn, hVidPnModeSet);
967 AssertNtStatusSuccess(rcNt2);
968 return Status;
969 }
970
971 Status = pVidPnInterface->pfnAssignSourceModeSet(hVidPn, VidPnSourceId, hVidPnModeSet);
972 if (!NT_SUCCESS(Status))
973 {
974 WARN(("\n\n!!!!!!!\n\n pfnAssignSourceModeSet failed, Status(0x%x)", Status));
975 vboxVidPnDumpVidPn("\nVidPn: ---------\n", pDevExt, hVidPn, pVidPnInterface, "\n------\n");
976 VBoxVidPnDumpMonitorModeSet("MonModeSet: --------\n", pDevExt, VidPnTargetId, "\n------\n");
977 NTSTATUS rcNt2 = pVidPnInterface->pfnReleaseSourceModeSet(hVidPn, hVidPnModeSet);
978 AssertNtStatusSuccess(rcNt2);
979 return Status;
980 }
981
982 return STATUS_SUCCESS;
983}
984
985static NTSTATUS vboxVidPnCollectInfoForPathSource(PVBOXMP_DEVEXT pDevExt,
986 D3DKMDT_HVIDPN hVidPn,
987 const DXGK_VIDPN_INTERFACE* pVidPnInterface,
988 D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE enmCurPivot,
989 uint32_t *aAdjustedModeMap,
990 CR_SORTARRAY *aModes,
991 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
992{
993 const CR_SORTARRAY* pSupportedModes = VBoxWddmVModesGet(pDevExt, VidPnTargetId); /* <- yes, modes are target-determined always */
994 NTSTATUS Status;
995
996 if (enmCurPivot == D3DKMDT_EPT_VIDPNSOURCE)
997 {
998 D3DKMDT_HVIDPNSOURCEMODESET hVidPnModeSet;
999 const DXGK_VIDPNSOURCEMODESET_INTERFACE *pVidPnModeSetInterface;
1000 Status = pVidPnInterface->pfnAcquireSourceModeSet(hVidPn,
1001 VidPnSourceId,
1002 &hVidPnModeSet,
1003 &pVidPnModeSetInterface);
1004 if (!NT_SUCCESS(Status))
1005 {
1006 WARN(("pfnAcquireSourceModeSet failed %#x", Status));
1007 return Status;
1008 }
1009
1010 /* intersect modes from target */
1011 if (!ASMBitTest(aAdjustedModeMap, VidPnTargetId))
1012 {
1013 Status = vboxVidPnSourceModeSetToArray(hVidPnModeSet, pVidPnModeSetInterface, &aModes[VidPnTargetId]);
1014 ASMBitSet(aAdjustedModeMap, VidPnTargetId);
1015 }
1016 else
1017 {
1018 CR_SORTARRAY Arr;
1019 CrSaInit(&Arr, 0);
1020 Status = vboxVidPnSourceModeSetToArray(hVidPnModeSet, pVidPnModeSetInterface, &aModes[VidPnTargetId]);
1021 CrSaIntersect(&aModes[VidPnTargetId], &Arr);
1022 CrSaCleanup(&Arr);
1023 }
1024
1025 NTSTATUS rcNt2 = pVidPnInterface->pfnReleaseSourceModeSet(hVidPn, hVidPnModeSet);
1026 AssertNtStatusSuccess(rcNt2);
1027
1028 if (!NT_SUCCESS(Status))
1029 {
1030 WARN(("pfnReleaseSourceModeSet failed %#x", Status));
1031 return Status;
1032 }
1033
1034 /* intersect it with supported target modes, just in case */
1035 CrSaIntersect(&aModes[VidPnTargetId], pSupportedModes);
1036
1037 return STATUS_SUCCESS;
1038 }
1039
1040 RTRECTSIZE pinnedSize = {0};
1041 Status = vboxVidPnQueryPinnedSourceMode(hVidPn, pVidPnInterface, VidPnSourceId, &pinnedSize);
1042 if (!NT_SUCCESS(Status))
1043 {
1044 WARN(("vboxVidPnQueryPinnedSourceMode failed %#x", Status));
1045 return Status;
1046 }
1047
1048 if (pinnedSize.cx)
1049 {
1050 Assert(CrSaContains(pSupportedModes, CR_RSIZE2U64(pinnedSize)));
1051
1052 if (!ASMBitTest(aAdjustedModeMap, VidPnTargetId))
1053 {
1054 Assert(CrSaGetSize(&aModes[VidPnTargetId]) == 0);
1055
1056 if (CrSaContains(pSupportedModes, CR_RSIZE2U64(pinnedSize)))
1057 {
1058 int rc = CrSaAdd(&aModes[VidPnTargetId], CR_RSIZE2U64(pinnedSize));
1059 if (!RT_SUCCESS(rc))
1060 {
1061 WARN(("CrSaAdd failed %d", rc));
1062 return STATUS_UNSUCCESSFUL;
1063 }
1064 }
1065 ASMBitSet(aAdjustedModeMap, VidPnTargetId);
1066 }
1067 else
1068 {
1069 CrSaClear(&aModes[VidPnTargetId]);
1070 if (CrSaContains(pSupportedModes, CR_RSIZE2U64(pinnedSize)))
1071 {
1072 int rc = CrSaAdd(&aModes[VidPnTargetId], CR_RSIZE2U64(pinnedSize));
1073 if (!RT_SUCCESS(rc))
1074 {
1075 WARN(("CrSaAdd failed %d", rc));
1076 return STATUS_UNSUCCESSFUL;
1077 }
1078 }
1079 }
1080
1081 return STATUS_SUCCESS;
1082 }
1083
1084
1085 Status = vboxVidPnQueryPinnedTargetMode(hVidPn, pVidPnInterface, VidPnTargetId, &pinnedSize);
1086 if (!NT_SUCCESS(Status))
1087 {
1088 WARN(("vboxVidPnQueryPinnedTargetMode failed %#x", Status));
1089 return Status;
1090 }
1091
1092 if (pinnedSize.cx)
1093 {
1094 Assert(CrSaContains(pSupportedModes, CR_RSIZE2U64(pinnedSize)));
1095
1096 if (!ASMBitTest(aAdjustedModeMap, VidPnTargetId))
1097 {
1098 Assert(CrSaGetSize(&aModes[VidPnTargetId]) == 0);
1099 int rc = CrSaAdd(&aModes[VidPnTargetId], CR_RSIZE2U64(pinnedSize));
1100 if (!RT_SUCCESS(rc))
1101 {
1102 WARN(("CrSaAdd failed %d", rc));
1103 return STATUS_UNSUCCESSFUL;
1104 }
1105 ASMBitSet(aAdjustedModeMap, VidPnTargetId);
1106 }
1107 else
1108 {
1109 CrSaClear(&aModes[VidPnTargetId]);
1110 int rc = CrSaAdd(&aModes[VidPnTargetId], CR_RSIZE2U64(pinnedSize));
1111 if (!RT_SUCCESS(rc))
1112 {
1113 WARN(("CrSaAdd failed %d", rc));
1114 return STATUS_UNSUCCESSFUL;
1115 }
1116 }
1117
1118 return STATUS_SUCCESS;
1119 }
1120
1121 /* now we are here because no pinned info is specified, we need to populate it based on the supported info
1122 * and modes already configured,
1123 * this is pretty simple actually */
1124
1125 if (!ASMBitTest(aAdjustedModeMap, VidPnTargetId))
1126 {
1127 Assert(CrSaGetSize(&aModes[VidPnTargetId]) == 0);
1128 int rc = CrSaClone(pSupportedModes, &aModes[VidPnTargetId]);
1129 if (!RT_SUCCESS(rc))
1130 {
1131 WARN(("CrSaClone failed %d", rc));
1132 return STATUS_UNSUCCESSFUL;
1133 }
1134 ASMBitSet(aAdjustedModeMap, VidPnTargetId);
1135 }
1136 else
1137 {
1138 CrSaIntersect(&aModes[VidPnTargetId], pSupportedModes);
1139 }
1140
1141 /* we are done */
1142 return STATUS_SUCCESS;
1143}
1144
1145static NTSTATUS vboxVidPnCheckMonitorModes(PVBOXMP_DEVEXT pDevExt, uint32_t u32Target, const CR_SORTARRAY *pSupportedModes)
1146{
1147 NTSTATUS Status;
1148 CONST DXGK_MONITOR_INTERFACE *pMonitorInterface;
1149 Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryMonitorInterface(pDevExt->u.primary.DxgkInterface.DeviceHandle, DXGK_MONITOR_INTERFACE_VERSION_V1, &pMonitorInterface);
1150 if (!NT_SUCCESS(Status))
1151 {
1152 WARN(("DxgkCbQueryMonitorInterface failed, Status()0x%x", Status));
1153 return Status;
1154 }
1155
1156 D3DKMDT_HMONITORSOURCEMODESET hVidPnModeSet;
1157 CONST DXGK_MONITORSOURCEMODESET_INTERFACE *pVidPnModeSetInterface;
1158
1159 if (!pSupportedModes)
1160 {
1161 pSupportedModes = VBoxWddmVModesGet(pDevExt, u32Target);
1162 }
1163
1164 CR_SORTARRAY DiffModes;
1165 int rc = CrSaInit(&DiffModes, CrSaGetSize(pSupportedModes));
1166 if (!RT_SUCCESS(rc))
1167 {
1168 WARN(("CrSaInit failed"));
1169 return STATUS_NO_MEMORY;
1170 }
1171
1172
1173 Status = pMonitorInterface->pfnAcquireMonitorSourceModeSet(pDevExt->u.primary.DxgkInterface.DeviceHandle,
1174 u32Target,
1175 &hVidPnModeSet,
1176 &pVidPnModeSetInterface);
1177 if (!NT_SUCCESS(Status))
1178 {
1179 WARN(("DxgkCbQueryMonitorInterface failed, Status()0x%x", Status));
1180// if (Status == STATUS_GRAPHICS_MONITOR_NOT_CONNECTED)
1181 CrSaCleanup(&DiffModes);
1182 return Status;
1183 }
1184
1185 VBOXVIDPN_MONITORMODE_ITER Iter;
1186 const D3DKMDT_MONITOR_SOURCE_MODE *pVidPnModeInfo;
1187
1188 rc = CrSaClone(pSupportedModes, &DiffModes);
1189 if (!RT_SUCCESS(rc))
1190 {
1191 WARN(("CrSaClone failed"));
1192 Status = STATUS_NO_MEMORY;
1193 goto done;
1194 }
1195
1196 VBoxVidPnMonitorModeIterInit(&Iter, hVidPnModeSet, pVidPnModeSetInterface);
1197
1198 while ((pVidPnModeInfo = VBoxVidPnMonitorModeIterNext(&Iter)) != NULL)
1199 {
1200 RTRECTSIZE size;
1201 size.cx = pVidPnModeInfo->VideoSignalInfo.ActiveSize.cx;
1202 size.cy = pVidPnModeInfo->VideoSignalInfo.ActiveSize.cy;
1203 CrSaRemove(&DiffModes, CR_RSIZE2U64(size));
1204 LOGF(("mode (%d x %d) is already in monitor modeset\n", size.cx, size.cy));
1205 }
1206
1207 VBoxVidPnMonitorModeIterTerm(&Iter);
1208
1209 Status = VBoxVidPnMonitorModeIterStatus(&Iter);
1210 if (!NT_SUCCESS(Status))
1211 {
1212 WARN(("iter status failed %#x", Status));
1213 goto done;
1214 }
1215
1216 LOGF(("Adding %d additional modes to monitor modeset\n", CrSaGetSize(&DiffModes)));
1217
1218 Status = vboxVidPnMonitorModeSetFromArray(hVidPnModeSet, pVidPnModeSetInterface, &DiffModes);
1219 if (!NT_SUCCESS(Status))
1220 {
1221 WARN(("vboxVidPnMonitorModeSetFromArray failed %#x", Status));
1222 goto done;
1223 }
1224
1225done:
1226 NTSTATUS rcNt2 = pMonitorInterface->pfnReleaseMonitorSourceModeSet(pDevExt->u.primary.DxgkInterface.DeviceHandle, hVidPnModeSet);
1227 if (!NT_SUCCESS(rcNt2))
1228 WARN(("pfnReleaseMonitorSourceModeSet failed rcNt2(0x%x)", rcNt2));
1229
1230 CrSaCleanup(&DiffModes);
1231
1232 return Status;
1233}
1234
1235static NTSTATUS vboxVidPnPathAdd(D3DKMDT_HVIDPN hVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface,
1236 const D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, const D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId,
1237 D3DKMDT_VIDPN_PRESENT_PATH_IMPORTANCE enmImportance)
1238{
1239 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
1240 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
1241 NTSTATUS Status = pVidPnInterface->pfnGetTopology(hVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
1242 if (!NT_SUCCESS(Status))
1243 {
1244 AssertFailed();
1245 return Status;
1246 }
1247
1248 D3DKMDT_VIDPN_PRESENT_PATH *pNewVidPnPresentPathInfo;
1249 Status = pVidPnTopologyInterface->pfnCreateNewPathInfo(hVidPnTopology, &pNewVidPnPresentPathInfo);
1250 if (!NT_SUCCESS(Status))
1251 {
1252 AssertFailed();
1253 return Status;
1254 }
1255
1256 pNewVidPnPresentPathInfo->VidPnSourceId = VidPnSourceId;
1257 pNewVidPnPresentPathInfo->VidPnTargetId = VidPnTargetId;
1258 pNewVidPnPresentPathInfo->ImportanceOrdinal = enmImportance;
1259 pNewVidPnPresentPathInfo->ContentTransformation.Scaling = D3DKMDT_VPPS_IDENTITY;
1260 memset(&pNewVidPnPresentPathInfo->ContentTransformation.ScalingSupport,
1261 0, sizeof (pNewVidPnPresentPathInfo->ContentTransformation.ScalingSupport));
1262 pNewVidPnPresentPathInfo->ContentTransformation.ScalingSupport.Identity = 1;
1263 pNewVidPnPresentPathInfo->ContentTransformation.ScalingSupport.Centered = 0;
1264 pNewVidPnPresentPathInfo->ContentTransformation.ScalingSupport.Stretched = 0;
1265 pNewVidPnPresentPathInfo->ContentTransformation.Rotation = D3DKMDT_VPPR_IDENTITY;
1266 pNewVidPnPresentPathInfo->ContentTransformation.RotationSupport.Identity = 1;
1267 pNewVidPnPresentPathInfo->ContentTransformation.RotationSupport.Rotate180 = 0;
1268 pNewVidPnPresentPathInfo->ContentTransformation.RotationSupport.Rotate270 = 0;
1269 pNewVidPnPresentPathInfo->ContentTransformation.RotationSupport.Rotate90 = 0;
1270 pNewVidPnPresentPathInfo->VisibleFromActiveTLOffset.cx = 0;
1271 pNewVidPnPresentPathInfo->VisibleFromActiveTLOffset.cy = 0;
1272 pNewVidPnPresentPathInfo->VisibleFromActiveBROffset.cx = 0;
1273 pNewVidPnPresentPathInfo->VisibleFromActiveBROffset.cy = 0;
1274 pNewVidPnPresentPathInfo->VidPnTargetColorBasis = D3DKMDT_CB_SRGB; /** @todo how does it matters? */
1275 pNewVidPnPresentPathInfo->VidPnTargetColorCoeffDynamicRanges.FirstChannel = 8;
1276 pNewVidPnPresentPathInfo->VidPnTargetColorCoeffDynamicRanges.SecondChannel = 8;
1277 pNewVidPnPresentPathInfo->VidPnTargetColorCoeffDynamicRanges.ThirdChannel = 8;
1278 pNewVidPnPresentPathInfo->VidPnTargetColorCoeffDynamicRanges.FourthChannel = 0;
1279 pNewVidPnPresentPathInfo->Content = D3DKMDT_VPPC_GRAPHICS;
1280 pNewVidPnPresentPathInfo->CopyProtection.CopyProtectionType = D3DKMDT_VPPMT_UNINITIALIZED;
1281// pNewVidPnPresentPathInfo->CopyProtection.CopyProtectionType = D3DKMDT_VPPMT_NOPROTECTION;
1282 pNewVidPnPresentPathInfo->CopyProtection.APSTriggerBits = 0;
1283 memset(&pNewVidPnPresentPathInfo->CopyProtection.CopyProtectionSupport, 0, sizeof (pNewVidPnPresentPathInfo->CopyProtection.CopyProtectionSupport));
1284// pNewVidPnPresentPathInfo->CopyProtection.CopyProtectionSupport.NoProtection = 1;
1285 memset (&pNewVidPnPresentPathInfo->GammaRamp, 0, sizeof (pNewVidPnPresentPathInfo->GammaRamp));
1286// pNewVidPnPresentPathInfo->GammaRamp.Type = D3DDDI_GAMMARAMP_DEFAULT;
1287// pNewVidPnPresentPathInfo->GammaRamp.DataSize = 0;
1288 Status = pVidPnTopologyInterface->pfnAddPath(hVidPnTopology, pNewVidPnPresentPathInfo);
1289 if (!NT_SUCCESS(Status))
1290 {
1291 AssertFailed();
1292 NTSTATUS rcNt2 = pVidPnTopologyInterface->pfnReleasePathInfo(hVidPnTopology, pNewVidPnPresentPathInfo);
1293 AssertNtStatus(rcNt2);
1294 }
1295
1296 LOG(("Recommended Path (%d->%d)", VidPnSourceId, VidPnTargetId));
1297
1298 return Status;
1299}
1300
1301NTSTATUS VBoxVidPnRecommendMonitorModes(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_TARGET_ID VideoPresentTargetId,
1302 D3DKMDT_HMONITORSOURCEMODESET hVidPnModeSet, const DXGK_MONITORSOURCEMODESET_INTERFACE *pVidPnModeSetInterface)
1303{
1304 const CR_SORTARRAY *pSupportedModes = VBoxWddmVModesGet(pDevExt, VideoPresentTargetId);
1305
1306 NTSTATUS Status = vboxVidPnMonitorModeSetFromArray(hVidPnModeSet, pVidPnModeSetInterface, pSupportedModes);
1307 if (!NT_SUCCESS(Status))
1308 {
1309 WARN(("vboxVidPnMonitorModeSetFromArray failed %d", Status));
1310 return Status;
1311 }
1312
1313 return STATUS_SUCCESS;
1314}
1315
1316NTSTATUS VBoxVidPnUpdateModes(PVBOXMP_DEVEXT pDevExt, uint32_t u32TargetId, const RTRECTSIZE *pSize)
1317{
1318 LOGF(("ENTER u32TargetId(%d) mode(%d x %d)", u32TargetId, pSize->cx, pSize->cy));
1319
1320 if (u32TargetId >= (uint32_t)VBoxCommonFromDeviceExt(pDevExt)->cDisplays)
1321 {
1322 WARN(("invalid target id"));
1323 return STATUS_INVALID_PARAMETER;
1324 }
1325
1326 int rc = VBoxWddmVModesAdd(pDevExt, u32TargetId, pSize, TRUE);
1327 LOGF(("VBoxWddmVModesAdd returned (%d)", rc));
1328
1329 if (RT_FAILURE(rc))
1330 {
1331 WARN(("VBoxWddmVModesAdd failed %d", rc));
1332 return STATUS_UNSUCCESSFUL;
1333 }
1334
1335 if (rc == VINF_ALREADY_INITIALIZED)
1336 {
1337 /* mode was already in list, just return */
1338 Assert(CrSaContains(VBoxWddmVModesGet(pDevExt, u32TargetId), CR_RSIZE2U64(*pSize)));
1339 LOGF(("LEAVE mode was already in modeset, just return"));
1340 return STATUS_SUCCESS;
1341 }
1342
1343#ifdef VBOX_WDDM_REPLUG_ON_MODE_CHANGE
1344 /* The VBOXESC_UPDATEMODES is a hint for the driver to use new display mode as soon as VidPn
1345 * manager will ask for it.
1346 * Probably, some new interface is required to plug/unplug displays by calling
1347 * VBoxWddmChildStatusReportReconnected.
1348 * But it is a bad idea to mix sending a display mode hint and (un)plug displays in VBOXESC_UPDATEMODES.
1349 */
1350
1351 /* modes have changed, need to replug */
1352 NTSTATUS Status = VBoxWddmChildStatusReportReconnected(pDevExt, u32TargetId);
1353 LOG(("VBoxWddmChildStatusReportReconnected returned (%d)", Status));
1354 if (!NT_SUCCESS(Status))
1355 {
1356 WARN(("VBoxWddmChildStatusReportReconnected failed Status(%#x)", Status));
1357 return Status;
1358 }
1359#endif
1360
1361 LOGF(("LEAVE u32TargetId(%d)", u32TargetId));
1362 return STATUS_SUCCESS;
1363}
1364
1365NTSTATUS VBoxVidPnRecommendFunctional(PVBOXMP_DEVEXT pDevExt, D3DKMDT_HVIDPN hVidPn, const VBOXWDDM_RECOMMENDVIDPN *pData)
1366{
1367 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
1368 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(hVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
1369 if (!NT_SUCCESS(Status))
1370 {
1371 WARN(("DxgkCbQueryVidPnInterface failed Status(%#x)", Status));
1372 return Status;
1373 }
1374
1375 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aVisitedSourceMap);
1376
1377 memset(aVisitedSourceMap, 0, sizeof (aVisitedSourceMap));
1378
1379 uint32_t Importance = (uint32_t)D3DKMDT_VPPI_PRIMARY;
1380
1381 for (uint32_t i = 0; i < (uint32_t)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
1382 {
1383 int32_t iSource = pData->aTargets[i].iSource;
1384 if (iSource < 0)
1385 continue;
1386
1387 if (iSource >= VBoxCommonFromDeviceExt(pDevExt)->cDisplays)
1388 {
1389 WARN(("invalid iSource"));
1390 return STATUS_INVALID_PARAMETER;
1391 }
1392
1393 if (!pDevExt->fComplexTopologiesEnabled && iSource != (int32_t)i)
1394 {
1395 WARN(("complex topologies not supported!"));
1396 return STATUS_INVALID_PARAMETER;
1397 }
1398
1399 bool fNewSource = false;
1400
1401 if (!ASMBitTest(aVisitedSourceMap, iSource))
1402 {
1403 int rc = VBoxWddmVModesAdd(pDevExt, i, &pData->aSources[iSource].Size, TRUE);
1404 if (RT_FAILURE(rc))
1405 {
1406 WARN(("VBoxWddmVModesAdd failed %d", rc));
1407 return STATUS_UNSUCCESSFUL;
1408 }
1409
1410 Assert(CrSaContains(VBoxWddmVModesGet(pDevExt, i), CR_RSIZE2U64(pData->aSources[iSource].Size)));
1411
1412 Status = vboxVidPnCheckMonitorModes(pDevExt, i);
1413 if (!NT_SUCCESS(Status))
1414 {
1415 WARN(("vboxVidPnCheckMonitorModes failed %#x", Status));
1416 return Status;
1417 }
1418
1419 ASMBitSet(aVisitedSourceMap, iSource);
1420 fNewSource = true;
1421 }
1422
1423 Status = vboxVidPnPathAdd(hVidPn, pVidPnInterface,
1424 (const D3DDDI_VIDEO_PRESENT_SOURCE_ID)iSource, (const D3DDDI_VIDEO_PRESENT_TARGET_ID)i,
1425 (D3DKMDT_VIDPN_PRESENT_PATH_IMPORTANCE)Importance);
1426 if (!NT_SUCCESS(Status))
1427 {
1428 WARN(("vboxVidPnPathAdd failed Status()0x%x\n", Status));
1429 return Status;
1430 }
1431
1432 Importance++;
1433
1434 do {
1435 D3DKMDT_HVIDPNTARGETMODESET hVidPnModeSet;
1436 const DXGK_VIDPNTARGETMODESET_INTERFACE *pVidPnModeSetInterface;
1437
1438 Status = pVidPnInterface->pfnCreateNewTargetModeSet(hVidPn,
1439 i,
1440 &hVidPnModeSet,
1441 &pVidPnModeSetInterface);
1442 if (NT_SUCCESS(Status))
1443 {
1444 D3DKMDT_VIDPN_TARGET_MODE *pVidPnModeInfo;
1445 Status = pVidPnModeSetInterface->pfnCreateNewModeInfo(hVidPnModeSet, &pVidPnModeInfo);
1446 if (NT_SUCCESS(Status))
1447 {
1448 vboxVidPnPopulateTargetModeInfo(pVidPnModeInfo, &pData->aSources[iSource].Size);
1449
1450 IN_CONST_D3DKMDT_VIDEO_PRESENT_TARGET_MODE_ID idMode = pVidPnModeInfo->Id;
1451
1452 Status = pVidPnModeSetInterface->pfnAddMode(hVidPnModeSet, pVidPnModeInfo);
1453 if (NT_SUCCESS(Status))
1454 {
1455 pVidPnModeInfo = NULL;
1456
1457 Status = pVidPnModeSetInterface->pfnPinMode(hVidPnModeSet, idMode);
1458 if (NT_SUCCESS(Status))
1459 {
1460 Status = pVidPnInterface->pfnAssignTargetModeSet(hVidPn, i, hVidPnModeSet);
1461 if (NT_SUCCESS(Status))
1462 {
1463 LOG(("Recommended Target[%d] (%dx%d)", i, pData->aSources[iSource].Size.cx, pData->aSources[iSource].Size.cy));
1464 break;
1465 }
1466 else
1467 WARN(("pfnAssignTargetModeSet failed %#x", Status));
1468 }
1469 else
1470 WARN(("pfnPinMode failed %#x", Status));
1471
1472 }
1473 else
1474 WARN(("pfnAddMode failed %#x", Status));
1475
1476 if (pVidPnModeInfo)
1477 {
1478 NTSTATUS rcNt2 = pVidPnModeSetInterface->pfnReleaseModeInfo(hVidPnModeSet, pVidPnModeInfo);
1479 AssertNtStatusSuccess(rcNt2);
1480 }
1481 }
1482 else
1483 WARN(("pfnCreateNewTargetModeSet failed %#x", Status));
1484
1485 NTSTATUS rcNt2 = pVidPnInterface->pfnReleaseTargetModeSet(hVidPn, hVidPnModeSet);
1486 AssertNtStatusSuccess(rcNt2);
1487 }
1488 else
1489 WARN(("pfnCreateNewTargetModeSet failed %#x", Status));
1490
1491 Assert(!NT_SUCCESS(Status));
1492
1493 return Status;
1494 } while (0);
1495
1496 if (fNewSource)
1497 {
1498 do {
1499 D3DKMDT_HVIDPNSOURCEMODESET hVidPnModeSet;
1500 const DXGK_VIDPNSOURCEMODESET_INTERFACE *pVidPnModeSetInterface;
1501
1502 Status = pVidPnInterface->pfnCreateNewSourceModeSet(hVidPn,
1503 iSource,
1504 &hVidPnModeSet,
1505 &pVidPnModeSetInterface);
1506 if (NT_SUCCESS(Status))
1507 {
1508 D3DKMDT_VIDPN_SOURCE_MODE *pVidPnModeInfo;
1509 Status = pVidPnModeSetInterface->pfnCreateNewModeInfo(hVidPnModeSet, &pVidPnModeInfo);
1510 if (NT_SUCCESS(Status))
1511 {
1512 vboxVidPnPopulateSourceModeInfo(pVidPnModeInfo, &pData->aSources[iSource].Size);
1513
1514 IN_CONST_D3DKMDT_VIDEO_PRESENT_SOURCE_MODE_ID idMode = pVidPnModeInfo->Id;
1515
1516 Status = pVidPnModeSetInterface->pfnAddMode(hVidPnModeSet, pVidPnModeInfo);
1517 if (NT_SUCCESS(Status))
1518 {
1519 pVidPnModeInfo = NULL;
1520
1521 Status = pVidPnModeSetInterface->pfnPinMode(hVidPnModeSet, idMode);
1522 if (NT_SUCCESS(Status))
1523 {
1524 Status = pVidPnInterface->pfnAssignSourceModeSet(hVidPn, iSource, hVidPnModeSet);
1525 if (NT_SUCCESS(Status))
1526 {
1527 LOG(("Recommended Source[%d] (%dx%d)", iSource, pData->aSources[iSource].Size.cx, pData->aSources[iSource].Size.cy));
1528 break;
1529 }
1530 else
1531 WARN(("pfnAssignSourceModeSet failed %#x", Status));
1532 }
1533 else
1534 WARN(("pfnPinMode failed %#x", Status));
1535
1536 }
1537 else
1538 WARN(("pfnAddMode failed %#x", Status));
1539
1540 if (pVidPnModeInfo)
1541 {
1542 NTSTATUS rcNt2 = pVidPnModeSetInterface->pfnReleaseModeInfo(hVidPnModeSet, pVidPnModeInfo);
1543 AssertNtStatusSuccess(rcNt2);
1544 }
1545 }
1546 else
1547 WARN(("pfnCreateNewSourceModeSet failed %#x", Status));
1548
1549 NTSTATUS rcNt2 = pVidPnInterface->pfnReleaseSourceModeSet(hVidPn, hVidPnModeSet);
1550 AssertNtStatusSuccess(rcNt2);
1551 }
1552 else
1553 WARN(("pfnCreateNewSourceModeSet failed %#x", Status));
1554
1555 Assert(!NT_SUCCESS(Status));
1556
1557 return Status;
1558 } while (0);
1559 }
1560 }
1561
1562 Assert(NT_SUCCESS(Status));
1563 return STATUS_SUCCESS;
1564}
1565
1566static BOOLEAN vboxVidPnIsPathSupported(PVBOXMP_DEVEXT pDevExt, const D3DKMDT_VIDPN_PRESENT_PATH *pNewVidPnPresentPathInfo)
1567{
1568 if (!pDevExt->fComplexTopologiesEnabled && pNewVidPnPresentPathInfo->VidPnSourceId != pNewVidPnPresentPathInfo->VidPnTargetId)
1569 {
1570 LOG(("unsupported source(%d)->target(%d) pair", pNewVidPnPresentPathInfo->VidPnSourceId, pNewVidPnPresentPathInfo->VidPnTargetId));
1571 return FALSE;
1572 }
1573
1574 /*
1575 ImportanceOrdinal does not matter for now
1576 pNewVidPnPresentPathInfo->ImportanceOrdinal
1577 */
1578
1579 if (pNewVidPnPresentPathInfo->ContentTransformation.Scaling != D3DKMDT_VPPS_UNPINNED
1580 && pNewVidPnPresentPathInfo->ContentTransformation.Scaling != D3DKMDT_VPPS_IDENTITY
1581 && pNewVidPnPresentPathInfo->ContentTransformation.Scaling != D3DKMDT_VPPS_NOTSPECIFIED)
1582 {
1583 WARN(("unsupported Scaling (%d)", pNewVidPnPresentPathInfo->ContentTransformation.Scaling));
1584 return FALSE;
1585 }
1586
1587 if ( !pNewVidPnPresentPathInfo->ContentTransformation.ScalingSupport.Identity
1588 || pNewVidPnPresentPathInfo->ContentTransformation.ScalingSupport.Centered
1589 || pNewVidPnPresentPathInfo->ContentTransformation.ScalingSupport.Stretched)
1590 {
1591 WARN(("unsupported Scaling support"));
1592 return FALSE;
1593 }
1594
1595 if (pNewVidPnPresentPathInfo->ContentTransformation.Rotation != D3DKMDT_VPPR_UNPINNED
1596 && pNewVidPnPresentPathInfo->ContentTransformation.Rotation != D3DKMDT_VPPR_IDENTITY
1597 && pNewVidPnPresentPathInfo->ContentTransformation.Rotation != D3DKMDT_VPPR_NOTSPECIFIED)
1598 {
1599 WARN(("unsupported rotation (%d)", pNewVidPnPresentPathInfo->ContentTransformation.Rotation));
1600 return FALSE;
1601 }
1602
1603 if ( !pNewVidPnPresentPathInfo->ContentTransformation.RotationSupport.Identity
1604 || pNewVidPnPresentPathInfo->ContentTransformation.RotationSupport.Rotate90
1605 || pNewVidPnPresentPathInfo->ContentTransformation.RotationSupport.Rotate180
1606 || pNewVidPnPresentPathInfo->ContentTransformation.RotationSupport.Rotate270)
1607 {
1608 WARN(("unsupported RotationSupport"));
1609 return FALSE;
1610 }
1611
1612 if (pNewVidPnPresentPathInfo->VisibleFromActiveTLOffset.cx
1613 || pNewVidPnPresentPathInfo->VisibleFromActiveTLOffset.cy)
1614 {
1615 WARN(("Non-zero TLOffset: cx(%d), cy(%d)",
1616 pNewVidPnPresentPathInfo->VisibleFromActiveTLOffset.cx,
1617 pNewVidPnPresentPathInfo->VisibleFromActiveTLOffset.cy));
1618 return FALSE;
1619 }
1620
1621 if (pNewVidPnPresentPathInfo->VisibleFromActiveBROffset.cx
1622 || pNewVidPnPresentPathInfo->VisibleFromActiveBROffset.cy)
1623 {
1624 WARN(("Non-zero TLOffset: cx(%d), cy(%d)",
1625 pNewVidPnPresentPathInfo->VisibleFromActiveBROffset.cx,
1626 pNewVidPnPresentPathInfo->VisibleFromActiveBROffset.cy));
1627 return FALSE;
1628 }
1629
1630 if (pNewVidPnPresentPathInfo->VidPnTargetColorBasis != D3DKMDT_CB_SRGB
1631 && pNewVidPnPresentPathInfo->VidPnTargetColorBasis != D3DKMDT_CB_UNINITIALIZED)
1632 {
1633 WARN(("unsupported VidPnTargetColorBasis (%d)", pNewVidPnPresentPathInfo->VidPnTargetColorBasis));
1634 return FALSE;
1635 }
1636
1637 /* channels?
1638 pNewVidPnPresentPathInfo->VidPnTargetColorCoeffDynamicRanges.FirstChannel;
1639 pNewVidPnPresentPathInfo->VidPnTargetColorCoeffDynamicRanges.SecondChannel;
1640 pNewVidPnPresentPathInfo->VidPnTargetColorCoeffDynamicRanges.ThirdChannel;
1641 we definitely not support fourth channel
1642 */
1643 if (pNewVidPnPresentPathInfo->VidPnTargetColorCoeffDynamicRanges.FourthChannel)
1644 {
1645 WARN(("Non-zero FourthChannel (%d)", pNewVidPnPresentPathInfo->VidPnTargetColorCoeffDynamicRanges.FourthChannel));
1646 return FALSE;
1647 }
1648
1649 /* Content (D3DKMDT_VPPC_GRAPHICS, _NOTSPECIFIED, _VIDEO), does not matter for now
1650 pNewVidPnPresentPathInfo->Content
1651 */
1652 /* not support copy protection for now */
1653 if (pNewVidPnPresentPathInfo->CopyProtection.CopyProtectionType != D3DKMDT_VPPMT_NOPROTECTION
1654 && pNewVidPnPresentPathInfo->CopyProtection.CopyProtectionType != D3DKMDT_VPPMT_UNINITIALIZED)
1655 {
1656 WARN(("Copy protection not supported CopyProtectionType(%d)", pNewVidPnPresentPathInfo->CopyProtection.CopyProtectionType));
1657 return FALSE;
1658 }
1659
1660 if (pNewVidPnPresentPathInfo->CopyProtection.APSTriggerBits)
1661 {
1662 WARN(("Copy protection not supported APSTriggerBits(%d)", pNewVidPnPresentPathInfo->CopyProtection.APSTriggerBits));
1663 return FALSE;
1664 }
1665
1666 D3DKMDT_VIDPN_PRESENT_PATH_COPYPROTECTION_SUPPORT tstCPSupport = {0};
1667 tstCPSupport.NoProtection = 1;
1668 if (memcmp(&tstCPSupport, &pNewVidPnPresentPathInfo->CopyProtection.CopyProtectionSupport, sizeof(tstCPSupport)))
1669 {
1670 WARN(("Copy protection support (0x%x)", *((UINT*)&pNewVidPnPresentPathInfo->CopyProtection.CopyProtectionSupport)));
1671 return FALSE;
1672 }
1673
1674 if (pNewVidPnPresentPathInfo->GammaRamp.Type != D3DDDI_GAMMARAMP_DEFAULT
1675 && pNewVidPnPresentPathInfo->GammaRamp.Type != D3DDDI_GAMMARAMP_UNINITIALIZED)
1676 {
1677 WARN(("Unsupported GammaRamp.Type (%d)", pNewVidPnPresentPathInfo->GammaRamp.Type));
1678 return FALSE;
1679 }
1680
1681 if (pNewVidPnPresentPathInfo->GammaRamp.DataSize != 0)
1682 {
1683 WARN(("Warning: non-zero GammaRamp.DataSize (%d), treating as supported", pNewVidPnPresentPathInfo->GammaRamp.DataSize));
1684 }
1685
1686 return TRUE;
1687}
1688
1689NTSTATUS VBoxVidPnIsSupported(PVBOXMP_DEVEXT pDevExt, D3DKMDT_HVIDPN hVidPn, BOOLEAN *pfSupported)
1690{
1691 /* According Microsoft Docs we must return pfSupported = TRUE here if hVidPn is NULL, as
1692 * the display adapter can always be configured to display nothing. */
1693 if (hVidPn == NULL)
1694 {
1695 *pfSupported = TRUE;
1696 return STATUS_SUCCESS;
1697 }
1698
1699 *pfSupported = FALSE;
1700
1701 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
1702 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(hVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
1703 if (!NT_SUCCESS(Status))
1704 {
1705 WARN(("DxgkCbQueryVidPnInterface failed Status()0x%x\n", Status));
1706 return Status;
1707 }
1708
1709#ifdef VBOXWDDM_DEBUG_VIDPN
1710 vboxVidPnDumpVidPn(">>>>IsSupported VidPN (IN) : >>>>\n", pDevExt, hVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<\n");
1711#endif
1712
1713 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
1714 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
1715 Status = pVidPnInterface->pfnGetTopology(hVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
1716 if (!NT_SUCCESS(Status))
1717 {
1718 WARN(("pfnGetTopology failed Status()0x%x\n", Status));
1719 return Status;
1720 }
1721
1722 VBOXVIDPN_PATH_ITER PathIter;
1723 const D3DKMDT_VIDPN_PRESENT_PATH * pPath;
1724 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aVisitedTargetMap);
1725
1726 memset(aVisitedTargetMap, 0, sizeof (aVisitedTargetMap));
1727
1728 BOOLEAN fSupported = TRUE;
1729 /* collect info first */
1730 VBoxVidPnPathIterInit(&PathIter, hVidPnTopology, pVidPnTopologyInterface);
1731 while ((pPath = VBoxVidPnPathIterNext(&PathIter)) != NULL)
1732 {
1733 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId = pPath->VidPnSourceId;
1734 D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId = pPath->VidPnTargetId;
1735 /* actually vidpn topology should contain only one target info, right? */
1736 Assert(!ASMBitTest(aVisitedTargetMap, VidPnTargetId));
1737 ASMBitSet(aVisitedTargetMap, VidPnTargetId);
1738
1739 if (!vboxVidPnIsPathSupported(pDevExt, pPath))
1740 {
1741 fSupported = FALSE;
1742 break;
1743 }
1744
1745 RTRECTSIZE TargetSize;
1746 RTRECTSIZE SourceSize;
1747 Status = vboxVidPnQueryPinnedTargetMode(hVidPn, pVidPnInterface, VidPnTargetId, &TargetSize);
1748 if (!NT_SUCCESS(Status))
1749 {
1750 WARN(("vboxVidPnQueryPinnedTargetMode failed %#x", Status));
1751 break;
1752 }
1753
1754 Status = vboxVidPnQueryPinnedSourceMode(hVidPn, pVidPnInterface, VidPnSourceId, &SourceSize);
1755 if (!NT_SUCCESS(Status))
1756 {
1757 WARN(("vboxVidPnQueryPinnedSourceMode failed %#x", Status));
1758 break;
1759 }
1760
1761 if (memcmp(&TargetSize, &SourceSize, sizeof (TargetSize)) && TargetSize.cx)
1762 {
1763 if (!SourceSize.cx)
1764 WARN(("not expected?"));
1765
1766 fSupported = FALSE;
1767 break;
1768 }
1769 }
1770
1771 VBoxVidPnPathIterTerm(&PathIter);
1772
1773 if (!NT_SUCCESS(Status))
1774 goto done;
1775
1776 Status = VBoxVidPnPathIterStatus(&PathIter);
1777 if (!NT_SUCCESS(Status))
1778 {
1779 WARN(("PathIter failed Status()0x%x\n", Status));
1780 goto done;
1781 }
1782
1783 *pfSupported = fSupported;
1784done:
1785
1786 return Status;
1787}
1788
1789NTSTATUS VBoxVidPnCofuncModality(PVBOXMP_DEVEXT pDevExt, D3DKMDT_HVIDPN hVidPn, D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE enmPivot, const DXGK_ENUM_PIVOT *pPivot)
1790{
1791 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
1792 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(hVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
1793 if (!NT_SUCCESS(Status))
1794 {
1795 WARN(("DxgkCbQueryVidPnInterface failed Status()0x%x\n", Status));
1796 return Status;
1797 }
1798
1799#ifdef VBOXWDDM_DEBUG_VIDPN
1800 vboxVidPnDumpCofuncModalityArg(">>>>MODALITY Args: ", enmPivot, pPivot, "\n");
1801 vboxVidPnDumpVidPn(">>>>MODALITY VidPN (IN) : >>>>\n", pDevExt, hVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<\n");
1802#endif
1803
1804 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
1805 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
1806 Status = pVidPnInterface->pfnGetTopology(hVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
1807 if (!NT_SUCCESS(Status))
1808 {
1809 WARN(("pfnGetTopology failed Status()0x%x\n", Status));
1810 return Status;
1811 }
1812
1813 VBOXVIDPN_PATH_ITER PathIter;
1814 const D3DKMDT_VIDPN_PRESENT_PATH * pPath;
1815 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aVisitedTargetMap);
1816 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aAdjustedModeMap);
1817 CR_SORTARRAY aModes[VBOX_VIDEO_MAX_SCREENS];
1818
1819 memset(aVisitedTargetMap, 0, sizeof (aVisitedTargetMap));
1820 memset(aAdjustedModeMap, 0, sizeof (aAdjustedModeMap));
1821 memset(aModes, 0, sizeof (aModes));
1822
1823 /* collect info first */
1824 VBoxVidPnPathIterInit(&PathIter, hVidPnTopology, pVidPnTopologyInterface);
1825 while ((pPath = VBoxVidPnPathIterNext(&PathIter)) != NULL)
1826 {
1827 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId = pPath->VidPnSourceId;
1828 D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId = pPath->VidPnTargetId;
1829 /* actually vidpn topology should contain only one target info, right? */
1830 Assert(!ASMBitTest(aVisitedTargetMap, VidPnTargetId));
1831 ASMBitSet(aVisitedTargetMap, VidPnTargetId);
1832
1833 D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE enmCurPivot = vboxVidPnCofuncModalityCurrentPathPivot(enmPivot, pPivot, VidPnSourceId, VidPnTargetId);
1834
1835 Status = vboxVidPnCollectInfoForPathTarget(pDevExt,
1836 hVidPn,
1837 pVidPnInterface,
1838 enmCurPivot,
1839 aAdjustedModeMap,
1840 aModes,
1841 VidPnSourceId, VidPnTargetId);
1842 if (!NT_SUCCESS(Status))
1843 {
1844 WARN(("vboxVidPnCollectInfoForPathTarget failed Status(0x%x\n", Status));
1845 VBoxVidPnDumpCofuncModalityInfo("Modality Info: ", enmPivot, pPivot, "\n");
1846 break;
1847 }
1848
1849 Assert(CrSaCovers(VBoxWddmVModesGet(pDevExt, VidPnTargetId), &aModes[VidPnTargetId]));
1850
1851 Status = vboxVidPnCollectInfoForPathSource(pDevExt,
1852 hVidPn,
1853 pVidPnInterface,
1854 enmCurPivot,
1855 aAdjustedModeMap,
1856 aModes,
1857 VidPnSourceId, VidPnTargetId);
1858 if (!NT_SUCCESS(Status))
1859 {
1860 WARN(("vboxVidPnCollectInfoForPathSource failed Status(0x%x\n", Status));
1861 VBoxVidPnDumpCofuncModalityInfo("Modality Info: ", enmPivot, pPivot, "\n");
1862 break;
1863 }
1864
1865 Assert(CrSaCovers(VBoxWddmVModesGet(pDevExt, VidPnTargetId), &aModes[VidPnTargetId]));
1866 }
1867
1868 VBoxVidPnPathIterTerm(&PathIter);
1869
1870 if (!NT_SUCCESS(Status))
1871 goto done;
1872
1873 Status = VBoxVidPnPathIterStatus(&PathIter);
1874 if (!NT_SUCCESS(Status))
1875 {
1876 WARN(("PathIter failed Status()0x%x\n", Status));
1877 VBoxVidPnDumpCofuncModalityInfo("Modality Info: ", enmPivot, pPivot, "\n");
1878 goto done;
1879 }
1880
1881 /* now we have collected all the necessary info,
1882 * go ahead and apply it */
1883 memset(aVisitedTargetMap, 0, sizeof (aVisitedTargetMap));
1884 VBoxVidPnPathIterInit(&PathIter, hVidPnTopology, pVidPnTopologyInterface);
1885 while ((pPath = VBoxVidPnPathIterNext(&PathIter)) != NULL)
1886 {
1887 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId = pPath->VidPnSourceId;
1888 D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId = pPath->VidPnTargetId;
1889 /* actually vidpn topology should contain only one target info, right? */
1890 Assert(!ASMBitTest(aVisitedTargetMap, VidPnTargetId));
1891 ASMBitSet(aVisitedTargetMap, VidPnTargetId);
1892
1893 D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE enmCurPivot = vboxVidPnCofuncModalityCurrentPathPivot(enmPivot, pPivot, VidPnSourceId, VidPnTargetId);
1894
1895 bool bUpdatePath = false;
1896 D3DKMDT_VIDPN_PRESENT_PATH AdjustedPath = {0};
1897 AdjustedPath.VidPnSourceId = pPath->VidPnSourceId;
1898 AdjustedPath.VidPnTargetId = pPath->VidPnTargetId;
1899 AdjustedPath.ContentTransformation = pPath->ContentTransformation;
1900 AdjustedPath.CopyProtection = pPath->CopyProtection;
1901
1902 if (pPath->ContentTransformation.Scaling == D3DKMDT_VPPS_UNPINNED)
1903 {
1904 AdjustedPath.ContentTransformation.ScalingSupport.Identity = TRUE;
1905 bUpdatePath = true;
1906 }
1907
1908 if (pPath->ContentTransformation.Rotation == D3DKMDT_VPPR_UNPINNED)
1909 {
1910 AdjustedPath.ContentTransformation.RotationSupport.Identity = TRUE;
1911 bUpdatePath = true;
1912 }
1913
1914 if (bUpdatePath)
1915 {
1916 Status = pVidPnTopologyInterface->pfnUpdatePathSupportInfo(hVidPnTopology, &AdjustedPath);
1917 if (!NT_SUCCESS(Status))
1918 {
1919 WARN(("pfnUpdatePathSupportInfo failed Status()0x%x\n", Status));
1920 VBoxVidPnDumpCofuncModalityInfo("Modality Info: ", enmPivot, pPivot, "\n");
1921 goto done;
1922 }
1923 }
1924
1925 Assert(CrSaCovers(VBoxWddmVModesGet(pDevExt, VidPnTargetId), &aModes[VidPnTargetId]));
1926
1927 Status = vboxVidPnApplyInfoForPathTarget(pDevExt,
1928 hVidPn,
1929 pVidPnInterface,
1930 enmCurPivot,
1931 aAdjustedModeMap,
1932 aModes,
1933 VidPnSourceId, VidPnTargetId);
1934 if (!NT_SUCCESS(Status))
1935 {
1936 WARN(("vboxVidPnApplyInfoForPathTarget failed Status(0x%x\n", Status));
1937 VBoxVidPnDumpCofuncModalityInfo("Modality Info: ", enmPivot, pPivot, "\n");
1938 break;
1939 }
1940
1941 Status = vboxVidPnApplyInfoForPathSource(pDevExt,
1942 hVidPn,
1943 pVidPnInterface,
1944 enmCurPivot,
1945 aAdjustedModeMap,
1946 aModes,
1947 VidPnSourceId, VidPnTargetId);
1948 if (!NT_SUCCESS(Status))
1949 {
1950 WARN(("vboxVidPnApplyInfoForPathSource failed Status(0x%x\n", Status));
1951 VBoxVidPnDumpCofuncModalityInfo("Modality Info: ", enmPivot, pPivot, "\n");
1952 break;
1953 }
1954 }
1955
1956 VBoxVidPnPathIterTerm(&PathIter);
1957
1958 if (!NT_SUCCESS(Status))
1959 goto done;
1960
1961 Status = VBoxVidPnPathIterStatus(&PathIter);
1962 if (!NT_SUCCESS(Status))
1963 {
1964 WARN(("PathIter failed Status()0x%x\n", Status));
1965 VBoxVidPnDumpCofuncModalityInfo("Modality Info: ", enmPivot, pPivot, "\n");
1966 goto done;
1967 }
1968
1969done:
1970
1971 for (uint32_t i = 0; i < (uint32_t)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
1972 {
1973 CrSaCleanup(&aModes[i]);
1974 }
1975
1976 return Status;
1977}
1978
1979NTSTATUS vboxVidPnEnumMonitorSourceModes(D3DKMDT_HMONITORSOURCEMODESET hMonitorSMS, CONST DXGK_MONITORSOURCEMODESET_INTERFACE *pMonitorSMSIf,
1980 PFNVBOXVIDPNENUMMONITORSOURCEMODES pfnCallback, PVOID pContext)
1981{
1982 CONST D3DKMDT_MONITOR_SOURCE_MODE *pMonitorSMI;
1983 NTSTATUS Status = pMonitorSMSIf->pfnAcquireFirstModeInfo(hMonitorSMS, &pMonitorSMI);
1984 Assert(Status == STATUS_SUCCESS || Status == STATUS_GRAPHICS_DATASET_IS_EMPTY);
1985 if (Status == STATUS_SUCCESS)
1986 {
1987 Assert(pMonitorSMI);
1988 while (1)
1989 {
1990 CONST D3DKMDT_MONITOR_SOURCE_MODE *pNextMonitorSMI;
1991 Status = pMonitorSMSIf->pfnAcquireNextModeInfo(hMonitorSMS, pMonitorSMI, &pNextMonitorSMI);
1992 if (!pfnCallback(hMonitorSMS, pMonitorSMSIf, pMonitorSMI, pContext))
1993 {
1994 Assert(Status == STATUS_SUCCESS || Status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET);
1995 if (Status == STATUS_SUCCESS)
1996 pMonitorSMSIf->pfnReleaseModeInfo(hMonitorSMS, pNextMonitorSMI);
1997 else if (Status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET)
1998 {
1999 Status = STATUS_SUCCESS;
2000 break;
2001 }
2002 else
2003 {
2004 LOGREL(("pfnAcquireNextModeInfo Failed Status(0x%x), ignored since callback returned false", Status));
2005 Status = STATUS_SUCCESS;
2006 }
2007 break;
2008 }
2009 else if (Status == STATUS_SUCCESS)
2010 pMonitorSMI = pNextMonitorSMI;
2011 else if (Status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET)
2012 {
2013 Status = STATUS_SUCCESS;
2014 break;
2015 }
2016 else
2017 {
2018 AssertBreakpoint();
2019 LOGREL(("pfnAcquireNextModeInfo Failed Status(0x%x)", Status));
2020 pNextMonitorSMI = NULL;
2021 break;
2022 }
2023 }
2024 }
2025 else if (Status == STATUS_GRAPHICS_DATASET_IS_EMPTY)
2026 Status = STATUS_SUCCESS;
2027 else
2028 LOGREL(("pfnAcquireFirstModeInfo failed Status(0x%x)", Status));
2029
2030 return Status;
2031}
2032
2033NTSTATUS vboxVidPnEnumSourceModes(D3DKMDT_HVIDPNSOURCEMODESET hNewVidPnSourceModeSet, const DXGK_VIDPNSOURCEMODESET_INTERFACE *pVidPnSourceModeSetInterface,
2034 PFNVBOXVIDPNENUMSOURCEMODES pfnCallback, PVOID pContext)
2035{
2036 const D3DKMDT_VIDPN_SOURCE_MODE *pNewVidPnSourceModeInfo;
2037 NTSTATUS Status = pVidPnSourceModeSetInterface->pfnAcquireFirstModeInfo(hNewVidPnSourceModeSet, &pNewVidPnSourceModeInfo);
2038 if (Status == STATUS_SUCCESS)
2039 {
2040 Assert(pNewVidPnSourceModeInfo);
2041 while (1)
2042 {
2043 const D3DKMDT_VIDPN_SOURCE_MODE *pNextVidPnSourceModeInfo;
2044 Status = pVidPnSourceModeSetInterface->pfnAcquireNextModeInfo(hNewVidPnSourceModeSet, pNewVidPnSourceModeInfo, &pNextVidPnSourceModeInfo);
2045 if (!pfnCallback(hNewVidPnSourceModeSet, pVidPnSourceModeSetInterface,
2046 pNewVidPnSourceModeInfo, pContext))
2047 {
2048 AssertNtStatusSuccess(Status);
2049 if (Status == STATUS_SUCCESS)
2050 pVidPnSourceModeSetInterface->pfnReleaseModeInfo(hNewVidPnSourceModeSet, pNextVidPnSourceModeInfo);
2051 else if (Status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET)
2052 {
2053 Status = STATUS_SUCCESS;
2054 break;
2055 }
2056 else
2057 {
2058 LOGREL(("pfnAcquireNextModeInfo Failed Status(0x%x), ignored since callback returned false", Status));
2059 Status = STATUS_SUCCESS;
2060 }
2061
2062 break;
2063 }
2064 else if (Status == STATUS_SUCCESS)
2065 pNewVidPnSourceModeInfo = pNextVidPnSourceModeInfo;
2066 else if (Status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET)
2067 {
2068 Status = STATUS_SUCCESS;
2069 break;
2070 }
2071 else
2072 {
2073 AssertBreakpoint();
2074 LOGREL(("pfnAcquireNextModeInfo Failed Status(0x%x)", Status));
2075 pNewVidPnSourceModeInfo = NULL;
2076 break;
2077 }
2078 }
2079 }
2080 else if (Status == STATUS_GRAPHICS_DATASET_IS_EMPTY)
2081 Status = STATUS_SUCCESS;
2082 else
2083 LOGREL(("pfnAcquireFirstModeInfo failed Status(0x%x)", Status));
2084
2085 return Status;
2086}
2087
2088NTSTATUS vboxVidPnEnumTargetModes(D3DKMDT_HVIDPNTARGETMODESET hNewVidPnTargetModeSet, const DXGK_VIDPNTARGETMODESET_INTERFACE *pVidPnTargetModeSetInterface,
2089 PFNVBOXVIDPNENUMTARGETMODES pfnCallback, PVOID pContext)
2090{
2091 const D3DKMDT_VIDPN_TARGET_MODE *pNewVidPnTargetModeInfo;
2092 NTSTATUS Status = pVidPnTargetModeSetInterface->pfnAcquireFirstModeInfo(hNewVidPnTargetModeSet, &pNewVidPnTargetModeInfo);
2093 if (Status == STATUS_SUCCESS)
2094 {
2095 Assert(pNewVidPnTargetModeInfo);
2096 while (1)
2097 {
2098 const D3DKMDT_VIDPN_TARGET_MODE *pNextVidPnTargetModeInfo;
2099 Status = pVidPnTargetModeSetInterface->pfnAcquireNextModeInfo(hNewVidPnTargetModeSet, pNewVidPnTargetModeInfo, &pNextVidPnTargetModeInfo);
2100 if (!pfnCallback(hNewVidPnTargetModeSet, pVidPnTargetModeSetInterface,
2101 pNewVidPnTargetModeInfo, pContext))
2102 {
2103 AssertNtStatusSuccess(Status);
2104 if (Status == STATUS_SUCCESS)
2105 pVidPnTargetModeSetInterface->pfnReleaseModeInfo(hNewVidPnTargetModeSet, pNextVidPnTargetModeInfo);
2106 else if (Status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET)
2107 {
2108 Status = STATUS_SUCCESS;
2109 break;
2110 }
2111 else
2112 {
2113 LOGREL(("pfnAcquireNextModeInfo Failed Status(0x%x), ignored since callback returned false", Status));
2114 Status = STATUS_SUCCESS;
2115 }
2116
2117 break;
2118 }
2119 else if (Status == STATUS_SUCCESS)
2120 pNewVidPnTargetModeInfo = pNextVidPnTargetModeInfo;
2121 else if (Status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET)
2122 {
2123 Status = STATUS_SUCCESS;
2124 break;
2125 }
2126 else
2127 {
2128 AssertBreakpoint();
2129 LOGREL(("pfnAcquireNextModeInfo Failed Status(0x%x)", Status));
2130 pNewVidPnTargetModeInfo = NULL;
2131 break;
2132 }
2133 }
2134 }
2135 else if (Status == STATUS_GRAPHICS_DATASET_IS_EMPTY)
2136 Status = STATUS_SUCCESS;
2137 else
2138 LOGREL(("pfnAcquireFirstModeInfo failed Status(0x%x)", Status));
2139
2140 return Status;
2141}
2142
2143NTSTATUS vboxVidPnEnumTargetsForSource(PVBOXMP_DEVEXT pDevExt, D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface,
2144 CONST D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId,
2145 PFNVBOXVIDPNENUMTARGETSFORSOURCE pfnCallback, PVOID pContext)
2146{
2147 SIZE_T cTgtPaths;
2148 NTSTATUS Status = pVidPnTopologyInterface->pfnGetNumPathsFromSource(hVidPnTopology, VidPnSourceId, &cTgtPaths);
2149 Assert(Status == STATUS_SUCCESS || Status == STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY);
2150 if (Status == STATUS_SUCCESS)
2151 {
2152 for (SIZE_T i = 0; i < cTgtPaths; ++i)
2153 {
2154 D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId;
2155 Status = pVidPnTopologyInterface->pfnEnumPathTargetsFromSource(hVidPnTopology, VidPnSourceId, i, &VidPnTargetId);
2156 AssertNtStatusSuccess(Status);
2157 if (Status == STATUS_SUCCESS)
2158 {
2159 if (!pfnCallback(pDevExt, hVidPnTopology, pVidPnTopologyInterface, VidPnSourceId, VidPnTargetId, cTgtPaths, pContext))
2160 break;
2161 }
2162 else
2163 {
2164 LOGREL(("pfnEnumPathTargetsFromSource failed Status(0x%x)", Status));
2165 break;
2166 }
2167 }
2168 }
2169 else if (Status != STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY)
2170 LOGREL(("pfnGetNumPathsFromSource failed Status(0x%x)", Status));
2171
2172 return Status;
2173}
2174
2175NTSTATUS vboxVidPnEnumPaths(D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface,
2176 PFNVBOXVIDPNENUMPATHS pfnCallback, PVOID pContext)
2177{
2178 const D3DKMDT_VIDPN_PRESENT_PATH *pNewVidPnPresentPathInfo = NULL;
2179 NTSTATUS Status = pVidPnTopologyInterface->pfnAcquireFirstPathInfo(hVidPnTopology, &pNewVidPnPresentPathInfo);
2180 if (Status == STATUS_SUCCESS)
2181 {
2182 while (1)
2183 {
2184 const D3DKMDT_VIDPN_PRESENT_PATH *pNextVidPnPresentPathInfo;
2185 Status = pVidPnTopologyInterface->pfnAcquireNextPathInfo(hVidPnTopology, pNewVidPnPresentPathInfo, &pNextVidPnPresentPathInfo);
2186
2187 if (!pfnCallback(hVidPnTopology, pVidPnTopologyInterface, pNewVidPnPresentPathInfo, pContext))
2188 {
2189 if (Status == STATUS_SUCCESS)
2190 pVidPnTopologyInterface->pfnReleasePathInfo(hVidPnTopology, pNextVidPnPresentPathInfo);
2191 else
2192 {
2193 if (Status != STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET)
2194 WARN(("pfnAcquireNextPathInfo Failed Status(0x%x), ignored since callback returned false", Status));
2195 Status = STATUS_SUCCESS;
2196 }
2197
2198 break;
2199 }
2200 else if (Status == STATUS_SUCCESS)
2201 pNewVidPnPresentPathInfo = pNextVidPnPresentPathInfo;
2202 else if (Status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET)
2203 {
2204 Status = STATUS_SUCCESS;
2205 break;
2206 }
2207 else
2208 {
2209 WARN(("pfnAcquireNextPathInfo Failed Status(0x%x)", Status));
2210 pNewVidPnPresentPathInfo = NULL;
2211 break;
2212 }
2213 }
2214 }
2215 else if (Status == STATUS_GRAPHICS_DATASET_IS_EMPTY)
2216 Status = STATUS_SUCCESS;
2217 else
2218 WARN(("pfnAcquireFirstModeInfo failed Status(0x%x)", Status));
2219
2220 return Status;
2221}
2222
2223NTSTATUS vboxVidPnSetupSourceInfo(PVBOXMP_DEVEXT pDevExt, CONST D3DKMDT_VIDPN_SOURCE_MODE* pVidPnSourceModeInfo,
2224 PVBOXWDDM_ALLOCATION pAllocation, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId,
2225 VBOXWDDM_SOURCE *paSources)
2226{
2227 RT_NOREF(pDevExt);
2228 PVBOXWDDM_SOURCE pSource = &paSources[VidPnSourceId];
2229 /* pVidPnSourceModeInfo could be null if STATUS_GRAPHICS_MODE_NOT_PINNED,
2230 * see VBoxVidPnCommitSourceModeForSrcId */
2231 uint8_t fChanges = 0;
2232 if (pVidPnSourceModeInfo)
2233 {
2234 if (pSource->AllocData.SurfDesc.width != pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cx)
2235 {
2236 fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
2237 pSource->AllocData.SurfDesc.width = pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cx;
2238 }
2239 if (pSource->AllocData.SurfDesc.height != pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy)
2240 {
2241 fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
2242 pSource->AllocData.SurfDesc.height = pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy;
2243 }
2244 if (pSource->AllocData.SurfDesc.format != pVidPnSourceModeInfo->Format.Graphics.PixelFormat)
2245 {
2246 fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
2247 pSource->AllocData.SurfDesc.format = pVidPnSourceModeInfo->Format.Graphics.PixelFormat;
2248 }
2249 if (pSource->AllocData.SurfDesc.bpp != vboxWddmCalcBitsPerPixel(pVidPnSourceModeInfo->Format.Graphics.PixelFormat))
2250 {
2251 fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
2252 pSource->AllocData.SurfDesc.bpp = vboxWddmCalcBitsPerPixel(pVidPnSourceModeInfo->Format.Graphics.PixelFormat);
2253 }
2254 if(pSource->AllocData.SurfDesc.pitch != pVidPnSourceModeInfo->Format.Graphics.Stride)
2255 {
2256 fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
2257 pSource->AllocData.SurfDesc.pitch = pVidPnSourceModeInfo->Format.Graphics.Stride;
2258 }
2259 pSource->AllocData.SurfDesc.depth = 1;
2260 if (pSource->AllocData.SurfDesc.slicePitch != pVidPnSourceModeInfo->Format.Graphics.Stride)
2261 {
2262 fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
2263 pSource->AllocData.SurfDesc.slicePitch = pVidPnSourceModeInfo->Format.Graphics.Stride;
2264 }
2265 if (pSource->AllocData.SurfDesc.cbSize != pVidPnSourceModeInfo->Format.Graphics.Stride * pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy)
2266 {
2267 fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
2268 pSource->AllocData.SurfDesc.cbSize = pVidPnSourceModeInfo->Format.Graphics.Stride * pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy;
2269 }
2270
2271 if (g_VBoxDisplayOnly)
2272 {
2273 vboxWddmDmSetupDefaultVramLocation(pDevExt, VidPnSourceId, paSources);
2274 }
2275 }
2276 else
2277 {
2278 VBoxVidPnAllocDataInit(&pSource->AllocData, VidPnSourceId);
2279 Assert(!pAllocation);
2280 fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_ALL;
2281 }
2282
2283 Assert(!g_VBoxDisplayOnly || !pAllocation);
2284 if (!g_VBoxDisplayOnly)
2285 {
2286 vboxWddmAssignPrimary(pSource, pAllocation, VidPnSourceId);
2287 }
2288
2289 Assert(pSource->AllocData.SurfDesc.VidPnSourceId == VidPnSourceId);
2290 pSource->u8SyncState &= ~fChanges;
2291 return STATUS_SUCCESS;
2292}
2293
2294NTSTATUS vboxVidPnCommitSourceMode(PVBOXMP_DEVEXT pDevExt, CONST D3DKMDT_VIDPN_SOURCE_MODE* pVidPnSourceModeInfo, PVBOXWDDM_ALLOCATION pAllocation,
2295 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, VBOXWDDM_SOURCE *paSources)
2296{
2297 if (VidPnSourceId < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays)
2298 return vboxVidPnSetupSourceInfo(pDevExt, pVidPnSourceModeInfo, pAllocation, VidPnSourceId, paSources);
2299
2300 WARN(("invalid srcId (%d), cSources(%d)", VidPnSourceId, VBoxCommonFromDeviceExt(pDevExt)->cDisplays));
2301 return STATUS_INVALID_PARAMETER;
2302}
2303
2304typedef struct VBOXVIDPNCOMMITTARGETMODE
2305{
2306 NTSTATUS Status;
2307 D3DKMDT_HVIDPN hVidPn;
2308 const DXGK_VIDPN_INTERFACE* pVidPnInterface;
2309 VBOXWDDM_SOURCE *paSources;
2310 VBOXWDDM_TARGET *paTargets;
2311} VBOXVIDPNCOMMITTARGETMODE;
2312
2313DECLCALLBACK(BOOLEAN) vboxVidPnCommitTargetModeEnum(PVBOXMP_DEVEXT pDevExt, D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology,
2314 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface,
2315 CONST D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId,
2316 D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId, SIZE_T cTgtPaths,
2317 PVOID pContext)
2318{
2319 RT_NOREF(hVidPnTopology, pVidPnTopologyInterface, cTgtPaths);
2320 VBOXVIDPNCOMMITTARGETMODE *pInfo = (VBOXVIDPNCOMMITTARGETMODE*)pContext;
2321 Assert(cTgtPaths <= (SIZE_T)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
2322 D3DKMDT_HVIDPNTARGETMODESET hVidPnTargetModeSet;
2323 CONST DXGK_VIDPNTARGETMODESET_INTERFACE* pVidPnTargetModeSetInterface;
2324 NTSTATUS Status = pInfo->pVidPnInterface->pfnAcquireTargetModeSet(pInfo->hVidPn, VidPnTargetId, &hVidPnTargetModeSet, &pVidPnTargetModeSetInterface);
2325 AssertNtStatusSuccess(Status);
2326 if (Status == STATUS_SUCCESS)
2327 {
2328 CONST D3DKMDT_VIDPN_TARGET_MODE* pPinnedVidPnTargetModeInfo;
2329 Status = pVidPnTargetModeSetInterface->pfnAcquirePinnedModeInfo(hVidPnTargetModeSet, &pPinnedVidPnTargetModeInfo);
2330 AssertNtStatusSuccess(Status);
2331 if (Status == STATUS_SUCCESS)
2332 {
2333 VBOXWDDM_SOURCE *pSource = &pInfo->paSources[VidPnSourceId];
2334 VBOXWDDM_TARGET *pTarget = &pInfo->paTargets[VidPnTargetId];
2335 pTarget->Size.cx = pPinnedVidPnTargetModeInfo->VideoSignalInfo.ActiveSize.cx;
2336 pTarget->Size.cy = pPinnedVidPnTargetModeInfo->VideoSignalInfo.TotalSize.cy;
2337
2338 VBoxVidPnStSourceTargetAdd(pInfo->paSources, VBoxCommonFromDeviceExt(pDevExt)->cDisplays, pSource, pTarget);
2339
2340 pTarget->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
2341
2342 pVidPnTargetModeSetInterface->pfnReleaseModeInfo(hVidPnTargetModeSet, pPinnedVidPnTargetModeInfo);
2343 }
2344 else
2345 WARN(("pfnAcquirePinnedModeInfo failed Status(0x%x)", Status));
2346
2347 pInfo->pVidPnInterface->pfnReleaseTargetModeSet(pInfo->hVidPn, hVidPnTargetModeSet);
2348 }
2349 else
2350 WARN(("pfnAcquireTargetModeSet failed Status(0x%x)", Status));
2351
2352 pInfo->Status = Status;
2353 return Status == STATUS_SUCCESS;
2354}
2355
2356NTSTATUS VBoxVidPnCommitSourceModeForSrcId(PVBOXMP_DEVEXT pDevExt, const D3DKMDT_HVIDPN hDesiredVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface,
2357 PVBOXWDDM_ALLOCATION pAllocation,
2358 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, VBOXWDDM_SOURCE *paSources, VBOXWDDM_TARGET *paTargets, BOOLEAN bPathPowerTransition)
2359{
2360 D3DKMDT_HVIDPNSOURCEMODESET hCurVidPnSourceModeSet;
2361 const DXGK_VIDPNSOURCEMODESET_INTERFACE *pCurVidPnSourceModeSetInterface;
2362
2363 PVBOXWDDM_SOURCE pSource = &paSources[VidPnSourceId];
2364 NTSTATUS Status;
2365
2366 if (bPathPowerTransition)
2367 {
2368 RTRECTSIZE PinnedModeSize;
2369 bool bHasPinnedMode;
2370
2371 Status = vboxVidPnQueryPinnedSourceMode(hDesiredVidPn, pVidPnInterface, VidPnSourceId, &PinnedModeSize);
2372 bHasPinnedMode = Status == STATUS_SUCCESS && PinnedModeSize.cx > 0 && PinnedModeSize.cy > 0;
2373 pSource->bBlankedByPowerOff = !bHasPinnedMode;
2374
2375 LOG(("Path power transition: srcId %d goes blank %d", VidPnSourceId, pSource->bBlankedByPowerOff));
2376 }
2377
2378 VBOXWDDM_TARGET_ITER Iter;
2379 VBoxVidPnStTIterInit(pSource, paTargets, (uint32_t)VBoxCommonFromDeviceExt(pDevExt)->cDisplays, &Iter);
2380 for (PVBOXWDDM_TARGET pTarget = VBoxVidPnStTIterNext(&Iter);
2381 pTarget;
2382 pTarget = VBoxVidPnStTIterNext(&Iter))
2383 {
2384 Assert(pTarget->VidPnSourceId == pSource->AllocData.SurfDesc.VidPnSourceId);
2385 pTarget->Size.cx = 0;
2386 pTarget->Size.cy = 0;
2387 pTarget->fBlankedByPowerOff = RT_BOOL(pSource->bBlankedByPowerOff);
2388 pTarget->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_ALL;
2389 }
2390
2391 VBoxVidPnStSourceCleanup(paSources, VidPnSourceId, paTargets, (uint32_t)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
2392
2393 Status = pVidPnInterface->pfnAcquireSourceModeSet(hDesiredVidPn,
2394 VidPnSourceId,
2395 &hCurVidPnSourceModeSet,
2396 &pCurVidPnSourceModeSetInterface);
2397 AssertNtStatusSuccess(Status);
2398 if (Status == STATUS_SUCCESS)
2399 {
2400 CONST D3DKMDT_VIDPN_SOURCE_MODE* pPinnedVidPnSourceModeInfo;
2401 Status = pCurVidPnSourceModeSetInterface->pfnAcquirePinnedModeInfo(hCurVidPnSourceModeSet, &pPinnedVidPnSourceModeInfo);
2402 Assert(Status == STATUS_SUCCESS || Status == STATUS_GRAPHICS_MODE_NOT_PINNED);
2403 if (Status == STATUS_SUCCESS)
2404 {
2405 Assert(pPinnedVidPnSourceModeInfo);
2406 Status = vboxVidPnCommitSourceMode(pDevExt, pPinnedVidPnSourceModeInfo, pAllocation, VidPnSourceId, paSources);
2407 AssertNtStatusSuccess(Status);
2408 if (Status == STATUS_SUCCESS)
2409 {
2410 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
2411 CONST DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
2412 Status = pVidPnInterface->pfnGetTopology(hDesiredVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
2413 AssertNtStatusSuccess(Status);
2414 if (Status == STATUS_SUCCESS)
2415 {
2416 VBOXVIDPNCOMMITTARGETMODE TgtModeInfo = {0};
2417 TgtModeInfo.Status = STATUS_SUCCESS; /* <- to ensure we're succeeded if no targets are set */
2418 TgtModeInfo.hVidPn = hDesiredVidPn;
2419 TgtModeInfo.pVidPnInterface = pVidPnInterface;
2420 TgtModeInfo.paSources = paSources;
2421 TgtModeInfo.paTargets = paTargets;
2422 Status = vboxVidPnEnumTargetsForSource(pDevExt, hVidPnTopology, pVidPnTopologyInterface,
2423 VidPnSourceId,
2424 vboxVidPnCommitTargetModeEnum, &TgtModeInfo);
2425 Assert(Status == STATUS_SUCCESS || Status == STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY);
2426 if (Status == STATUS_SUCCESS)
2427 {
2428 Status = TgtModeInfo.Status;
2429 AssertNtStatusSuccess(Status);
2430 }
2431 else if (Status == STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY)
2432 {
2433 Status = STATUS_SUCCESS;
2434 }
2435 else
2436 WARN(("vboxVidPnEnumTargetsForSource failed Status(0x%x)", Status));
2437 }
2438 else
2439 WARN(("pfnGetTopology failed Status(0x%x)", Status));
2440 }
2441 else
2442 WARN(("vboxVidPnCommitSourceMode failed Status(0x%x)", Status));
2443 /* release */
2444 pCurVidPnSourceModeSetInterface->pfnReleaseModeInfo(hCurVidPnSourceModeSet, pPinnedVidPnSourceModeInfo);
2445 }
2446 else if (Status == STATUS_GRAPHICS_MODE_NOT_PINNED)
2447 {
2448 Status = vboxVidPnCommitSourceMode(pDevExt, NULL, pAllocation, VidPnSourceId, paSources);
2449 AssertNtStatusSuccess(Status);
2450 }
2451 else
2452 WARN(("pfnAcquirePinnedModeInfo failed Status(0x%x)", Status));
2453
2454 pVidPnInterface->pfnReleaseSourceModeSet(hDesiredVidPn, hCurVidPnSourceModeSet);
2455 }
2456 else
2457 {
2458 WARN(("pfnAcquireSourceModeSet failed Status(0x%x)", Status));
2459 }
2460
2461 return Status;
2462}
2463
2464NTSTATUS VBoxVidPnCommitAll(PVBOXMP_DEVEXT pDevExt, const D3DKMDT_HVIDPN hDesiredVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface,
2465 PVBOXWDDM_ALLOCATION pAllocation,
2466 VBOXWDDM_SOURCE *paSources, VBOXWDDM_TARGET *paTargets)
2467{
2468 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
2469 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
2470 NTSTATUS Status = pVidPnInterface->pfnGetTopology(hDesiredVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
2471 if (!NT_SUCCESS(Status))
2472 {
2473 WARN(("pfnGetTopology failed Status 0x%x", Status));
2474 return Status;
2475 }
2476
2477 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
2478 {
2479 PVBOXWDDM_TARGET pTarget = &paTargets[i];
2480 pTarget->Size.cx = 0;
2481 pTarget->Size.cy = 0;
2482 pTarget->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_ALL;
2483
2484 if (pTarget->VidPnSourceId == D3DDDI_ID_UNINITIALIZED)
2485 continue;
2486
2487 Assert(pTarget->VidPnSourceId < (D3DDDI_VIDEO_PRESENT_SOURCE_ID)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
2488
2489 VBOXWDDM_SOURCE *pSource = &paSources[pTarget->VidPnSourceId];
2490 VBoxVidPnAllocDataInit(&pSource->AllocData, pTarget->VidPnSourceId);
2491 pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_ALL;
2492 }
2493
2494 VBoxVidPnStCleanup(paSources, paTargets, VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
2495
2496 VBOXVIDPN_PATH_ITER PathIter;
2497 const D3DKMDT_VIDPN_PRESENT_PATH *pPath;
2498 VBoxVidPnPathIterInit(&PathIter, hVidPnTopology, pVidPnTopologyInterface);
2499 while ((pPath = VBoxVidPnPathIterNext(&PathIter)) != NULL)
2500 {
2501 Status = VBoxVidPnCommitSourceModeForSrcId(pDevExt, hDesiredVidPn, pVidPnInterface, pAllocation,
2502 pPath->VidPnSourceId, paSources, paTargets, FALSE);
2503 if (Status != STATUS_SUCCESS)
2504 {
2505 WARN(("VBoxVidPnCommitSourceModeForSrcId failed Status(0x%x)", Status));
2506 break;
2507 }
2508 }
2509
2510 VBoxVidPnPathIterTerm(&PathIter);
2511
2512 if (!NT_SUCCESS(Status))
2513 {
2514 WARN((""));
2515 return Status;
2516 }
2517
2518 Status = VBoxVidPnPathIterStatus(&PathIter);
2519 if (!NT_SUCCESS(Status))
2520 {
2521 WARN(("VBoxVidPnPathIterStatus failed Status 0x%x", Status));
2522 return Status;
2523 }
2524
2525 return STATUS_SUCCESS;
2526}
2527
2528#define VBOXVIDPNDUMP_STRCASE(_t) \
2529 case _t: return #_t;
2530#define VBOXVIDPNDUMP_STRCASE_UNKNOWN() \
2531 default: Assert(0); return "Unknown";
2532
2533#define VBOXVIDPNDUMP_STRFLAGS(_v, _t) \
2534 if ((_v)._t return #_t;
2535
2536const char* vboxVidPnDumpStrImportance(D3DKMDT_VIDPN_PRESENT_PATH_IMPORTANCE ImportanceOrdinal)
2537{
2538 switch (ImportanceOrdinal)
2539 {
2540 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPI_UNINITIALIZED);
2541 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPI_PRIMARY);
2542 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPI_SECONDARY);
2543 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPI_TERTIARY);
2544 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPI_QUATERNARY);
2545 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPI_QUINARY);
2546 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPI_SENARY);
2547 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPI_SEPTENARY);
2548 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPI_OCTONARY);
2549 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPI_NONARY);
2550 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPI_DENARY);
2551 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2552 }
2553}
2554
2555const char* vboxVidPnDumpStrScaling(D3DKMDT_VIDPN_PRESENT_PATH_SCALING Scaling)
2556{
2557 switch (Scaling)
2558 {
2559 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPS_UNINITIALIZED);
2560 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPS_IDENTITY);
2561 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPS_CENTERED);
2562 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPS_STRETCHED);
2563 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPS_UNPINNED);
2564 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPS_NOTSPECIFIED);
2565 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2566 }
2567}
2568
2569const char* vboxVidPnDumpStrRotation(D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation)
2570{
2571 switch (Rotation)
2572 {
2573 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPR_UNINITIALIZED);
2574 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPR_IDENTITY);
2575 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPR_ROTATE90);
2576 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPR_ROTATE180);
2577 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPR_ROTATE270);
2578 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPR_UNPINNED);
2579 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPR_NOTSPECIFIED);
2580 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2581 }
2582}
2583
2584const char* vboxVidPnDumpStrColorBasis(const D3DKMDT_COLOR_BASIS ColorBasis)
2585{
2586 switch (ColorBasis)
2587 {
2588 VBOXVIDPNDUMP_STRCASE(D3DKMDT_CB_UNINITIALIZED);
2589 VBOXVIDPNDUMP_STRCASE(D3DKMDT_CB_INTENSITY);
2590 VBOXVIDPNDUMP_STRCASE(D3DKMDT_CB_SRGB);
2591 VBOXVIDPNDUMP_STRCASE(D3DKMDT_CB_SCRGB);
2592 VBOXVIDPNDUMP_STRCASE(D3DKMDT_CB_YCBCR);
2593 VBOXVIDPNDUMP_STRCASE(D3DKMDT_CB_YPBPR);
2594 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2595 }
2596}
2597
2598const char * vboxVidPnDumpStrMonCapabilitiesOrigin(D3DKMDT_MONITOR_CAPABILITIES_ORIGIN enmOrigin)
2599{
2600 switch (enmOrigin)
2601 {
2602 VBOXVIDPNDUMP_STRCASE(D3DKMDT_MCO_UNINITIALIZED);
2603 VBOXVIDPNDUMP_STRCASE(D3DKMDT_MCO_DEFAULTMONITORPROFILE);
2604 VBOXVIDPNDUMP_STRCASE(D3DKMDT_MCO_MONITORDESCRIPTOR);
2605 VBOXVIDPNDUMP_STRCASE(D3DKMDT_MCO_MONITORDESCRIPTOR_REGISTRYOVERRIDE);
2606 VBOXVIDPNDUMP_STRCASE(D3DKMDT_MCO_SPECIFICCAP_REGISTRYOVERRIDE);
2607 VBOXVIDPNDUMP_STRCASE(D3DKMDT_MCO_DRIVER);
2608 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2609 }
2610}
2611
2612const char* vboxVidPnDumpStrPvam(D3DKMDT_PIXEL_VALUE_ACCESS_MODE PixelValueAccessMode)
2613{
2614 switch (PixelValueAccessMode)
2615 {
2616 VBOXVIDPNDUMP_STRCASE(D3DKMDT_PVAM_UNINITIALIZED);
2617 VBOXVIDPNDUMP_STRCASE(D3DKMDT_PVAM_DIRECT);
2618 VBOXVIDPNDUMP_STRCASE(D3DKMDT_PVAM_PRESETPALETTE);
2619 VBOXVIDPNDUMP_STRCASE(D3DKMDT_PVAM_SETTABLEPALETTE);
2620 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2621 }
2622}
2623
2624
2625
2626const char* vboxVidPnDumpStrContent(D3DKMDT_VIDPN_PRESENT_PATH_CONTENT Content)
2627{
2628 switch (Content)
2629 {
2630 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPC_UNINITIALIZED);
2631 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPC_GRAPHICS);
2632 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPC_VIDEO);
2633 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPC_NOTSPECIFIED);
2634 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2635 }
2636}
2637
2638const char* vboxVidPnDumpStrCopyProtectionType(D3DKMDT_VIDPN_PRESENT_PATH_COPYPROTECTION_TYPE CopyProtectionType)
2639{
2640 switch (CopyProtectionType)
2641 {
2642 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPMT_UNINITIALIZED);
2643 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPMT_NOPROTECTION);
2644 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPMT_MACROVISION_APSTRIGGER);
2645 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPMT_MACROVISION_FULLSUPPORT);
2646 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2647 }
2648}
2649
2650const char* vboxVidPnDumpStrGammaRampType(D3DDDI_GAMMARAMP_TYPE Type)
2651{
2652 switch (Type)
2653 {
2654 VBOXVIDPNDUMP_STRCASE(D3DDDI_GAMMARAMP_UNINITIALIZED);
2655 VBOXVIDPNDUMP_STRCASE(D3DDDI_GAMMARAMP_DEFAULT);
2656 VBOXVIDPNDUMP_STRCASE(D3DDDI_GAMMARAMP_RGB256x3x16);
2657 VBOXVIDPNDUMP_STRCASE(D3DDDI_GAMMARAMP_DXGI_1);
2658 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2659 }
2660}
2661
2662const char* vboxVidPnDumpStrSourceModeType(D3DKMDT_VIDPN_SOURCE_MODE_TYPE Type)
2663{
2664 switch (Type)
2665 {
2666 VBOXVIDPNDUMP_STRCASE(D3DKMDT_RMT_UNINITIALIZED);
2667 VBOXVIDPNDUMP_STRCASE(D3DKMDT_RMT_GRAPHICS);
2668 VBOXVIDPNDUMP_STRCASE(D3DKMDT_RMT_TEXT);
2669 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2670 }
2671}
2672
2673const char* vboxVidPnDumpStrScanLineOrdering(D3DDDI_VIDEO_SIGNAL_SCANLINE_ORDERING ScanLineOrdering)
2674{
2675 switch (ScanLineOrdering)
2676 {
2677 VBOXVIDPNDUMP_STRCASE(D3DDDI_VSSLO_UNINITIALIZED);
2678 VBOXVIDPNDUMP_STRCASE(D3DDDI_VSSLO_PROGRESSIVE);
2679 VBOXVIDPNDUMP_STRCASE(D3DDDI_VSSLO_INTERLACED_UPPERFIELDFIRST);
2680 VBOXVIDPNDUMP_STRCASE(D3DDDI_VSSLO_INTERLACED_LOWERFIELDFIRST);
2681 VBOXVIDPNDUMP_STRCASE(D3DDDI_VSSLO_OTHER);
2682 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2683 }
2684}
2685
2686const char* vboxVidPnDumpStrCFMPivotType(D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE EnumPivotType)
2687{
2688 switch (EnumPivotType)
2689 {
2690 VBOXVIDPNDUMP_STRCASE(D3DKMDT_EPT_UNINITIALIZED);
2691 VBOXVIDPNDUMP_STRCASE(D3DKMDT_EPT_VIDPNSOURCE);
2692 VBOXVIDPNDUMP_STRCASE(D3DKMDT_EPT_VIDPNTARGET);
2693 VBOXVIDPNDUMP_STRCASE(D3DKMDT_EPT_SCALING);
2694 VBOXVIDPNDUMP_STRCASE(D3DKMDT_EPT_ROTATION);
2695 VBOXVIDPNDUMP_STRCASE(D3DKMDT_EPT_NOPIVOT);
2696 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2697 }
2698}
2699
2700const char* vboxVidPnDumpStrModePreference(D3DKMDT_MODE_PREFERENCE Preference)
2701{
2702 switch (Preference)
2703 {
2704 VBOXVIDPNDUMP_STRCASE(D3DKMDT_MP_UNINITIALIZED);
2705 VBOXVIDPNDUMP_STRCASE(D3DKMDT_MP_PREFERRED);
2706 VBOXVIDPNDUMP_STRCASE(D3DKMDT_MP_NOTPREFERRED);
2707 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2708 }
2709}
2710
2711const char* vboxVidPnDumpStrSignalStandard(D3DKMDT_VIDEO_SIGNAL_STANDARD VideoStandard)
2712{
2713 switch (VideoStandard)
2714 {
2715 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_UNINITIALIZED);
2716 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_VESA_DMT);
2717 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_VESA_GTF);
2718 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_VESA_CVT);
2719 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_IBM);
2720 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_APPLE);
2721 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_NTSC_M);
2722 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_NTSC_J);
2723 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_NTSC_443);
2724 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_PAL_B);
2725 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_PAL_B1);
2726 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_PAL_G);
2727 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_PAL_H);
2728 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_PAL_I);
2729 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_PAL_D);
2730 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_PAL_N);
2731 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_PAL_NC);
2732 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_SECAM_B);
2733 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_SECAM_D);
2734 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_SECAM_G);
2735 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_SECAM_H);
2736 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_SECAM_K);
2737 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_SECAM_K1);
2738 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_SECAM_L);
2739 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_SECAM_L1);
2740 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_EIA_861);
2741 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_EIA_861A);
2742 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_EIA_861B);
2743 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_PAL_K);
2744 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_PAL_K1);
2745 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_PAL_L);
2746 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_PAL_M);
2747 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_OTHER);
2748 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2749 }
2750}
2751
2752const char* vboxVidPnDumpStrPixFormat(D3DDDIFORMAT PixelFormat)
2753{
2754 switch (PixelFormat)
2755 {
2756 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_UNKNOWN);
2757 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_R8G8B8);
2758 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A8R8G8B8);
2759 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_X8R8G8B8);
2760 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_R5G6B5);
2761 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_X1R5G5B5);
2762 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A1R5G5B5);
2763 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A4R4G4B4);
2764 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_R3G3B2);
2765 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A8);
2766 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A8R3G3B2);
2767 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_X4R4G4B4);
2768 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A2B10G10R10);
2769 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A8B8G8R8);
2770 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_X8B8G8R8);
2771 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_G16R16);
2772 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A2R10G10B10);
2773 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A16B16G16R16);
2774 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A8P8);
2775 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_R32F);
2776 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_G32R32F);
2777 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A32B32G32R32F);
2778 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_CxV8U8);
2779 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A1);
2780 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_BINARYBUFFER);
2781 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_VERTEXDATA);
2782 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_INDEX16);
2783 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_INDEX32);
2784 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_Q16W16V16U16);
2785 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_MULTI2_ARGB8);
2786 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_R16F);
2787 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_G16R16F);
2788 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A16B16G16R16F);
2789 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_D32F_LOCKABLE);
2790 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_D24FS8);
2791 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_D32_LOCKABLE);
2792 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_S8_LOCKABLE);
2793 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_S1D15);
2794 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_S8D24);
2795 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_X8D24);
2796 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_X4S4D24);
2797 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_L16);
2798 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_UYVY);
2799 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_R8G8_B8G8);
2800 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_YUY2);
2801 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_G8R8_G8B8);
2802 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_DXT1);
2803 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_DXT2);
2804 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_DXT3);
2805 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_DXT4);
2806 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_DXT5);
2807 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_D16_LOCKABLE);
2808 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_D32);
2809 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_D15S1);
2810 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_D24S8);
2811 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_D24X8);
2812 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_D24X4S4);
2813 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_D16);
2814 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_P8);
2815 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_L8);
2816 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A8L8);
2817 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A4L4);
2818 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_V8U8);
2819 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_L6V5U5);
2820 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_X8L8V8U8);
2821 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_Q8W8V8U8);
2822 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_V16U16);
2823 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_W11V11U10);
2824 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A2W10V10U10);
2825 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2826 }
2827}
2828
2829void vboxVidPnDumpCopyProtectoin(const char *pPrefix, const D3DKMDT_VIDPN_PRESENT_PATH_COPYPROTECTION *pCopyProtection, const char *pSuffix)
2830{
2831 LOGREL_EXACT(("%sType(%s), TODO%s", pPrefix,
2832 vboxVidPnDumpStrCopyProtectionType(pCopyProtection->CopyProtectionType), pSuffix));
2833}
2834
2835
2836void vboxVidPnDumpPathTransformation(const D3DKMDT_VIDPN_PRESENT_PATH_TRANSFORMATION *pContentTransformation)
2837{
2838 LOGREL_EXACT((" --Transformation: Scaling(%s), ScalingSupport(%d), Rotation(%s), RotationSupport(%d)--",
2839 vboxVidPnDumpStrScaling(pContentTransformation->Scaling), pContentTransformation->ScalingSupport,
2840 vboxVidPnDumpStrRotation(pContentTransformation->Rotation), pContentTransformation->RotationSupport));
2841}
2842
2843void vboxVidPnDumpRegion(const char *pPrefix, const D3DKMDT_2DREGION *pRegion, const char *pSuffix)
2844{
2845 LOGREL_EXACT(("%s%dX%d%s", pPrefix, pRegion->cx, pRegion->cy, pSuffix));
2846}
2847
2848void vboxVidPnDumpRational(const char *pPrefix, const D3DDDI_RATIONAL *pRational, const char *pSuffix)
2849{
2850 LOGREL_EXACT(("%s%d/%d=%d%s", pPrefix, pRational->Numerator, pRational->Denominator, pRational->Numerator/pRational->Denominator, pSuffix));
2851}
2852
2853void vboxVidPnDumpRanges(const char *pPrefix, const D3DKMDT_COLOR_COEFF_DYNAMIC_RANGES *pDynamicRanges, const char *pSuffix)
2854{
2855 LOGREL_EXACT(("%sFirstChannel(%d), SecondChannel(%d), ThirdChannel(%d), FourthChannel(%d)%s", pPrefix,
2856 pDynamicRanges->FirstChannel,
2857 pDynamicRanges->SecondChannel,
2858 pDynamicRanges->ThirdChannel,
2859 pDynamicRanges->FourthChannel,
2860 pSuffix));
2861}
2862
2863void vboxVidPnDumpGammaRamp(const char *pPrefix, const D3DKMDT_GAMMA_RAMP *pGammaRamp, const char *pSuffix)
2864{
2865 LOGREL_EXACT(("%sType(%s), DataSize(%d), TODO: dump the rest%s", pPrefix,
2866 vboxVidPnDumpStrGammaRampType(pGammaRamp->Type), pGammaRamp->DataSize,
2867 pSuffix));
2868}
2869
2870void VBoxVidPnDumpSourceMode(const char *pPrefix, const D3DKMDT_VIDPN_SOURCE_MODE* pVidPnSourceModeInfo, const char *pSuffix)
2871{
2872 LOGREL_EXACT(("%sType(%s), ", pPrefix, vboxVidPnDumpStrSourceModeType(pVidPnSourceModeInfo->Type)));
2873 vboxVidPnDumpRegion("surf(", &pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize, "), ");
2874 vboxVidPnDumpRegion("vis(", &pVidPnSourceModeInfo->Format.Graphics.VisibleRegionSize, "), ");
2875 LOGREL_EXACT(("stride(%d), ", pVidPnSourceModeInfo->Format.Graphics.Stride));
2876 LOGREL_EXACT(("format(%s), ", vboxVidPnDumpStrPixFormat(pVidPnSourceModeInfo->Format.Graphics.PixelFormat)));
2877 LOGREL_EXACT(("clrBasis(%s), ", vboxVidPnDumpStrColorBasis(pVidPnSourceModeInfo->Format.Graphics.ColorBasis)));
2878 LOGREL_EXACT(("pvam(%s)%s", vboxVidPnDumpStrPvam(pVidPnSourceModeInfo->Format.Graphics.PixelValueAccessMode), pSuffix));
2879}
2880
2881void vboxVidPnDumpSignalInfo(const char *pPrefix, const D3DKMDT_VIDEO_SIGNAL_INFO *pVideoSignalInfo, const char *pSuffix)
2882{
2883 LOGREL_EXACT(("%sVStd(%s), ", pPrefix, vboxVidPnDumpStrSignalStandard(pVideoSignalInfo->VideoStandard)));
2884 vboxVidPnDumpRegion("totSize(", &pVideoSignalInfo->TotalSize, "), ");
2885 vboxVidPnDumpRegion("activeSize(", &pVideoSignalInfo->ActiveSize, "), ");
2886 vboxVidPnDumpRational("VSynch(", &pVideoSignalInfo->VSyncFreq, "), ");
2887 LOGREL_EXACT(("PixelRate(%d), ScanLineOrdering(%s)%s", pVideoSignalInfo->PixelRate, vboxVidPnDumpStrScanLineOrdering(pVideoSignalInfo->ScanLineOrdering), pSuffix));
2888}
2889
2890void VBoxVidPnDumpTargetMode(const char *pPrefix, const D3DKMDT_VIDPN_TARGET_MODE* CONST pVidPnTargetModeInfo, const char *pSuffix)
2891{
2892 LOGREL_EXACT(("%s", pPrefix));
2893 LOGREL_EXACT(("ID: %d, ", pVidPnTargetModeInfo->Id));
2894 vboxVidPnDumpSignalInfo("VSI: ", &pVidPnTargetModeInfo->VideoSignalInfo, ", ");
2895 LOGREL_EXACT(("Preference(%s)%s", vboxVidPnDumpStrModePreference(pVidPnTargetModeInfo->Preference), pSuffix));
2896}
2897
2898void VBoxVidPnDumpMonitorMode(const char *pPrefix, const D3DKMDT_MONITOR_SOURCE_MODE *pVidPnModeInfo, const char *pSuffix)
2899{
2900 LOGREL_EXACT(("%s", pPrefix));
2901
2902 LOGREL_EXACT(("ID: %d, ", pVidPnModeInfo->Id));
2903
2904 vboxVidPnDumpSignalInfo("VSI: ", &pVidPnModeInfo->VideoSignalInfo, ", ");
2905
2906 LOGREL_EXACT(("ColorBasis: %s, ", vboxVidPnDumpStrColorBasis(pVidPnModeInfo->ColorBasis)));
2907
2908 vboxVidPnDumpRanges("Ranges: ", &pVidPnModeInfo->ColorCoeffDynamicRanges, ", ");
2909
2910 LOGREL_EXACT(("MonCapOr: %s, ", vboxVidPnDumpStrMonCapabilitiesOrigin(pVidPnModeInfo->Origin)));
2911
2912 LOGREL_EXACT(("Preference(%s)%s", vboxVidPnDumpStrModePreference(pVidPnModeInfo->Preference), pSuffix));
2913}
2914
2915NTSTATUS VBoxVidPnDumpMonitorModeSet(const char *pPrefix, PVBOXMP_DEVEXT pDevExt, uint32_t u32Target, const char *pSuffix)
2916{
2917 LOGREL_EXACT(("%s Tgt[%d]\n", pPrefix, u32Target));
2918
2919 NTSTATUS Status;
2920 CONST DXGK_MONITOR_INTERFACE *pMonitorInterface;
2921 Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryMonitorInterface(pDevExt->u.primary.DxgkInterface.DeviceHandle, DXGK_MONITOR_INTERFACE_VERSION_V1, &pMonitorInterface);
2922 if (!NT_SUCCESS(Status))
2923 {
2924 WARN(("DxgkCbQueryMonitorInterface failed, Status()0x%x", Status));
2925 return Status;
2926 }
2927
2928 D3DKMDT_HMONITORSOURCEMODESET hVidPnModeSet;
2929 CONST DXGK_MONITORSOURCEMODESET_INTERFACE *pVidPnModeSetInterface;
2930
2931 Status = pMonitorInterface->pfnAcquireMonitorSourceModeSet(pDevExt->u.primary.DxgkInterface.DeviceHandle,
2932 u32Target,
2933 &hVidPnModeSet,
2934 &pVidPnModeSetInterface);
2935 if (!NT_SUCCESS(Status))
2936 {
2937 WARN(("DxgkCbQueryMonitorInterface failed, Status()0x%x", Status));
2938 return Status;
2939 }
2940
2941 VBOXVIDPN_MONITORMODE_ITER Iter;
2942 const D3DKMDT_MONITOR_SOURCE_MODE *pVidPnModeInfo;
2943
2944 VBoxVidPnMonitorModeIterInit(&Iter, hVidPnModeSet, pVidPnModeSetInterface);
2945
2946 while ((pVidPnModeInfo = VBoxVidPnMonitorModeIterNext(&Iter)) != NULL)
2947 {
2948 VBoxVidPnDumpMonitorMode("MonitorMode: ",pVidPnModeInfo, "\n");
2949 }
2950
2951 VBoxVidPnMonitorModeIterTerm(&Iter);
2952
2953 Status = VBoxVidPnMonitorModeIterStatus(&Iter);
2954 if (!NT_SUCCESS(Status))
2955 {
2956 WARN(("iter status failed %#x", Status));
2957 }
2958
2959 NTSTATUS rcNt2 = pMonitorInterface->pfnReleaseMonitorSourceModeSet(pDevExt->u.primary.DxgkInterface.DeviceHandle, hVidPnModeSet);
2960 if (!NT_SUCCESS(rcNt2))
2961 WARN(("pfnReleaseMonitorSourceModeSet failed rcNt2(0x%x)", rcNt2));
2962
2963 LOGREL_EXACT(("%s", pSuffix));
2964
2965 return Status;
2966}
2967
2968void vboxVidPnDumpPinnedSourceMode(const D3DKMDT_HVIDPN hVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
2969{
2970 D3DKMDT_HVIDPNSOURCEMODESET hCurVidPnSourceModeSet;
2971 const DXGK_VIDPNSOURCEMODESET_INTERFACE *pCurVidPnSourceModeSetInterface;
2972
2973 NTSTATUS Status = pVidPnInterface->pfnAcquireSourceModeSet(hVidPn,
2974 VidPnSourceId,
2975 &hCurVidPnSourceModeSet,
2976 &pCurVidPnSourceModeSetInterface);
2977 AssertNtStatusSuccess(Status);
2978 if (Status == STATUS_SUCCESS)
2979 {
2980 CONST D3DKMDT_VIDPN_SOURCE_MODE* pPinnedVidPnSourceModeInfo;
2981
2982 Status = pCurVidPnSourceModeSetInterface->pfnAcquirePinnedModeInfo(hCurVidPnSourceModeSet, &pPinnedVidPnSourceModeInfo);
2983 Assert(Status == STATUS_SUCCESS || Status == STATUS_GRAPHICS_MODE_NOT_PINNED);
2984 if (Status == STATUS_SUCCESS)
2985 {
2986 VBoxVidPnDumpSourceMode("Source Pinned: ", pPinnedVidPnSourceModeInfo, "\n");
2987 pCurVidPnSourceModeSetInterface->pfnReleaseModeInfo(hCurVidPnSourceModeSet, pPinnedVidPnSourceModeInfo);
2988 }
2989 else if (Status == STATUS_GRAPHICS_MODE_NOT_PINNED)
2990 {
2991 LOGREL_EXACT(("Source NOT Pinned\n"));
2992 }
2993 else
2994 {
2995 LOGREL_EXACT(("ERROR getting piined Source Mode(0x%x)\n", Status));
2996 }
2997 pVidPnInterface->pfnReleaseSourceModeSet(hVidPn, hCurVidPnSourceModeSet);
2998 }
2999 else
3000 {
3001 LOGREL_EXACT(("ERROR getting SourceModeSet(0x%x)\n", Status));
3002 }
3003}
3004
3005
3006DECLCALLBACK(BOOLEAN) vboxVidPnDumpSourceModeSetEnum(D3DKMDT_HVIDPNSOURCEMODESET hNewVidPnSourceModeSet,
3007 const DXGK_VIDPNSOURCEMODESET_INTERFACE *pVidPnSourceModeSetInterface,
3008 const D3DKMDT_VIDPN_SOURCE_MODE *pNewVidPnSourceModeInfo, PVOID pContext)
3009{
3010
3011 RT_NOREF(hNewVidPnSourceModeSet, pVidPnSourceModeSetInterface, pNewVidPnSourceModeInfo, pContext);
3012 VBoxVidPnDumpSourceMode("SourceMode: ", pNewVidPnSourceModeInfo, "\n");
3013 return TRUE;
3014}
3015
3016void vboxVidPnDumpSourceModeSet(PVBOXMP_DEVEXT pDevExt, const D3DKMDT_HVIDPN hVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface,
3017 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
3018{
3019 RT_NOREF(pDevExt);
3020 LOGREL_EXACT(("\n >>>+++SourceMode Set for Source(%d)+++\n", VidPnSourceId));
3021 D3DKMDT_HVIDPNSOURCEMODESET hCurVidPnSourceModeSet;
3022 const DXGK_VIDPNSOURCEMODESET_INTERFACE *pCurVidPnSourceModeSetInterface;
3023
3024 NTSTATUS Status = pVidPnInterface->pfnAcquireSourceModeSet(hVidPn,
3025 VidPnSourceId,
3026 &hCurVidPnSourceModeSet,
3027 &pCurVidPnSourceModeSetInterface);
3028 AssertNtStatusSuccess(Status);
3029 if (Status == STATUS_SUCCESS)
3030 {
3031
3032 Status = vboxVidPnEnumSourceModes(hCurVidPnSourceModeSet, pCurVidPnSourceModeSetInterface,
3033 vboxVidPnDumpSourceModeSetEnum, NULL);
3034 AssertNtStatusSuccess(Status);
3035 if (Status != STATUS_SUCCESS)
3036 {
3037 LOGREL_EXACT(("ERROR enumerating Source Modes(0x%x)\n", Status));
3038 }
3039 pVidPnInterface->pfnReleaseSourceModeSet(hVidPn, hCurVidPnSourceModeSet);
3040 }
3041 else
3042 {
3043 LOGREL_EXACT(("ERROR getting SourceModeSet for Source(%d), Status(0x%x)\n", VidPnSourceId, Status));
3044 }
3045
3046 LOGREL_EXACT((" <<<+++End Of SourceMode Set for Source(%d)+++", VidPnSourceId));
3047}
3048
3049DECLCALLBACK(BOOLEAN) vboxVidPnDumpTargetModeSetEnum(D3DKMDT_HVIDPNTARGETMODESET hNewVidPnTargetModeSet,
3050 const DXGK_VIDPNTARGETMODESET_INTERFACE *pVidPnTargetModeSetInterface,
3051 const D3DKMDT_VIDPN_TARGET_MODE *pNewVidPnTargetModeInfo, PVOID pContext)
3052{
3053 RT_NOREF(hNewVidPnTargetModeSet, pVidPnTargetModeSetInterface, pNewVidPnTargetModeInfo, pContext);
3054 VBoxVidPnDumpTargetMode("TargetMode: ", pNewVidPnTargetModeInfo, "\n");
3055 return TRUE;
3056}
3057
3058void vboxVidPnDumpTargetModeSet(PVBOXMP_DEVEXT pDevExt, const D3DKMDT_HVIDPN hVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface,
3059 D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
3060{
3061 RT_NOREF(pDevExt);
3062 LOGREL_EXACT(("\n >>>---TargetMode Set for Target(%d)---\n", VidPnTargetId));
3063 D3DKMDT_HVIDPNTARGETMODESET hCurVidPnTargetModeSet;
3064 const DXGK_VIDPNTARGETMODESET_INTERFACE *pCurVidPnTargetModeSetInterface;
3065
3066 NTSTATUS Status = pVidPnInterface->pfnAcquireTargetModeSet(hVidPn,
3067 VidPnTargetId,
3068 &hCurVidPnTargetModeSet,
3069 &pCurVidPnTargetModeSetInterface);
3070 AssertNtStatusSuccess(Status);
3071 if (Status == STATUS_SUCCESS)
3072 {
3073
3074 Status = vboxVidPnEnumTargetModes(hCurVidPnTargetModeSet, pCurVidPnTargetModeSetInterface,
3075 vboxVidPnDumpTargetModeSetEnum, NULL);
3076 AssertNtStatusSuccess(Status);
3077 if (Status != STATUS_SUCCESS)
3078 {
3079 LOGREL_EXACT(("ERROR enumerating Target Modes(0x%x)\n", Status));
3080 }
3081 pVidPnInterface->pfnReleaseTargetModeSet(hVidPn, hCurVidPnTargetModeSet);
3082 }
3083 else
3084 {
3085 LOGREL_EXACT(("ERROR getting TargetModeSet for Target(%d), Status(0x%x)\n", VidPnTargetId, Status));
3086 }
3087
3088 LOGREL_EXACT((" <<<---End Of TargetMode Set for Target(%d)---", VidPnTargetId));
3089}
3090
3091
3092void vboxVidPnDumpPinnedTargetMode(const D3DKMDT_HVIDPN hVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
3093{
3094 D3DKMDT_HVIDPNTARGETMODESET hCurVidPnTargetModeSet;
3095 const DXGK_VIDPNTARGETMODESET_INTERFACE *pCurVidPnTargetModeSetInterface;
3096
3097 NTSTATUS Status = pVidPnInterface->pfnAcquireTargetModeSet(hVidPn,
3098 VidPnTargetId,
3099 &hCurVidPnTargetModeSet,
3100 &pCurVidPnTargetModeSetInterface);
3101 AssertNtStatusSuccess(Status);
3102 if (Status == STATUS_SUCCESS)
3103 {
3104 CONST D3DKMDT_VIDPN_TARGET_MODE* pPinnedVidPnTargetModeInfo;
3105
3106 Status = pCurVidPnTargetModeSetInterface->pfnAcquirePinnedModeInfo(hCurVidPnTargetModeSet, &pPinnedVidPnTargetModeInfo);
3107 Assert(Status == STATUS_SUCCESS || Status == STATUS_GRAPHICS_MODE_NOT_PINNED);
3108 if (Status == STATUS_SUCCESS)
3109 {
3110 VBoxVidPnDumpTargetMode("Target Pinned: ", pPinnedVidPnTargetModeInfo, "\n");
3111 pCurVidPnTargetModeSetInterface->pfnReleaseModeInfo(hCurVidPnTargetModeSet, pPinnedVidPnTargetModeInfo);
3112 }
3113 else if (Status == STATUS_GRAPHICS_MODE_NOT_PINNED)
3114 {
3115 LOGREL_EXACT(("Target NOT Pinned\n"));
3116 }
3117 else
3118 {
3119 LOGREL_EXACT(("ERROR getting piined Target Mode(0x%x)\n", Status));
3120 }
3121 pVidPnInterface->pfnReleaseTargetModeSet(hVidPn, hCurVidPnTargetModeSet);
3122 }
3123 else
3124 {
3125 LOGREL_EXACT(("ERROR getting TargetModeSet(0x%x)\n", Status));
3126 }
3127}
3128
3129void VBoxVidPnDumpCofuncModalityInfo(const char *pPrefix, D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE enmEnumPivotType, const DXGK_ENUM_PIVOT *pPivot, const char *pSuffix)
3130{
3131 LOGREL_EXACT(("%sPivotType(%s), SourceId(0x%x), TargetId(0x%x),%s", pPrefix, vboxVidPnDumpStrCFMPivotType(enmEnumPivotType),
3132 pPivot->VidPnSourceId, pPivot->VidPnTargetId, pSuffix));
3133}
3134
3135void vboxVidPnDumpCofuncModalityArg(const char *pPrefix, D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE enmPivot, const DXGK_ENUM_PIVOT *pPivot, const char *pSuffix)
3136{
3137 LOGREL_EXACT(("%sPivotType(%s), SourceId(0x%x), TargetId(0x%x),%s", pPrefix, vboxVidPnDumpStrCFMPivotType(enmPivot),
3138 pPivot->VidPnSourceId, pPivot->VidPnTargetId, pSuffix));
3139}
3140
3141void vboxVidPnDumpPath(const D3DKMDT_HVIDPN hVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface, const D3DKMDT_VIDPN_PRESENT_PATH *pVidPnPresentPathInfo)
3142{
3143 LOGREL_EXACT((" >>**** Start Dump VidPn Path ****>>\n"));
3144 LOGREL_EXACT(("VidPnSourceId(%d), VidPnTargetId(%d)\n",
3145 pVidPnPresentPathInfo->VidPnSourceId, pVidPnPresentPathInfo->VidPnTargetId));
3146
3147 vboxVidPnDumpPinnedSourceMode(hVidPn, pVidPnInterface, pVidPnPresentPathInfo->VidPnSourceId);
3148 vboxVidPnDumpPinnedTargetMode(hVidPn, pVidPnInterface, pVidPnPresentPathInfo->VidPnTargetId);
3149
3150 vboxVidPnDumpPathTransformation(&pVidPnPresentPathInfo->ContentTransformation);
3151
3152 LOGREL_EXACT(("Importance(%s), TargetColorBasis(%s), Content(%s), ",
3153 vboxVidPnDumpStrImportance(pVidPnPresentPathInfo->ImportanceOrdinal),
3154 vboxVidPnDumpStrColorBasis(pVidPnPresentPathInfo->VidPnTargetColorBasis),
3155 vboxVidPnDumpStrContent(pVidPnPresentPathInfo->Content)));
3156 vboxVidPnDumpRegion("VFA_TL_O(", &pVidPnPresentPathInfo->VisibleFromActiveTLOffset, "), ");
3157 vboxVidPnDumpRegion("VFA_BR_O(", &pVidPnPresentPathInfo->VisibleFromActiveBROffset, "), ");
3158 vboxVidPnDumpRanges("CCDynamicRanges: ", &pVidPnPresentPathInfo->VidPnTargetColorCoeffDynamicRanges, "| ");
3159 vboxVidPnDumpCopyProtectoin("CProtection: ", &pVidPnPresentPathInfo->CopyProtection, "| ");
3160 vboxVidPnDumpGammaRamp("GammaRamp: ", &pVidPnPresentPathInfo->GammaRamp, "\n");
3161
3162 LOGREL_EXACT((" <<**** Stop Dump VidPn Path ****<<"));
3163}
3164
3165typedef struct VBOXVIDPNDUMPPATHENUM
3166{
3167 D3DKMDT_HVIDPN hVidPn;
3168 const DXGK_VIDPN_INTERFACE* pVidPnInterface;
3169} VBOXVIDPNDUMPPATHENUM, *PVBOXVIDPNDUMPPATHENUM;
3170
3171static DECLCALLBACK(BOOLEAN) vboxVidPnDumpPathEnum(D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface,
3172 const D3DKMDT_VIDPN_PRESENT_PATH *pVidPnPresentPathInfo, PVOID pContext)
3173{
3174 PVBOXVIDPNDUMPPATHENUM pData = (PVBOXVIDPNDUMPPATHENUM)pContext;
3175 vboxVidPnDumpPath(pData->hVidPn, pData->pVidPnInterface, pVidPnPresentPathInfo);
3176
3177 pVidPnTopologyInterface->pfnReleasePathInfo(hVidPnTopology, pVidPnPresentPathInfo);
3178 return TRUE;
3179}
3180
3181void vboxVidPnDumpVidPn(const char * pPrefix, PVBOXMP_DEVEXT pDevExt, D3DKMDT_HVIDPN hVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface, const char * pSuffix)
3182{
3183 LOGREL_EXACT(("%s", pPrefix));
3184
3185 VBOXVIDPNDUMPPATHENUM CbData;
3186 CbData.hVidPn = hVidPn;
3187 CbData.pVidPnInterface = pVidPnInterface;
3188 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
3189 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
3190 NTSTATUS Status = pVidPnInterface->pfnGetTopology(hVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
3191 AssertNtStatusSuccess(Status);
3192 if (Status == STATUS_SUCCESS)
3193 {
3194 Status = vboxVidPnEnumPaths(hVidPnTopology, pVidPnTopologyInterface,
3195 vboxVidPnDumpPathEnum, &CbData);
3196 AssertNtStatusSuccess(Status);
3197 }
3198
3199 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
3200 {
3201 vboxVidPnDumpSourceModeSet(pDevExt, hVidPn, pVidPnInterface, (D3DDDI_VIDEO_PRESENT_SOURCE_ID)i);
3202 vboxVidPnDumpTargetModeSet(pDevExt, hVidPn, pVidPnInterface, (D3DDDI_VIDEO_PRESENT_TARGET_ID)i);
3203 }
3204
3205 LOGREL_EXACT(("%s", pSuffix));
3206}
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