VirtualBox

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

Last change on this file was 98103, checked in by vboxsync, 17 months ago

Copyright year updates by scm.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use