VirtualBox

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

Last change on this file since 69496 was 69496, checked in by vboxsync, 7 years ago

*: scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 125.7 KB
Line 
1/* $Id: VBoxMPVidPn.cpp 69496 2017-10-28 14:55:58Z vboxsync $ */
2/** @file
3 * VBox WDDM Miniport driver
4 */
5
6/*
7 * Copyright (C) 2011-2017 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)((pVsi->PixelRate / 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, 60 /* ULONG VSync */);
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, 60 /* ULONG VSync */);
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 VBoxVideoW8.sys 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 *pfSupported = FALSE;
1692
1693 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
1694 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(hVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
1695 if (!NT_SUCCESS(Status))
1696 {
1697 WARN(("DxgkCbQueryVidPnInterface failed Status()0x%x\n", Status));
1698 return Status;
1699 }
1700
1701#ifdef VBOXWDDM_DEBUG_VIDPN
1702 vboxVidPnDumpVidPn(">>>>IsSupported VidPN (IN) : >>>>\n", pDevExt, hVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<\n");
1703#endif
1704
1705 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
1706 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
1707 Status = pVidPnInterface->pfnGetTopology(hVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
1708 if (!NT_SUCCESS(Status))
1709 {
1710 WARN(("pfnGetTopology failed Status()0x%x\n", Status));
1711 return Status;
1712 }
1713
1714 VBOXVIDPN_PATH_ITER PathIter;
1715 const D3DKMDT_VIDPN_PRESENT_PATH * pPath;
1716 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aVisitedTargetMap);
1717
1718 memset(aVisitedTargetMap, 0, sizeof (aVisitedTargetMap));
1719
1720 BOOLEAN fSupported = TRUE;
1721 /* collect info first */
1722 VBoxVidPnPathIterInit(&PathIter, hVidPnTopology, pVidPnTopologyInterface);
1723 while ((pPath = VBoxVidPnPathIterNext(&PathIter)) != NULL)
1724 {
1725 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId = pPath->VidPnSourceId;
1726 D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId = pPath->VidPnTargetId;
1727 /* actually vidpn topology should contain only one target info, right? */
1728 Assert(!ASMBitTest(aVisitedTargetMap, VidPnTargetId));
1729 ASMBitSet(aVisitedTargetMap, VidPnTargetId);
1730
1731 if (!vboxVidPnIsPathSupported(pDevExt, pPath))
1732 {
1733 fSupported = FALSE;
1734 break;
1735 }
1736
1737 RTRECTSIZE TargetSize;
1738 RTRECTSIZE SourceSize;
1739 Status = vboxVidPnQueryPinnedTargetMode(hVidPn, pVidPnInterface, VidPnTargetId, &TargetSize);
1740 if (!NT_SUCCESS(Status))
1741 {
1742 WARN(("vboxVidPnQueryPinnedTargetMode failed %#x", Status));
1743 break;
1744 }
1745
1746 Status = vboxVidPnQueryPinnedSourceMode(hVidPn, pVidPnInterface, VidPnSourceId, &SourceSize);
1747 if (!NT_SUCCESS(Status))
1748 {
1749 WARN(("vboxVidPnQueryPinnedSourceMode failed %#x", Status));
1750 break;
1751 }
1752
1753 if (memcmp(&TargetSize, &SourceSize, sizeof (TargetSize)) && TargetSize.cx)
1754 {
1755 if (!SourceSize.cx)
1756 WARN(("not expected?"));
1757
1758 fSupported = FALSE;
1759 break;
1760 }
1761 }
1762
1763 VBoxVidPnPathIterTerm(&PathIter);
1764
1765 if (!NT_SUCCESS(Status))
1766 goto done;
1767
1768 Status = VBoxVidPnPathIterStatus(&PathIter);
1769 if (!NT_SUCCESS(Status))
1770 {
1771 WARN(("PathIter failed Status()0x%x\n", Status));
1772 goto done;
1773 }
1774
1775 *pfSupported = fSupported;
1776done:
1777
1778 return Status;
1779}
1780
1781NTSTATUS VBoxVidPnCofuncModality(PVBOXMP_DEVEXT pDevExt, D3DKMDT_HVIDPN hVidPn, D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE enmPivot, const DXGK_ENUM_PIVOT *pPivot)
1782{
1783 const DXGK_VIDPN_INTERFACE* pVidPnInterface = NULL;
1784 NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryVidPnInterface(hVidPn, DXGK_VIDPN_INTERFACE_VERSION_V1, &pVidPnInterface);
1785 if (!NT_SUCCESS(Status))
1786 {
1787 WARN(("DxgkCbQueryVidPnInterface failed Status()0x%x\n", Status));
1788 return Status;
1789 }
1790
1791#ifdef VBOXWDDM_DEBUG_VIDPN
1792 vboxVidPnDumpCofuncModalityArg(">>>>MODALITY Args: ", enmPivot, pPivot, "\n");
1793 vboxVidPnDumpVidPn(">>>>MODALITY VidPN (IN) : >>>>\n", pDevExt, hVidPn, pVidPnInterface, "<<<<<<<<<<<<<<<<<<<<\n");
1794#endif
1795
1796 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
1797 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
1798 Status = pVidPnInterface->pfnGetTopology(hVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
1799 if (!NT_SUCCESS(Status))
1800 {
1801 WARN(("pfnGetTopology failed Status()0x%x\n", Status));
1802 return Status;
1803 }
1804
1805 VBOXVIDPN_PATH_ITER PathIter;
1806 const D3DKMDT_VIDPN_PRESENT_PATH * pPath;
1807 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aVisitedTargetMap);
1808 VBOXCMDVBVA_SCREENMAP_DECL(uint32_t, aAdjustedModeMap);
1809 CR_SORTARRAY aModes[VBOX_VIDEO_MAX_SCREENS];
1810
1811 memset(aVisitedTargetMap, 0, sizeof (aVisitedTargetMap));
1812 memset(aAdjustedModeMap, 0, sizeof (aAdjustedModeMap));
1813 memset(aModes, 0, sizeof (aModes));
1814
1815 /* collect info first */
1816 VBoxVidPnPathIterInit(&PathIter, hVidPnTopology, pVidPnTopologyInterface);
1817 while ((pPath = VBoxVidPnPathIterNext(&PathIter)) != NULL)
1818 {
1819 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId = pPath->VidPnSourceId;
1820 D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId = pPath->VidPnTargetId;
1821 /* actually vidpn topology should contain only one target info, right? */
1822 Assert(!ASMBitTest(aVisitedTargetMap, VidPnTargetId));
1823 ASMBitSet(aVisitedTargetMap, VidPnTargetId);
1824
1825 D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE enmCurPivot = vboxVidPnCofuncModalityCurrentPathPivot(enmPivot, pPivot, VidPnSourceId, VidPnTargetId);
1826
1827 Status = vboxVidPnCollectInfoForPathTarget(pDevExt,
1828 hVidPn,
1829 pVidPnInterface,
1830 enmCurPivot,
1831 aAdjustedModeMap,
1832 aModes,
1833 VidPnSourceId, VidPnTargetId);
1834 if (!NT_SUCCESS(Status))
1835 {
1836 WARN(("vboxVidPnCollectInfoForPathTarget failed Status(0x%x\n", Status));
1837 VBoxVidPnDumpCofuncModalityInfo("Modality Info: ", enmPivot, pPivot, "\n");
1838 break;
1839 }
1840
1841 Assert(CrSaCovers(VBoxWddmVModesGet(pDevExt, VidPnTargetId), &aModes[VidPnTargetId]));
1842
1843 Status = vboxVidPnCollectInfoForPathSource(pDevExt,
1844 hVidPn,
1845 pVidPnInterface,
1846 enmCurPivot,
1847 aAdjustedModeMap,
1848 aModes,
1849 VidPnSourceId, VidPnTargetId);
1850 if (!NT_SUCCESS(Status))
1851 {
1852 WARN(("vboxVidPnCollectInfoForPathSource failed Status(0x%x\n", Status));
1853 VBoxVidPnDumpCofuncModalityInfo("Modality Info: ", enmPivot, pPivot, "\n");
1854 break;
1855 }
1856
1857 Assert(CrSaCovers(VBoxWddmVModesGet(pDevExt, VidPnTargetId), &aModes[VidPnTargetId]));
1858 }
1859
1860 VBoxVidPnPathIterTerm(&PathIter);
1861
1862 if (!NT_SUCCESS(Status))
1863 goto done;
1864
1865 Status = VBoxVidPnPathIterStatus(&PathIter);
1866 if (!NT_SUCCESS(Status))
1867 {
1868 WARN(("PathIter failed Status()0x%x\n", Status));
1869 VBoxVidPnDumpCofuncModalityInfo("Modality Info: ", enmPivot, pPivot, "\n");
1870 goto done;
1871 }
1872
1873 /* now we have collected all the necessary info,
1874 * go ahead and apply it */
1875 memset(aVisitedTargetMap, 0, sizeof (aVisitedTargetMap));
1876 VBoxVidPnPathIterInit(&PathIter, hVidPnTopology, pVidPnTopologyInterface);
1877 while ((pPath = VBoxVidPnPathIterNext(&PathIter)) != NULL)
1878 {
1879 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId = pPath->VidPnSourceId;
1880 D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId = pPath->VidPnTargetId;
1881 /* actually vidpn topology should contain only one target info, right? */
1882 Assert(!ASMBitTest(aVisitedTargetMap, VidPnTargetId));
1883 ASMBitSet(aVisitedTargetMap, VidPnTargetId);
1884
1885 D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE enmCurPivot = vboxVidPnCofuncModalityCurrentPathPivot(enmPivot, pPivot, VidPnSourceId, VidPnTargetId);
1886
1887 bool bUpdatePath = false;
1888 D3DKMDT_VIDPN_PRESENT_PATH AdjustedPath = {0};
1889 AdjustedPath.VidPnSourceId = pPath->VidPnSourceId;
1890 AdjustedPath.VidPnTargetId = pPath->VidPnTargetId;
1891 AdjustedPath.ContentTransformation = pPath->ContentTransformation;
1892 AdjustedPath.CopyProtection = pPath->CopyProtection;
1893
1894 if (pPath->ContentTransformation.Scaling == D3DKMDT_VPPS_UNPINNED)
1895 {
1896 AdjustedPath.ContentTransformation.ScalingSupport.Identity = TRUE;
1897 bUpdatePath = true;
1898 }
1899
1900 if (pPath->ContentTransformation.Rotation == D3DKMDT_VPPR_UNPINNED)
1901 {
1902 AdjustedPath.ContentTransformation.RotationSupport.Identity = TRUE;
1903 bUpdatePath = true;
1904 }
1905
1906 if (bUpdatePath)
1907 {
1908 Status = pVidPnTopologyInterface->pfnUpdatePathSupportInfo(hVidPnTopology, &AdjustedPath);
1909 if (!NT_SUCCESS(Status))
1910 {
1911 WARN(("pfnUpdatePathSupportInfo failed Status()0x%x\n", Status));
1912 VBoxVidPnDumpCofuncModalityInfo("Modality Info: ", enmPivot, pPivot, "\n");
1913 goto done;
1914 }
1915 }
1916
1917 Assert(CrSaCovers(VBoxWddmVModesGet(pDevExt, VidPnTargetId), &aModes[VidPnTargetId]));
1918
1919 Status = vboxVidPnApplyInfoForPathTarget(pDevExt,
1920 hVidPn,
1921 pVidPnInterface,
1922 enmCurPivot,
1923 aAdjustedModeMap,
1924 aModes,
1925 VidPnSourceId, VidPnTargetId);
1926 if (!NT_SUCCESS(Status))
1927 {
1928 WARN(("vboxVidPnApplyInfoForPathTarget failed Status(0x%x\n", Status));
1929 VBoxVidPnDumpCofuncModalityInfo("Modality Info: ", enmPivot, pPivot, "\n");
1930 break;
1931 }
1932
1933 Status = vboxVidPnApplyInfoForPathSource(pDevExt,
1934 hVidPn,
1935 pVidPnInterface,
1936 enmCurPivot,
1937 aAdjustedModeMap,
1938 aModes,
1939 VidPnSourceId, VidPnTargetId);
1940 if (!NT_SUCCESS(Status))
1941 {
1942 WARN(("vboxVidPnApplyInfoForPathSource failed Status(0x%x\n", Status));
1943 VBoxVidPnDumpCofuncModalityInfo("Modality Info: ", enmPivot, pPivot, "\n");
1944 break;
1945 }
1946 }
1947
1948 VBoxVidPnPathIterTerm(&PathIter);
1949
1950 if (!NT_SUCCESS(Status))
1951 goto done;
1952
1953 Status = VBoxVidPnPathIterStatus(&PathIter);
1954 if (!NT_SUCCESS(Status))
1955 {
1956 WARN(("PathIter failed Status()0x%x\n", Status));
1957 VBoxVidPnDumpCofuncModalityInfo("Modality Info: ", enmPivot, pPivot, "\n");
1958 goto done;
1959 }
1960
1961done:
1962
1963 for (uint32_t i = 0; i < (uint32_t)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
1964 {
1965 CrSaCleanup(&aModes[i]);
1966 }
1967
1968 return Status;
1969}
1970
1971NTSTATUS vboxVidPnEnumMonitorSourceModes(D3DKMDT_HMONITORSOURCEMODESET hMonitorSMS, CONST DXGK_MONITORSOURCEMODESET_INTERFACE *pMonitorSMSIf,
1972 PFNVBOXVIDPNENUMMONITORSOURCEMODES pfnCallback, PVOID pContext)
1973{
1974 CONST D3DKMDT_MONITOR_SOURCE_MODE *pMonitorSMI;
1975 NTSTATUS Status = pMonitorSMSIf->pfnAcquireFirstModeInfo(hMonitorSMS, &pMonitorSMI);
1976 Assert(Status == STATUS_SUCCESS || Status == STATUS_GRAPHICS_DATASET_IS_EMPTY);
1977 if (Status == STATUS_SUCCESS)
1978 {
1979 Assert(pMonitorSMI);
1980 while (1)
1981 {
1982 CONST D3DKMDT_MONITOR_SOURCE_MODE *pNextMonitorSMI;
1983 Status = pMonitorSMSIf->pfnAcquireNextModeInfo(hMonitorSMS, pMonitorSMI, &pNextMonitorSMI);
1984 if (!pfnCallback(hMonitorSMS, pMonitorSMSIf, pMonitorSMI, pContext))
1985 {
1986 Assert(Status == STATUS_SUCCESS || Status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET);
1987 if (Status == STATUS_SUCCESS)
1988 pMonitorSMSIf->pfnReleaseModeInfo(hMonitorSMS, pNextMonitorSMI);
1989 else if (Status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET)
1990 {
1991 Status = STATUS_SUCCESS;
1992 break;
1993 }
1994 else
1995 {
1996 LOGREL(("pfnAcquireNextModeInfo Failed Status(0x%x), ignored since callback returned false", Status));
1997 Status = STATUS_SUCCESS;
1998 }
1999 break;
2000 }
2001 else if (Status == STATUS_SUCCESS)
2002 pMonitorSMI = pNextMonitorSMI;
2003 else if (Status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET)
2004 {
2005 Status = STATUS_SUCCESS;
2006 break;
2007 }
2008 else
2009 {
2010 AssertBreakpoint();
2011 LOGREL(("pfnAcquireNextModeInfo Failed Status(0x%x)", Status));
2012 pNextMonitorSMI = NULL;
2013 break;
2014 }
2015 }
2016 }
2017 else if (Status == STATUS_GRAPHICS_DATASET_IS_EMPTY)
2018 Status = STATUS_SUCCESS;
2019 else
2020 LOGREL(("pfnAcquireFirstModeInfo failed Status(0x%x)", Status));
2021
2022 return Status;
2023}
2024
2025NTSTATUS vboxVidPnEnumSourceModes(D3DKMDT_HVIDPNSOURCEMODESET hNewVidPnSourceModeSet, const DXGK_VIDPNSOURCEMODESET_INTERFACE *pVidPnSourceModeSetInterface,
2026 PFNVBOXVIDPNENUMSOURCEMODES pfnCallback, PVOID pContext)
2027{
2028 const D3DKMDT_VIDPN_SOURCE_MODE *pNewVidPnSourceModeInfo;
2029 NTSTATUS Status = pVidPnSourceModeSetInterface->pfnAcquireFirstModeInfo(hNewVidPnSourceModeSet, &pNewVidPnSourceModeInfo);
2030 if (Status == STATUS_SUCCESS)
2031 {
2032 Assert(pNewVidPnSourceModeInfo);
2033 while (1)
2034 {
2035 const D3DKMDT_VIDPN_SOURCE_MODE *pNextVidPnSourceModeInfo;
2036 Status = pVidPnSourceModeSetInterface->pfnAcquireNextModeInfo(hNewVidPnSourceModeSet, pNewVidPnSourceModeInfo, &pNextVidPnSourceModeInfo);
2037 if (!pfnCallback(hNewVidPnSourceModeSet, pVidPnSourceModeSetInterface,
2038 pNewVidPnSourceModeInfo, pContext))
2039 {
2040 AssertNtStatusSuccess(Status);
2041 if (Status == STATUS_SUCCESS)
2042 pVidPnSourceModeSetInterface->pfnReleaseModeInfo(hNewVidPnSourceModeSet, pNextVidPnSourceModeInfo);
2043 else if (Status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET)
2044 {
2045 Status = STATUS_SUCCESS;
2046 break;
2047 }
2048 else
2049 {
2050 LOGREL(("pfnAcquireNextModeInfo Failed Status(0x%x), ignored since callback returned false", Status));
2051 Status = STATUS_SUCCESS;
2052 }
2053
2054 break;
2055 }
2056 else if (Status == STATUS_SUCCESS)
2057 pNewVidPnSourceModeInfo = pNextVidPnSourceModeInfo;
2058 else if (Status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET)
2059 {
2060 Status = STATUS_SUCCESS;
2061 break;
2062 }
2063 else
2064 {
2065 AssertBreakpoint();
2066 LOGREL(("pfnAcquireNextModeInfo Failed Status(0x%x)", Status));
2067 pNewVidPnSourceModeInfo = NULL;
2068 break;
2069 }
2070 }
2071 }
2072 else if (Status == STATUS_GRAPHICS_DATASET_IS_EMPTY)
2073 Status = STATUS_SUCCESS;
2074 else
2075 LOGREL(("pfnAcquireFirstModeInfo failed Status(0x%x)", Status));
2076
2077 return Status;
2078}
2079
2080NTSTATUS vboxVidPnEnumTargetModes(D3DKMDT_HVIDPNTARGETMODESET hNewVidPnTargetModeSet, const DXGK_VIDPNTARGETMODESET_INTERFACE *pVidPnTargetModeSetInterface,
2081 PFNVBOXVIDPNENUMTARGETMODES pfnCallback, PVOID pContext)
2082{
2083 const D3DKMDT_VIDPN_TARGET_MODE *pNewVidPnTargetModeInfo;
2084 NTSTATUS Status = pVidPnTargetModeSetInterface->pfnAcquireFirstModeInfo(hNewVidPnTargetModeSet, &pNewVidPnTargetModeInfo);
2085 if (Status == STATUS_SUCCESS)
2086 {
2087 Assert(pNewVidPnTargetModeInfo);
2088 while (1)
2089 {
2090 const D3DKMDT_VIDPN_TARGET_MODE *pNextVidPnTargetModeInfo;
2091 Status = pVidPnTargetModeSetInterface->pfnAcquireNextModeInfo(hNewVidPnTargetModeSet, pNewVidPnTargetModeInfo, &pNextVidPnTargetModeInfo);
2092 if (!pfnCallback(hNewVidPnTargetModeSet, pVidPnTargetModeSetInterface,
2093 pNewVidPnTargetModeInfo, pContext))
2094 {
2095 AssertNtStatusSuccess(Status);
2096 if (Status == STATUS_SUCCESS)
2097 pVidPnTargetModeSetInterface->pfnReleaseModeInfo(hNewVidPnTargetModeSet, pNextVidPnTargetModeInfo);
2098 else if (Status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET)
2099 {
2100 Status = STATUS_SUCCESS;
2101 break;
2102 }
2103 else
2104 {
2105 LOGREL(("pfnAcquireNextModeInfo Failed Status(0x%x), ignored since callback returned false", Status));
2106 Status = STATUS_SUCCESS;
2107 }
2108
2109 break;
2110 }
2111 else if (Status == STATUS_SUCCESS)
2112 pNewVidPnTargetModeInfo = pNextVidPnTargetModeInfo;
2113 else if (Status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET)
2114 {
2115 Status = STATUS_SUCCESS;
2116 break;
2117 }
2118 else
2119 {
2120 AssertBreakpoint();
2121 LOGREL(("pfnAcquireNextModeInfo Failed Status(0x%x)", Status));
2122 pNewVidPnTargetModeInfo = NULL;
2123 break;
2124 }
2125 }
2126 }
2127 else if (Status == STATUS_GRAPHICS_DATASET_IS_EMPTY)
2128 Status = STATUS_SUCCESS;
2129 else
2130 LOGREL(("pfnAcquireFirstModeInfo failed Status(0x%x)", Status));
2131
2132 return Status;
2133}
2134
2135NTSTATUS vboxVidPnEnumTargetsForSource(PVBOXMP_DEVEXT pDevExt, D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface,
2136 CONST D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId,
2137 PFNVBOXVIDPNENUMTARGETSFORSOURCE pfnCallback, PVOID pContext)
2138{
2139 SIZE_T cTgtPaths;
2140 NTSTATUS Status = pVidPnTopologyInterface->pfnGetNumPathsFromSource(hVidPnTopology, VidPnSourceId, &cTgtPaths);
2141 Assert(Status == STATUS_SUCCESS || Status == STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY);
2142 if (Status == STATUS_SUCCESS)
2143 {
2144 for (SIZE_T i = 0; i < cTgtPaths; ++i)
2145 {
2146 D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId;
2147 Status = pVidPnTopologyInterface->pfnEnumPathTargetsFromSource(hVidPnTopology, VidPnSourceId, i, &VidPnTargetId);
2148 AssertNtStatusSuccess(Status);
2149 if (Status == STATUS_SUCCESS)
2150 {
2151 if (!pfnCallback(pDevExt, hVidPnTopology, pVidPnTopologyInterface, VidPnSourceId, VidPnTargetId, cTgtPaths, pContext))
2152 break;
2153 }
2154 else
2155 {
2156 LOGREL(("pfnEnumPathTargetsFromSource failed Status(0x%x)", Status));
2157 break;
2158 }
2159 }
2160 }
2161 else if (Status != STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY)
2162 LOGREL(("pfnGetNumPathsFromSource failed Status(0x%x)", Status));
2163
2164 return Status;
2165}
2166
2167NTSTATUS vboxVidPnEnumPaths(D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface,
2168 PFNVBOXVIDPNENUMPATHS pfnCallback, PVOID pContext)
2169{
2170 const D3DKMDT_VIDPN_PRESENT_PATH *pNewVidPnPresentPathInfo = NULL;
2171 NTSTATUS Status = pVidPnTopologyInterface->pfnAcquireFirstPathInfo(hVidPnTopology, &pNewVidPnPresentPathInfo);
2172 if (Status == STATUS_SUCCESS)
2173 {
2174 while (1)
2175 {
2176 const D3DKMDT_VIDPN_PRESENT_PATH *pNextVidPnPresentPathInfo;
2177 Status = pVidPnTopologyInterface->pfnAcquireNextPathInfo(hVidPnTopology, pNewVidPnPresentPathInfo, &pNextVidPnPresentPathInfo);
2178
2179 if (!pfnCallback(hVidPnTopology, pVidPnTopologyInterface, pNewVidPnPresentPathInfo, pContext))
2180 {
2181 if (Status == STATUS_SUCCESS)
2182 pVidPnTopologyInterface->pfnReleasePathInfo(hVidPnTopology, pNextVidPnPresentPathInfo);
2183 else
2184 {
2185 if (Status != STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET)
2186 WARN(("pfnAcquireNextPathInfo Failed Status(0x%x), ignored since callback returned false", Status));
2187 Status = STATUS_SUCCESS;
2188 }
2189
2190 break;
2191 }
2192 else if (Status == STATUS_SUCCESS)
2193 pNewVidPnPresentPathInfo = pNextVidPnPresentPathInfo;
2194 else if (Status == STATUS_GRAPHICS_NO_MORE_ELEMENTS_IN_DATASET)
2195 {
2196 Status = STATUS_SUCCESS;
2197 break;
2198 }
2199 else
2200 {
2201 WARN(("pfnAcquireNextPathInfo Failed Status(0x%x)", Status));
2202 pNewVidPnPresentPathInfo = NULL;
2203 break;
2204 }
2205 }
2206 }
2207 else if (Status == STATUS_GRAPHICS_DATASET_IS_EMPTY)
2208 Status = STATUS_SUCCESS;
2209 else
2210 WARN(("pfnAcquireFirstModeInfo failed Status(0x%x)", Status));
2211
2212 return Status;
2213}
2214
2215NTSTATUS vboxVidPnSetupSourceInfo(PVBOXMP_DEVEXT pDevExt, CONST D3DKMDT_VIDPN_SOURCE_MODE* pVidPnSourceModeInfo,
2216 PVBOXWDDM_ALLOCATION pAllocation, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId,
2217 VBOXWDDM_SOURCE *paSources)
2218{
2219 RT_NOREF(pDevExt);
2220 PVBOXWDDM_SOURCE pSource = &paSources[VidPnSourceId];
2221 /* pVidPnSourceModeInfo could be null if STATUS_GRAPHICS_MODE_NOT_PINNED,
2222 * see VBoxVidPnCommitSourceModeForSrcId */
2223 uint8_t fChanges = 0;
2224 if (pVidPnSourceModeInfo)
2225 {
2226 if (pSource->AllocData.SurfDesc.width != pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cx)
2227 {
2228 fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
2229 pSource->AllocData.SurfDesc.width = pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cx;
2230 }
2231 if (pSource->AllocData.SurfDesc.height != pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy)
2232 {
2233 fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
2234 pSource->AllocData.SurfDesc.height = pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy;
2235 }
2236 if (pSource->AllocData.SurfDesc.format != pVidPnSourceModeInfo->Format.Graphics.PixelFormat)
2237 {
2238 fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
2239 pSource->AllocData.SurfDesc.format = pVidPnSourceModeInfo->Format.Graphics.PixelFormat;
2240 }
2241 if (pSource->AllocData.SurfDesc.bpp != vboxWddmCalcBitsPerPixel(pVidPnSourceModeInfo->Format.Graphics.PixelFormat))
2242 {
2243 fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
2244 pSource->AllocData.SurfDesc.bpp = vboxWddmCalcBitsPerPixel(pVidPnSourceModeInfo->Format.Graphics.PixelFormat);
2245 }
2246 if(pSource->AllocData.SurfDesc.pitch != pVidPnSourceModeInfo->Format.Graphics.Stride)
2247 {
2248 fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
2249 pSource->AllocData.SurfDesc.pitch = pVidPnSourceModeInfo->Format.Graphics.Stride;
2250 }
2251 pSource->AllocData.SurfDesc.depth = 1;
2252 if (pSource->AllocData.SurfDesc.slicePitch != pVidPnSourceModeInfo->Format.Graphics.Stride)
2253 {
2254 fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
2255 pSource->AllocData.SurfDesc.slicePitch = pVidPnSourceModeInfo->Format.Graphics.Stride;
2256 }
2257 if (pSource->AllocData.SurfDesc.cbSize != pVidPnSourceModeInfo->Format.Graphics.Stride * pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy)
2258 {
2259 fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
2260 pSource->AllocData.SurfDesc.cbSize = pVidPnSourceModeInfo->Format.Graphics.Stride * pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize.cy;
2261 }
2262#ifdef VBOX_WDDM_WIN8
2263 if (g_VBoxDisplayOnly)
2264 {
2265 vboxWddmDmSetupDefaultVramLocation(pDevExt, VidPnSourceId, paSources);
2266 }
2267#endif
2268 }
2269 else
2270 {
2271 VBoxVidPnAllocDataInit(&pSource->AllocData, VidPnSourceId);
2272 Assert(!pAllocation);
2273 fChanges |= VBOXWDDM_HGSYNC_F_SYNCED_ALL;
2274 }
2275
2276#ifdef VBOX_WDDM_WIN8
2277 Assert(!g_VBoxDisplayOnly || !pAllocation);
2278 if (!g_VBoxDisplayOnly)
2279#endif
2280 {
2281 vboxWddmAssignPrimary(pSource, pAllocation, VidPnSourceId);
2282 }
2283
2284 Assert(pSource->AllocData.SurfDesc.VidPnSourceId == VidPnSourceId);
2285 pSource->u8SyncState &= ~fChanges;
2286 return STATUS_SUCCESS;
2287}
2288
2289NTSTATUS vboxVidPnCommitSourceMode(PVBOXMP_DEVEXT pDevExt, CONST D3DKMDT_VIDPN_SOURCE_MODE* pVidPnSourceModeInfo, PVBOXWDDM_ALLOCATION pAllocation,
2290 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, VBOXWDDM_SOURCE *paSources)
2291{
2292 if (VidPnSourceId < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays)
2293 return vboxVidPnSetupSourceInfo(pDevExt, pVidPnSourceModeInfo, pAllocation, VidPnSourceId, paSources);
2294
2295 WARN(("invalid srcId (%d), cSources(%d)", VidPnSourceId, VBoxCommonFromDeviceExt(pDevExt)->cDisplays));
2296 return STATUS_INVALID_PARAMETER;
2297}
2298
2299typedef struct VBOXVIDPNCOMMITTARGETMODE
2300{
2301 NTSTATUS Status;
2302 D3DKMDT_HVIDPN hVidPn;
2303 const DXGK_VIDPN_INTERFACE* pVidPnInterface;
2304 VBOXWDDM_SOURCE *paSources;
2305 VBOXWDDM_TARGET *paTargets;
2306} VBOXVIDPNCOMMITTARGETMODE;
2307
2308DECLCALLBACK(BOOLEAN) vboxVidPnCommitTargetModeEnum(PVBOXMP_DEVEXT pDevExt, D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology,
2309 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface,
2310 CONST D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId,
2311 D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId, SIZE_T cTgtPaths,
2312 PVOID pContext)
2313{
2314 RT_NOREF(hVidPnTopology, pVidPnTopologyInterface, cTgtPaths);
2315 VBOXVIDPNCOMMITTARGETMODE *pInfo = (VBOXVIDPNCOMMITTARGETMODE*)pContext;
2316 Assert(cTgtPaths <= (SIZE_T)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
2317 D3DKMDT_HVIDPNTARGETMODESET hVidPnTargetModeSet;
2318 CONST DXGK_VIDPNTARGETMODESET_INTERFACE* pVidPnTargetModeSetInterface;
2319 NTSTATUS Status = pInfo->pVidPnInterface->pfnAcquireTargetModeSet(pInfo->hVidPn, VidPnTargetId, &hVidPnTargetModeSet, &pVidPnTargetModeSetInterface);
2320 AssertNtStatusSuccess(Status);
2321 if (Status == STATUS_SUCCESS)
2322 {
2323 CONST D3DKMDT_VIDPN_TARGET_MODE* pPinnedVidPnTargetModeInfo;
2324 Status = pVidPnTargetModeSetInterface->pfnAcquirePinnedModeInfo(hVidPnTargetModeSet, &pPinnedVidPnTargetModeInfo);
2325 AssertNtStatusSuccess(Status);
2326 if (Status == STATUS_SUCCESS)
2327 {
2328 VBOXWDDM_SOURCE *pSource = &pInfo->paSources[VidPnSourceId];
2329 VBOXWDDM_TARGET *pTarget = &pInfo->paTargets[VidPnTargetId];
2330 pTarget->Size.cx = pPinnedVidPnTargetModeInfo->VideoSignalInfo.ActiveSize.cx;
2331 pTarget->Size.cy = pPinnedVidPnTargetModeInfo->VideoSignalInfo.TotalSize.cy;
2332
2333 VBoxVidPnStSourceTargetAdd(pInfo->paSources, VBoxCommonFromDeviceExt(pDevExt)->cDisplays, pSource, pTarget);
2334
2335 pTarget->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_DIMENSIONS;
2336
2337 pVidPnTargetModeSetInterface->pfnReleaseModeInfo(hVidPnTargetModeSet, pPinnedVidPnTargetModeInfo);
2338 }
2339 else
2340 WARN(("pfnAcquirePinnedModeInfo failed Status(0x%x)", Status));
2341
2342 pInfo->pVidPnInterface->pfnReleaseTargetModeSet(pInfo->hVidPn, hVidPnTargetModeSet);
2343 }
2344 else
2345 WARN(("pfnAcquireTargetModeSet failed Status(0x%x)", Status));
2346
2347 pInfo->Status = Status;
2348 return Status == STATUS_SUCCESS;
2349}
2350
2351NTSTATUS VBoxVidPnCommitSourceModeForSrcId(PVBOXMP_DEVEXT pDevExt, const D3DKMDT_HVIDPN hDesiredVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface,
2352 PVBOXWDDM_ALLOCATION pAllocation,
2353 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId, VBOXWDDM_SOURCE *paSources, VBOXWDDM_TARGET *paTargets, BOOLEAN bPathPowerTransition)
2354{
2355 D3DKMDT_HVIDPNSOURCEMODESET hCurVidPnSourceModeSet;
2356 const DXGK_VIDPNSOURCEMODESET_INTERFACE *pCurVidPnSourceModeSetInterface;
2357
2358 PVBOXWDDM_SOURCE pSource = &paSources[VidPnSourceId];
2359 NTSTATUS Status;
2360
2361 if (bPathPowerTransition)
2362 {
2363 RTRECTSIZE PinnedModeSize;
2364 bool bHasPinnedMode;
2365
2366 Status = vboxVidPnQueryPinnedSourceMode(hDesiredVidPn, pVidPnInterface, VidPnSourceId, &PinnedModeSize);
2367 bHasPinnedMode = Status == STATUS_SUCCESS && PinnedModeSize.cx > 0 && PinnedModeSize.cy > 0;
2368 pSource->bBlankedByPowerOff = !bHasPinnedMode;
2369
2370 LOG(("Path power transition: srcId %d goes blank %d", VidPnSourceId, pSource->bBlankedByPowerOff));
2371 }
2372
2373 VBOXWDDM_TARGET_ITER Iter;
2374 VBoxVidPnStTIterInit(pSource, paTargets, (uint32_t)VBoxCommonFromDeviceExt(pDevExt)->cDisplays, &Iter);
2375 for (PVBOXWDDM_TARGET pTarget = VBoxVidPnStTIterNext(&Iter);
2376 pTarget;
2377 pTarget = VBoxVidPnStTIterNext(&Iter))
2378 {
2379 Assert(pTarget->VidPnSourceId == pSource->AllocData.SurfDesc.VidPnSourceId);
2380 pTarget->Size.cx = 0;
2381 pTarget->Size.cy = 0;
2382 pTarget->fBlankedByPowerOff = RT_BOOL(pSource->bBlankedByPowerOff);
2383 pTarget->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_ALL;
2384 }
2385
2386 VBoxVidPnStSourceCleanup(paSources, VidPnSourceId, paTargets, (uint32_t)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
2387
2388 Status = pVidPnInterface->pfnAcquireSourceModeSet(hDesiredVidPn,
2389 VidPnSourceId,
2390 &hCurVidPnSourceModeSet,
2391 &pCurVidPnSourceModeSetInterface);
2392 AssertNtStatusSuccess(Status);
2393 if (Status == STATUS_SUCCESS)
2394 {
2395 CONST D3DKMDT_VIDPN_SOURCE_MODE* pPinnedVidPnSourceModeInfo;
2396 Status = pCurVidPnSourceModeSetInterface->pfnAcquirePinnedModeInfo(hCurVidPnSourceModeSet, &pPinnedVidPnSourceModeInfo);
2397 Assert(Status == STATUS_SUCCESS || Status == STATUS_GRAPHICS_MODE_NOT_PINNED);
2398 if (Status == STATUS_SUCCESS)
2399 {
2400 Assert(pPinnedVidPnSourceModeInfo);
2401 Status = vboxVidPnCommitSourceMode(pDevExt, pPinnedVidPnSourceModeInfo, pAllocation, VidPnSourceId, paSources);
2402 AssertNtStatusSuccess(Status);
2403 if (Status == STATUS_SUCCESS)
2404 {
2405 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
2406 CONST DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
2407 Status = pVidPnInterface->pfnGetTopology(hDesiredVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
2408 AssertNtStatusSuccess(Status);
2409 if (Status == STATUS_SUCCESS)
2410 {
2411 VBOXVIDPNCOMMITTARGETMODE TgtModeInfo = {0};
2412 TgtModeInfo.Status = STATUS_SUCCESS; /* <- to ensure we're succeeded if no targets are set */
2413 TgtModeInfo.hVidPn = hDesiredVidPn;
2414 TgtModeInfo.pVidPnInterface = pVidPnInterface;
2415 TgtModeInfo.paSources = paSources;
2416 TgtModeInfo.paTargets = paTargets;
2417 Status = vboxVidPnEnumTargetsForSource(pDevExt, hVidPnTopology, pVidPnTopologyInterface,
2418 VidPnSourceId,
2419 vboxVidPnCommitTargetModeEnum, &TgtModeInfo);
2420 Assert(Status == STATUS_SUCCESS || Status == STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY);
2421 if (Status == STATUS_SUCCESS)
2422 {
2423 Status = TgtModeInfo.Status;
2424 AssertNtStatusSuccess(Status);
2425 }
2426 else if (Status == STATUS_GRAPHICS_SOURCE_NOT_IN_TOPOLOGY)
2427 {
2428 Status = STATUS_SUCCESS;
2429 }
2430 else
2431 WARN(("vboxVidPnEnumTargetsForSource failed Status(0x%x)", Status));
2432 }
2433 else
2434 WARN(("pfnGetTopology failed Status(0x%x)", Status));
2435 }
2436 else
2437 WARN(("vboxVidPnCommitSourceMode failed Status(0x%x)", Status));
2438 /* release */
2439 pCurVidPnSourceModeSetInterface->pfnReleaseModeInfo(hCurVidPnSourceModeSet, pPinnedVidPnSourceModeInfo);
2440 }
2441 else if (Status == STATUS_GRAPHICS_MODE_NOT_PINNED)
2442 {
2443 Status = vboxVidPnCommitSourceMode(pDevExt, NULL, pAllocation, VidPnSourceId, paSources);
2444 AssertNtStatusSuccess(Status);
2445 }
2446 else
2447 WARN(("pfnAcquirePinnedModeInfo failed Status(0x%x)", Status));
2448
2449 pVidPnInterface->pfnReleaseSourceModeSet(hDesiredVidPn, hCurVidPnSourceModeSet);
2450 }
2451 else
2452 {
2453 WARN(("pfnAcquireSourceModeSet failed Status(0x%x)", Status));
2454 }
2455
2456 return Status;
2457}
2458
2459NTSTATUS VBoxVidPnCommitAll(PVBOXMP_DEVEXT pDevExt, const D3DKMDT_HVIDPN hDesiredVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface,
2460 PVBOXWDDM_ALLOCATION pAllocation,
2461 VBOXWDDM_SOURCE *paSources, VBOXWDDM_TARGET *paTargets)
2462{
2463 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
2464 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
2465 NTSTATUS Status = pVidPnInterface->pfnGetTopology(hDesiredVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
2466 if (!NT_SUCCESS(Status))
2467 {
2468 WARN(("pfnGetTopology failed Status 0x%x", Status));
2469 return Status;
2470 }
2471
2472 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
2473 {
2474 PVBOXWDDM_TARGET pTarget = &paTargets[i];
2475 pTarget->Size.cx = 0;
2476 pTarget->Size.cy = 0;
2477 pTarget->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_ALL;
2478
2479 if (pTarget->VidPnSourceId == D3DDDI_ID_UNINITIALIZED)
2480 continue;
2481
2482 Assert(pTarget->VidPnSourceId < (D3DDDI_VIDEO_PRESENT_SOURCE_ID)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
2483
2484 VBOXWDDM_SOURCE *pSource = &paSources[pTarget->VidPnSourceId];
2485 VBoxVidPnAllocDataInit(&pSource->AllocData, pTarget->VidPnSourceId);
2486 pSource->u8SyncState &= ~VBOXWDDM_HGSYNC_F_SYNCED_ALL;
2487 }
2488
2489 VBoxVidPnStCleanup(paSources, paTargets, VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
2490
2491 VBOXVIDPN_PATH_ITER PathIter;
2492 const D3DKMDT_VIDPN_PRESENT_PATH *pPath;
2493 VBoxVidPnPathIterInit(&PathIter, hVidPnTopology, pVidPnTopologyInterface);
2494 while ((pPath = VBoxVidPnPathIterNext(&PathIter)) != NULL)
2495 {
2496 Status = VBoxVidPnCommitSourceModeForSrcId(pDevExt, hDesiredVidPn, pVidPnInterface, pAllocation,
2497 pPath->VidPnSourceId, paSources, paTargets, FALSE);
2498 if (Status != STATUS_SUCCESS)
2499 {
2500 WARN(("VBoxVidPnCommitSourceModeForSrcId failed Status(0x%x)", Status));
2501 break;
2502 }
2503 }
2504
2505 VBoxVidPnPathIterTerm(&PathIter);
2506
2507 if (!NT_SUCCESS(Status))
2508 {
2509 WARN((""));
2510 return Status;
2511 }
2512
2513 Status = VBoxVidPnPathIterStatus(&PathIter);
2514 if (!NT_SUCCESS(Status))
2515 {
2516 WARN(("VBoxVidPnPathIterStatus failed Status 0x%x", Status));
2517 return Status;
2518 }
2519
2520 return STATUS_SUCCESS;
2521}
2522
2523#define VBOXVIDPNDUMP_STRCASE(_t) \
2524 case _t: return #_t;
2525#define VBOXVIDPNDUMP_STRCASE_UNKNOWN() \
2526 default: Assert(0); return "Unknown";
2527
2528#define VBOXVIDPNDUMP_STRFLAGS(_v, _t) \
2529 if ((_v)._t return #_t;
2530
2531const char* vboxVidPnDumpStrImportance(D3DKMDT_VIDPN_PRESENT_PATH_IMPORTANCE ImportanceOrdinal)
2532{
2533 switch (ImportanceOrdinal)
2534 {
2535 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPI_UNINITIALIZED);
2536 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPI_PRIMARY);
2537 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPI_SECONDARY);
2538 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPI_TERTIARY);
2539 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPI_QUATERNARY);
2540 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPI_QUINARY);
2541 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPI_SENARY);
2542 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPI_SEPTENARY);
2543 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPI_OCTONARY);
2544 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPI_NONARY);
2545 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPI_DENARY);
2546 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2547 }
2548}
2549
2550const char* vboxVidPnDumpStrScaling(D3DKMDT_VIDPN_PRESENT_PATH_SCALING Scaling)
2551{
2552 switch (Scaling)
2553 {
2554 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPS_UNINITIALIZED);
2555 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPS_IDENTITY);
2556 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPS_CENTERED);
2557 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPS_STRETCHED);
2558 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPS_UNPINNED);
2559 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPS_NOTSPECIFIED);
2560 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2561 }
2562}
2563
2564const char* vboxVidPnDumpStrRotation(D3DKMDT_VIDPN_PRESENT_PATH_ROTATION Rotation)
2565{
2566 switch (Rotation)
2567 {
2568 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPR_UNINITIALIZED);
2569 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPR_IDENTITY);
2570 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPR_ROTATE90);
2571 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPR_ROTATE180);
2572 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPR_ROTATE270);
2573 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPR_UNPINNED);
2574 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPR_NOTSPECIFIED);
2575 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2576 }
2577}
2578
2579const char* vboxVidPnDumpStrColorBasis(const D3DKMDT_COLOR_BASIS ColorBasis)
2580{
2581 switch (ColorBasis)
2582 {
2583 VBOXVIDPNDUMP_STRCASE(D3DKMDT_CB_UNINITIALIZED);
2584 VBOXVIDPNDUMP_STRCASE(D3DKMDT_CB_INTENSITY);
2585 VBOXVIDPNDUMP_STRCASE(D3DKMDT_CB_SRGB);
2586 VBOXVIDPNDUMP_STRCASE(D3DKMDT_CB_SCRGB);
2587 VBOXVIDPNDUMP_STRCASE(D3DKMDT_CB_YCBCR);
2588 VBOXVIDPNDUMP_STRCASE(D3DKMDT_CB_YPBPR);
2589 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2590 }
2591}
2592
2593const char * vboxVidPnDumpStrMonCapabilitiesOrigin(D3DKMDT_MONITOR_CAPABILITIES_ORIGIN enmOrigin)
2594{
2595 switch (enmOrigin)
2596 {
2597 VBOXVIDPNDUMP_STRCASE(D3DKMDT_MCO_UNINITIALIZED);
2598 VBOXVIDPNDUMP_STRCASE(D3DKMDT_MCO_DEFAULTMONITORPROFILE);
2599 VBOXVIDPNDUMP_STRCASE(D3DKMDT_MCO_MONITORDESCRIPTOR);
2600 VBOXVIDPNDUMP_STRCASE(D3DKMDT_MCO_MONITORDESCRIPTOR_REGISTRYOVERRIDE);
2601 VBOXVIDPNDUMP_STRCASE(D3DKMDT_MCO_SPECIFICCAP_REGISTRYOVERRIDE);
2602 VBOXVIDPNDUMP_STRCASE(D3DKMDT_MCO_DRIVER);
2603 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2604 }
2605}
2606
2607const char* vboxVidPnDumpStrPvam(D3DKMDT_PIXEL_VALUE_ACCESS_MODE PixelValueAccessMode)
2608{
2609 switch (PixelValueAccessMode)
2610 {
2611 VBOXVIDPNDUMP_STRCASE(D3DKMDT_PVAM_UNINITIALIZED);
2612 VBOXVIDPNDUMP_STRCASE(D3DKMDT_PVAM_DIRECT);
2613 VBOXVIDPNDUMP_STRCASE(D3DKMDT_PVAM_PRESETPALETTE);
2614 VBOXVIDPNDUMP_STRCASE(D3DKMDT_PVAM_SETTABLEPALETTE);
2615 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2616 }
2617}
2618
2619
2620
2621const char* vboxVidPnDumpStrContent(D3DKMDT_VIDPN_PRESENT_PATH_CONTENT Content)
2622{
2623 switch (Content)
2624 {
2625 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPC_UNINITIALIZED);
2626 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPC_GRAPHICS);
2627 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPC_VIDEO);
2628 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPC_NOTSPECIFIED);
2629 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2630 }
2631}
2632
2633const char* vboxVidPnDumpStrCopyProtectionType(D3DKMDT_VIDPN_PRESENT_PATH_COPYPROTECTION_TYPE CopyProtectionType)
2634{
2635 switch (CopyProtectionType)
2636 {
2637 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPMT_UNINITIALIZED);
2638 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPMT_NOPROTECTION);
2639 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPMT_MACROVISION_APSTRIGGER);
2640 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VPPMT_MACROVISION_FULLSUPPORT);
2641 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2642 }
2643}
2644
2645const char* vboxVidPnDumpStrGammaRampType(D3DDDI_GAMMARAMP_TYPE Type)
2646{
2647 switch (Type)
2648 {
2649 VBOXVIDPNDUMP_STRCASE(D3DDDI_GAMMARAMP_UNINITIALIZED);
2650 VBOXVIDPNDUMP_STRCASE(D3DDDI_GAMMARAMP_DEFAULT);
2651 VBOXVIDPNDUMP_STRCASE(D3DDDI_GAMMARAMP_RGB256x3x16);
2652 VBOXVIDPNDUMP_STRCASE(D3DDDI_GAMMARAMP_DXGI_1);
2653 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2654 }
2655}
2656
2657const char* vboxVidPnDumpStrSourceModeType(D3DKMDT_VIDPN_SOURCE_MODE_TYPE Type)
2658{
2659 switch (Type)
2660 {
2661 VBOXVIDPNDUMP_STRCASE(D3DKMDT_RMT_UNINITIALIZED);
2662 VBOXVIDPNDUMP_STRCASE(D3DKMDT_RMT_GRAPHICS);
2663 VBOXVIDPNDUMP_STRCASE(D3DKMDT_RMT_TEXT);
2664 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2665 }
2666}
2667
2668const char* vboxVidPnDumpStrScanLineOrdering(D3DDDI_VIDEO_SIGNAL_SCANLINE_ORDERING ScanLineOrdering)
2669{
2670 switch (ScanLineOrdering)
2671 {
2672 VBOXVIDPNDUMP_STRCASE(D3DDDI_VSSLO_UNINITIALIZED);
2673 VBOXVIDPNDUMP_STRCASE(D3DDDI_VSSLO_PROGRESSIVE);
2674 VBOXVIDPNDUMP_STRCASE(D3DDDI_VSSLO_INTERLACED_UPPERFIELDFIRST);
2675 VBOXVIDPNDUMP_STRCASE(D3DDDI_VSSLO_INTERLACED_LOWERFIELDFIRST);
2676 VBOXVIDPNDUMP_STRCASE(D3DDDI_VSSLO_OTHER);
2677 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2678 }
2679}
2680
2681const char* vboxVidPnDumpStrCFMPivotType(D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE EnumPivotType)
2682{
2683 switch (EnumPivotType)
2684 {
2685 VBOXVIDPNDUMP_STRCASE(D3DKMDT_EPT_UNINITIALIZED);
2686 VBOXVIDPNDUMP_STRCASE(D3DKMDT_EPT_VIDPNSOURCE);
2687 VBOXVIDPNDUMP_STRCASE(D3DKMDT_EPT_VIDPNTARGET);
2688 VBOXVIDPNDUMP_STRCASE(D3DKMDT_EPT_SCALING);
2689 VBOXVIDPNDUMP_STRCASE(D3DKMDT_EPT_ROTATION);
2690 VBOXVIDPNDUMP_STRCASE(D3DKMDT_EPT_NOPIVOT);
2691 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2692 }
2693}
2694
2695const char* vboxVidPnDumpStrModePreference(D3DKMDT_MODE_PREFERENCE Preference)
2696{
2697 switch (Preference)
2698 {
2699 VBOXVIDPNDUMP_STRCASE(D3DKMDT_MP_UNINITIALIZED);
2700 VBOXVIDPNDUMP_STRCASE(D3DKMDT_MP_PREFERRED);
2701 VBOXVIDPNDUMP_STRCASE(D3DKMDT_MP_NOTPREFERRED);
2702 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2703 }
2704}
2705
2706const char* vboxVidPnDumpStrSignalStandard(D3DKMDT_VIDEO_SIGNAL_STANDARD VideoStandard)
2707{
2708 switch (VideoStandard)
2709 {
2710 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_UNINITIALIZED);
2711 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_VESA_DMT);
2712 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_VESA_GTF);
2713 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_VESA_CVT);
2714 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_IBM);
2715 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_APPLE);
2716 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_NTSC_M);
2717 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_NTSC_J);
2718 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_NTSC_443);
2719 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_PAL_B);
2720 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_PAL_B1);
2721 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_PAL_G);
2722 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_PAL_H);
2723 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_PAL_I);
2724 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_PAL_D);
2725 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_PAL_N);
2726 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_PAL_NC);
2727 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_SECAM_B);
2728 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_SECAM_D);
2729 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_SECAM_G);
2730 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_SECAM_H);
2731 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_SECAM_K);
2732 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_SECAM_K1);
2733 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_SECAM_L);
2734 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_SECAM_L1);
2735 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_EIA_861);
2736 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_EIA_861A);
2737 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_EIA_861B);
2738 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_PAL_K);
2739 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_PAL_K1);
2740 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_PAL_L);
2741 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_PAL_M);
2742 VBOXVIDPNDUMP_STRCASE(D3DKMDT_VSS_OTHER);
2743 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2744 }
2745}
2746
2747const char* vboxVidPnDumpStrPixFormat(D3DDDIFORMAT PixelFormat)
2748{
2749 switch (PixelFormat)
2750 {
2751 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_UNKNOWN);
2752 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_R8G8B8);
2753 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A8R8G8B8);
2754 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_X8R8G8B8);
2755 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_R5G6B5);
2756 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_X1R5G5B5);
2757 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A1R5G5B5);
2758 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A4R4G4B4);
2759 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_R3G3B2);
2760 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A8);
2761 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A8R3G3B2);
2762 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_X4R4G4B4);
2763 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A2B10G10R10);
2764 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A8B8G8R8);
2765 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_X8B8G8R8);
2766 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_G16R16);
2767 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A2R10G10B10);
2768 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A16B16G16R16);
2769 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A8P8);
2770 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_R32F);
2771 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_G32R32F);
2772 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A32B32G32R32F);
2773 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_CxV8U8);
2774 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A1);
2775 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_BINARYBUFFER);
2776 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_VERTEXDATA);
2777 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_INDEX16);
2778 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_INDEX32);
2779 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_Q16W16V16U16);
2780 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_MULTI2_ARGB8);
2781 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_R16F);
2782 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_G16R16F);
2783 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A16B16G16R16F);
2784 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_D32F_LOCKABLE);
2785 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_D24FS8);
2786 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_D32_LOCKABLE);
2787 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_S8_LOCKABLE);
2788 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_S1D15);
2789 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_S8D24);
2790 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_X8D24);
2791 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_X4S4D24);
2792 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_L16);
2793 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_UYVY);
2794 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_R8G8_B8G8);
2795 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_YUY2);
2796 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_G8R8_G8B8);
2797 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_DXT1);
2798 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_DXT2);
2799 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_DXT3);
2800 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_DXT4);
2801 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_DXT5);
2802 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_D16_LOCKABLE);
2803 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_D32);
2804 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_D15S1);
2805 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_D24S8);
2806 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_D24X8);
2807 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_D24X4S4);
2808 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_D16);
2809 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_P8);
2810 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_L8);
2811 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A8L8);
2812 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A4L4);
2813 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_V8U8);
2814 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_L6V5U5);
2815 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_X8L8V8U8);
2816 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_Q8W8V8U8);
2817 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_V16U16);
2818 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_W11V11U10);
2819 VBOXVIDPNDUMP_STRCASE(D3DDDIFMT_A2W10V10U10);
2820 VBOXVIDPNDUMP_STRCASE_UNKNOWN();
2821 }
2822}
2823
2824void vboxVidPnDumpCopyProtectoin(const char *pPrefix, const D3DKMDT_VIDPN_PRESENT_PATH_COPYPROTECTION *pCopyProtection, const char *pSuffix)
2825{
2826 LOGREL_EXACT(("%sType(%s), TODO%s", pPrefix,
2827 vboxVidPnDumpStrCopyProtectionType(pCopyProtection->CopyProtectionType), pSuffix));
2828}
2829
2830
2831void vboxVidPnDumpPathTransformation(const D3DKMDT_VIDPN_PRESENT_PATH_TRANSFORMATION *pContentTransformation)
2832{
2833 LOGREL_EXACT((" --Transformation: Scaling(%s), ScalingSupport(%d), Rotation(%s), RotationSupport(%d)--",
2834 vboxVidPnDumpStrScaling(pContentTransformation->Scaling), pContentTransformation->ScalingSupport,
2835 vboxVidPnDumpStrRotation(pContentTransformation->Rotation), pContentTransformation->RotationSupport));
2836}
2837
2838void vboxVidPnDumpRegion(const char *pPrefix, const D3DKMDT_2DREGION *pRegion, const char *pSuffix)
2839{
2840 LOGREL_EXACT(("%s%dX%d%s", pPrefix, pRegion->cx, pRegion->cy, pSuffix));
2841}
2842
2843void vboxVidPnDumpRational(const char *pPrefix, const D3DDDI_RATIONAL *pRational, const char *pSuffix)
2844{
2845 LOGREL_EXACT(("%s%d/%d=%d%s", pPrefix, pRational->Numerator, pRational->Denominator, pRational->Numerator/pRational->Denominator, pSuffix));
2846}
2847
2848void vboxVidPnDumpRanges(const char *pPrefix, const D3DKMDT_COLOR_COEFF_DYNAMIC_RANGES *pDynamicRanges, const char *pSuffix)
2849{
2850 LOGREL_EXACT(("%sFirstChannel(%d), SecondChannel(%d), ThirdChannel(%d), FourthChannel(%d)%s", pPrefix,
2851 pDynamicRanges->FirstChannel,
2852 pDynamicRanges->SecondChannel,
2853 pDynamicRanges->ThirdChannel,
2854 pDynamicRanges->FourthChannel,
2855 pSuffix));
2856}
2857
2858void vboxVidPnDumpGammaRamp(const char *pPrefix, const D3DKMDT_GAMMA_RAMP *pGammaRamp, const char *pSuffix)
2859{
2860 LOGREL_EXACT(("%sType(%s), DataSize(%d), TODO: dump the rest%s", pPrefix,
2861 vboxVidPnDumpStrGammaRampType(pGammaRamp->Type), pGammaRamp->DataSize,
2862 pSuffix));
2863}
2864
2865void VBoxVidPnDumpSourceMode(const char *pPrefix, const D3DKMDT_VIDPN_SOURCE_MODE* pVidPnSourceModeInfo, const char *pSuffix)
2866{
2867 LOGREL_EXACT(("%sType(%s), ", pPrefix, vboxVidPnDumpStrSourceModeType(pVidPnSourceModeInfo->Type)));
2868 vboxVidPnDumpRegion("surf(", &pVidPnSourceModeInfo->Format.Graphics.PrimSurfSize, "), ");
2869 vboxVidPnDumpRegion("vis(", &pVidPnSourceModeInfo->Format.Graphics.VisibleRegionSize, "), ");
2870 LOGREL_EXACT(("stride(%d), ", pVidPnSourceModeInfo->Format.Graphics.Stride));
2871 LOGREL_EXACT(("format(%s), ", vboxVidPnDumpStrPixFormat(pVidPnSourceModeInfo->Format.Graphics.PixelFormat)));
2872 LOGREL_EXACT(("clrBasis(%s), ", vboxVidPnDumpStrColorBasis(pVidPnSourceModeInfo->Format.Graphics.ColorBasis)));
2873 LOGREL_EXACT(("pvam(%s)%s", vboxVidPnDumpStrPvam(pVidPnSourceModeInfo->Format.Graphics.PixelValueAccessMode), pSuffix));
2874}
2875
2876void vboxVidPnDumpSignalInfo(const char *pPrefix, const D3DKMDT_VIDEO_SIGNAL_INFO *pVideoSignalInfo, const char *pSuffix)
2877{
2878 LOGREL_EXACT(("%sVStd(%s), ", pPrefix, vboxVidPnDumpStrSignalStandard(pVideoSignalInfo->VideoStandard)));
2879 vboxVidPnDumpRegion("totSize(", &pVideoSignalInfo->TotalSize, "), ");
2880 vboxVidPnDumpRegion("activeSize(", &pVideoSignalInfo->ActiveSize, "), ");
2881 vboxVidPnDumpRational("VSynch(", &pVideoSignalInfo->VSyncFreq, "), ");
2882 LOGREL_EXACT(("PixelRate(%d), ScanLineOrdering(%s)%s", pVideoSignalInfo->PixelRate, vboxVidPnDumpStrScanLineOrdering(pVideoSignalInfo->ScanLineOrdering), pSuffix));
2883}
2884
2885void VBoxVidPnDumpTargetMode(const char *pPrefix, const D3DKMDT_VIDPN_TARGET_MODE* CONST pVidPnTargetModeInfo, const char *pSuffix)
2886{
2887 LOGREL_EXACT(("%s", pPrefix));
2888 LOGREL_EXACT(("ID: %d, ", pVidPnTargetModeInfo->Id));
2889 vboxVidPnDumpSignalInfo("VSI: ", &pVidPnTargetModeInfo->VideoSignalInfo, ", ");
2890 LOGREL_EXACT(("Preference(%s)%s", vboxVidPnDumpStrModePreference(pVidPnTargetModeInfo->Preference), pSuffix));
2891}
2892
2893void VBoxVidPnDumpMonitorMode(const char *pPrefix, const D3DKMDT_MONITOR_SOURCE_MODE *pVidPnModeInfo, const char *pSuffix)
2894{
2895 LOGREL_EXACT(("%s", pPrefix));
2896
2897 LOGREL_EXACT(("ID: %d, ", pVidPnModeInfo->Id));
2898
2899 vboxVidPnDumpSignalInfo("VSI: ", &pVidPnModeInfo->VideoSignalInfo, ", ");
2900
2901 LOGREL_EXACT(("ColorBasis: %s, ", vboxVidPnDumpStrColorBasis(pVidPnModeInfo->ColorBasis)));
2902
2903 vboxVidPnDumpRanges("Ranges: ", &pVidPnModeInfo->ColorCoeffDynamicRanges, ", ");
2904
2905 LOGREL_EXACT(("MonCapOr: %s, ", vboxVidPnDumpStrMonCapabilitiesOrigin(pVidPnModeInfo->Origin)));
2906
2907 LOGREL_EXACT(("Preference(%s)%s", vboxVidPnDumpStrModePreference(pVidPnModeInfo->Preference), pSuffix));
2908}
2909
2910NTSTATUS VBoxVidPnDumpMonitorModeSet(const char *pPrefix, PVBOXMP_DEVEXT pDevExt, uint32_t u32Target, const char *pSuffix)
2911{
2912 LOGREL_EXACT(("%s Tgt[%d]\n", pPrefix, u32Target));
2913
2914 NTSTATUS Status;
2915 CONST DXGK_MONITOR_INTERFACE *pMonitorInterface;
2916 Status = pDevExt->u.primary.DxgkInterface.DxgkCbQueryMonitorInterface(pDevExt->u.primary.DxgkInterface.DeviceHandle, DXGK_MONITOR_INTERFACE_VERSION_V1, &pMonitorInterface);
2917 if (!NT_SUCCESS(Status))
2918 {
2919 WARN(("DxgkCbQueryMonitorInterface failed, Status()0x%x", Status));
2920 return Status;
2921 }
2922
2923 D3DKMDT_HMONITORSOURCEMODESET hVidPnModeSet;
2924 CONST DXGK_MONITORSOURCEMODESET_INTERFACE *pVidPnModeSetInterface;
2925
2926 Status = pMonitorInterface->pfnAcquireMonitorSourceModeSet(pDevExt->u.primary.DxgkInterface.DeviceHandle,
2927 u32Target,
2928 &hVidPnModeSet,
2929 &pVidPnModeSetInterface);
2930 if (!NT_SUCCESS(Status))
2931 {
2932 WARN(("DxgkCbQueryMonitorInterface failed, Status()0x%x", Status));
2933 return Status;
2934 }
2935
2936 VBOXVIDPN_MONITORMODE_ITER Iter;
2937 const D3DKMDT_MONITOR_SOURCE_MODE *pVidPnModeInfo;
2938
2939 VBoxVidPnMonitorModeIterInit(&Iter, hVidPnModeSet, pVidPnModeSetInterface);
2940
2941 while ((pVidPnModeInfo = VBoxVidPnMonitorModeIterNext(&Iter)) != NULL)
2942 {
2943 VBoxVidPnDumpMonitorMode("MonitorMode: ",pVidPnModeInfo, "\n");
2944 }
2945
2946 VBoxVidPnMonitorModeIterTerm(&Iter);
2947
2948 Status = VBoxVidPnMonitorModeIterStatus(&Iter);
2949 if (!NT_SUCCESS(Status))
2950 {
2951 WARN(("iter status failed %#x", Status));
2952 }
2953
2954 NTSTATUS rcNt2 = pMonitorInterface->pfnReleaseMonitorSourceModeSet(pDevExt->u.primary.DxgkInterface.DeviceHandle, hVidPnModeSet);
2955 if (!NT_SUCCESS(rcNt2))
2956 WARN(("pfnReleaseMonitorSourceModeSet failed rcNt2(0x%x)", rcNt2));
2957
2958 LOGREL_EXACT(("%s", pSuffix));
2959
2960 return Status;
2961}
2962
2963void vboxVidPnDumpPinnedSourceMode(const D3DKMDT_HVIDPN hVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface, D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
2964{
2965 D3DKMDT_HVIDPNSOURCEMODESET hCurVidPnSourceModeSet;
2966 const DXGK_VIDPNSOURCEMODESET_INTERFACE *pCurVidPnSourceModeSetInterface;
2967
2968 NTSTATUS Status = pVidPnInterface->pfnAcquireSourceModeSet(hVidPn,
2969 VidPnSourceId,
2970 &hCurVidPnSourceModeSet,
2971 &pCurVidPnSourceModeSetInterface);
2972 AssertNtStatusSuccess(Status);
2973 if (Status == STATUS_SUCCESS)
2974 {
2975 CONST D3DKMDT_VIDPN_SOURCE_MODE* pPinnedVidPnSourceModeInfo;
2976
2977 Status = pCurVidPnSourceModeSetInterface->pfnAcquirePinnedModeInfo(hCurVidPnSourceModeSet, &pPinnedVidPnSourceModeInfo);
2978 Assert(Status == STATUS_SUCCESS || Status == STATUS_GRAPHICS_MODE_NOT_PINNED);
2979 if (Status == STATUS_SUCCESS)
2980 {
2981 VBoxVidPnDumpSourceMode("Source Pinned: ", pPinnedVidPnSourceModeInfo, "\n");
2982 pCurVidPnSourceModeSetInterface->pfnReleaseModeInfo(hCurVidPnSourceModeSet, pPinnedVidPnSourceModeInfo);
2983 }
2984 else if (Status == STATUS_GRAPHICS_MODE_NOT_PINNED)
2985 {
2986 LOGREL_EXACT(("Source NOT Pinned\n"));
2987 }
2988 else
2989 {
2990 LOGREL_EXACT(("ERROR getting piined Source Mode(0x%x)\n", Status));
2991 }
2992 pVidPnInterface->pfnReleaseSourceModeSet(hVidPn, hCurVidPnSourceModeSet);
2993 }
2994 else
2995 {
2996 LOGREL_EXACT(("ERROR getting SourceModeSet(0x%x)\n", Status));
2997 }
2998}
2999
3000
3001DECLCALLBACK(BOOLEAN) vboxVidPnDumpSourceModeSetEnum(D3DKMDT_HVIDPNSOURCEMODESET hNewVidPnSourceModeSet,
3002 const DXGK_VIDPNSOURCEMODESET_INTERFACE *pVidPnSourceModeSetInterface,
3003 const D3DKMDT_VIDPN_SOURCE_MODE *pNewVidPnSourceModeInfo, PVOID pContext)
3004{
3005
3006 RT_NOREF(hNewVidPnSourceModeSet, pVidPnSourceModeSetInterface, pNewVidPnSourceModeInfo, pContext);
3007 VBoxVidPnDumpSourceMode("SourceMode: ", pNewVidPnSourceModeInfo, "\n");
3008 return TRUE;
3009}
3010
3011void vboxVidPnDumpSourceModeSet(PVBOXMP_DEVEXT pDevExt, const D3DKMDT_HVIDPN hVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface,
3012 D3DDDI_VIDEO_PRESENT_SOURCE_ID VidPnSourceId)
3013{
3014 RT_NOREF(pDevExt);
3015 LOGREL_EXACT(("\n >>>+++SourceMode Set for Source(%d)+++\n", VidPnSourceId));
3016 D3DKMDT_HVIDPNSOURCEMODESET hCurVidPnSourceModeSet;
3017 const DXGK_VIDPNSOURCEMODESET_INTERFACE *pCurVidPnSourceModeSetInterface;
3018
3019 NTSTATUS Status = pVidPnInterface->pfnAcquireSourceModeSet(hVidPn,
3020 VidPnSourceId,
3021 &hCurVidPnSourceModeSet,
3022 &pCurVidPnSourceModeSetInterface);
3023 AssertNtStatusSuccess(Status);
3024 if (Status == STATUS_SUCCESS)
3025 {
3026
3027 Status = vboxVidPnEnumSourceModes(hCurVidPnSourceModeSet, pCurVidPnSourceModeSetInterface,
3028 vboxVidPnDumpSourceModeSetEnum, NULL);
3029 AssertNtStatusSuccess(Status);
3030 if (Status != STATUS_SUCCESS)
3031 {
3032 LOGREL_EXACT(("ERROR enumerating Source Modes(0x%x)\n", Status));
3033 }
3034 pVidPnInterface->pfnReleaseSourceModeSet(hVidPn, hCurVidPnSourceModeSet);
3035 }
3036 else
3037 {
3038 LOGREL_EXACT(("ERROR getting SourceModeSet for Source(%d), Status(0x%x)\n", VidPnSourceId, Status));
3039 }
3040
3041 LOGREL_EXACT((" <<<+++End Of SourceMode Set for Source(%d)+++", VidPnSourceId));
3042}
3043
3044DECLCALLBACK(BOOLEAN) vboxVidPnDumpTargetModeSetEnum(D3DKMDT_HVIDPNTARGETMODESET hNewVidPnTargetModeSet,
3045 const DXGK_VIDPNTARGETMODESET_INTERFACE *pVidPnTargetModeSetInterface,
3046 const D3DKMDT_VIDPN_TARGET_MODE *pNewVidPnTargetModeInfo, PVOID pContext)
3047{
3048 RT_NOREF(hNewVidPnTargetModeSet, pVidPnTargetModeSetInterface, pNewVidPnTargetModeInfo, pContext);
3049 VBoxVidPnDumpTargetMode("TargetMode: ", pNewVidPnTargetModeInfo, "\n");
3050 return TRUE;
3051}
3052
3053void vboxVidPnDumpTargetModeSet(PVBOXMP_DEVEXT pDevExt, const D3DKMDT_HVIDPN hVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface,
3054 D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
3055{
3056 RT_NOREF(pDevExt);
3057 LOGREL_EXACT(("\n >>>---TargetMode Set for Target(%d)---\n", VidPnTargetId));
3058 D3DKMDT_HVIDPNTARGETMODESET hCurVidPnTargetModeSet;
3059 const DXGK_VIDPNTARGETMODESET_INTERFACE *pCurVidPnTargetModeSetInterface;
3060
3061 NTSTATUS Status = pVidPnInterface->pfnAcquireTargetModeSet(hVidPn,
3062 VidPnTargetId,
3063 &hCurVidPnTargetModeSet,
3064 &pCurVidPnTargetModeSetInterface);
3065 AssertNtStatusSuccess(Status);
3066 if (Status == STATUS_SUCCESS)
3067 {
3068
3069 Status = vboxVidPnEnumTargetModes(hCurVidPnTargetModeSet, pCurVidPnTargetModeSetInterface,
3070 vboxVidPnDumpTargetModeSetEnum, NULL);
3071 AssertNtStatusSuccess(Status);
3072 if (Status != STATUS_SUCCESS)
3073 {
3074 LOGREL_EXACT(("ERROR enumerating Target Modes(0x%x)\n", Status));
3075 }
3076 pVidPnInterface->pfnReleaseTargetModeSet(hVidPn, hCurVidPnTargetModeSet);
3077 }
3078 else
3079 {
3080 LOGREL_EXACT(("ERROR getting TargetModeSet for Target(%d), Status(0x%x)\n", VidPnTargetId, Status));
3081 }
3082
3083 LOGREL_EXACT((" <<<---End Of TargetMode Set for Target(%d)---", VidPnTargetId));
3084}
3085
3086
3087void vboxVidPnDumpPinnedTargetMode(const D3DKMDT_HVIDPN hVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
3088{
3089 D3DKMDT_HVIDPNTARGETMODESET hCurVidPnTargetModeSet;
3090 const DXGK_VIDPNTARGETMODESET_INTERFACE *pCurVidPnTargetModeSetInterface;
3091
3092 NTSTATUS Status = pVidPnInterface->pfnAcquireTargetModeSet(hVidPn,
3093 VidPnTargetId,
3094 &hCurVidPnTargetModeSet,
3095 &pCurVidPnTargetModeSetInterface);
3096 AssertNtStatusSuccess(Status);
3097 if (Status == STATUS_SUCCESS)
3098 {
3099 CONST D3DKMDT_VIDPN_TARGET_MODE* pPinnedVidPnTargetModeInfo;
3100
3101 Status = pCurVidPnTargetModeSetInterface->pfnAcquirePinnedModeInfo(hCurVidPnTargetModeSet, &pPinnedVidPnTargetModeInfo);
3102 Assert(Status == STATUS_SUCCESS || Status == STATUS_GRAPHICS_MODE_NOT_PINNED);
3103 if (Status == STATUS_SUCCESS)
3104 {
3105 VBoxVidPnDumpTargetMode("Target Pinned: ", pPinnedVidPnTargetModeInfo, "\n");
3106 pCurVidPnTargetModeSetInterface->pfnReleaseModeInfo(hCurVidPnTargetModeSet, pPinnedVidPnTargetModeInfo);
3107 }
3108 else if (Status == STATUS_GRAPHICS_MODE_NOT_PINNED)
3109 {
3110 LOGREL_EXACT(("Target NOT Pinned\n"));
3111 }
3112 else
3113 {
3114 LOGREL_EXACT(("ERROR getting piined Target Mode(0x%x)\n", Status));
3115 }
3116 pVidPnInterface->pfnReleaseTargetModeSet(hVidPn, hCurVidPnTargetModeSet);
3117 }
3118 else
3119 {
3120 LOGREL_EXACT(("ERROR getting TargetModeSet(0x%x)\n", Status));
3121 }
3122}
3123
3124void VBoxVidPnDumpCofuncModalityInfo(const char *pPrefix, D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE enmEnumPivotType, const DXGK_ENUM_PIVOT *pPivot, const char *pSuffix)
3125{
3126 LOGREL_EXACT(("%sPivotType(%s), SourceId(0x%x), TargetId(0x%x),%s", pPrefix, vboxVidPnDumpStrCFMPivotType(enmEnumPivotType),
3127 pPivot->VidPnSourceId, pPivot->VidPnTargetId, pSuffix));
3128}
3129
3130void vboxVidPnDumpCofuncModalityArg(const char *pPrefix, D3DKMDT_ENUMCOFUNCMODALITY_PIVOT_TYPE enmPivot, const DXGK_ENUM_PIVOT *pPivot, const char *pSuffix)
3131{
3132 LOGREL_EXACT(("%sPivotType(%s), SourceId(0x%x), TargetId(0x%x),%s", pPrefix, vboxVidPnDumpStrCFMPivotType(enmPivot),
3133 pPivot->VidPnSourceId, pPivot->VidPnTargetId, pSuffix));
3134}
3135
3136void vboxVidPnDumpPath(const D3DKMDT_HVIDPN hVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface, const D3DKMDT_VIDPN_PRESENT_PATH *pVidPnPresentPathInfo)
3137{
3138 LOGREL_EXACT((" >>**** Start Dump VidPn Path ****>>\n"));
3139 LOGREL_EXACT(("VidPnSourceId(%d), VidPnTargetId(%d)\n",
3140 pVidPnPresentPathInfo->VidPnSourceId, pVidPnPresentPathInfo->VidPnTargetId));
3141
3142 vboxVidPnDumpPinnedSourceMode(hVidPn, pVidPnInterface, pVidPnPresentPathInfo->VidPnSourceId);
3143 vboxVidPnDumpPinnedTargetMode(hVidPn, pVidPnInterface, pVidPnPresentPathInfo->VidPnTargetId);
3144
3145 vboxVidPnDumpPathTransformation(&pVidPnPresentPathInfo->ContentTransformation);
3146
3147 LOGREL_EXACT(("Importance(%s), TargetColorBasis(%s), Content(%s), ",
3148 vboxVidPnDumpStrImportance(pVidPnPresentPathInfo->ImportanceOrdinal),
3149 vboxVidPnDumpStrColorBasis(pVidPnPresentPathInfo->VidPnTargetColorBasis),
3150 vboxVidPnDumpStrContent(pVidPnPresentPathInfo->Content)));
3151 vboxVidPnDumpRegion("VFA_TL_O(", &pVidPnPresentPathInfo->VisibleFromActiveTLOffset, "), ");
3152 vboxVidPnDumpRegion("VFA_BR_O(", &pVidPnPresentPathInfo->VisibleFromActiveBROffset, "), ");
3153 vboxVidPnDumpRanges("CCDynamicRanges: ", &pVidPnPresentPathInfo->VidPnTargetColorCoeffDynamicRanges, "| ");
3154 vboxVidPnDumpCopyProtectoin("CProtection: ", &pVidPnPresentPathInfo->CopyProtection, "| ");
3155 vboxVidPnDumpGammaRamp("GammaRamp: ", &pVidPnPresentPathInfo->GammaRamp, "\n");
3156
3157 LOGREL_EXACT((" <<**** Stop Dump VidPn Path ****<<"));
3158}
3159
3160typedef struct VBOXVIDPNDUMPPATHENUM
3161{
3162 D3DKMDT_HVIDPN hVidPn;
3163 const DXGK_VIDPN_INTERFACE* pVidPnInterface;
3164} VBOXVIDPNDUMPPATHENUM, *PVBOXVIDPNDUMPPATHENUM;
3165
3166static DECLCALLBACK(BOOLEAN) vboxVidPnDumpPathEnum(D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology, const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface,
3167 const D3DKMDT_VIDPN_PRESENT_PATH *pVidPnPresentPathInfo, PVOID pContext)
3168{
3169 PVBOXVIDPNDUMPPATHENUM pData = (PVBOXVIDPNDUMPPATHENUM)pContext;
3170 vboxVidPnDumpPath(pData->hVidPn, pData->pVidPnInterface, pVidPnPresentPathInfo);
3171
3172 pVidPnTopologyInterface->pfnReleasePathInfo(hVidPnTopology, pVidPnPresentPathInfo);
3173 return TRUE;
3174}
3175
3176void vboxVidPnDumpVidPn(const char * pPrefix, PVBOXMP_DEVEXT pDevExt, D3DKMDT_HVIDPN hVidPn, const DXGK_VIDPN_INTERFACE* pVidPnInterface, const char * pSuffix)
3177{
3178 LOGREL_EXACT(("%s", pPrefix));
3179
3180 VBOXVIDPNDUMPPATHENUM CbData;
3181 CbData.hVidPn = hVidPn;
3182 CbData.pVidPnInterface = pVidPnInterface;
3183 D3DKMDT_HVIDPNTOPOLOGY hVidPnTopology;
3184 const DXGK_VIDPNTOPOLOGY_INTERFACE* pVidPnTopologyInterface;
3185 NTSTATUS Status = pVidPnInterface->pfnGetTopology(hVidPn, &hVidPnTopology, &pVidPnTopologyInterface);
3186 AssertNtStatusSuccess(Status);
3187 if (Status == STATUS_SUCCESS)
3188 {
3189 Status = vboxVidPnEnumPaths(hVidPnTopology, pVidPnTopologyInterface,
3190 vboxVidPnDumpPathEnum, &CbData);
3191 AssertNtStatusSuccess(Status);
3192 }
3193
3194 for (int i = 0; i < VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++i)
3195 {
3196 vboxVidPnDumpSourceModeSet(pDevExt, hVidPn, pVidPnInterface, (D3DDDI_VIDEO_PRESENT_SOURCE_ID)i);
3197 vboxVidPnDumpTargetModeSet(pDevExt, hVidPn, pVidPnInterface, (D3DDDI_VIDEO_PRESENT_TARGET_ID)i);
3198 }
3199
3200 LOGREL_EXACT(("%s", pSuffix));
3201}
Note: See TracBrowser for help on using the repository browser.

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