VirtualBox

Ignore:
Timestamp:
Jul 22, 2014 7:36:45 PM (11 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
95166
Message:

wddm: autoresize enhancements

Location:
trunk
Files:
5 edited

Legend:

Unmodified
Added
Removed
  • trunk

  • trunk/src/VBox

  • trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPCommon.h

    r50900 r52136  
    3030
    3131/* Video modes related */
     32#ifdef VBOX_XPDM_MINIPORT
    3233void VBoxMPCmnInitCustomVideoModes(PVBOXMP_DEVEXT pExt);
    3334VIDEO_MODE_INFORMATION* VBoxMPCmnGetCustomVideoModeInfo(ULONG ulIndex);
    34 
    35 #ifdef VBOX_XPDM_MINIPORT
    3635VIDEO_MODE_INFORMATION* VBoxMPCmnGetVideoModeInfo(PVBOXMP_DEVEXT pExt, ULONG ulIndex);
    3736VIDEO_MODE_INFORMATION* VBoxMPXpdmCurrentVideoMode(PVBOXMP_DEVEXT pExt);
    3837ULONG VBoxMPXpdmGetVideoModesCount(PVBOXMP_DEVEXT pExt);
    3938void VBoxMPXpdmBuildVideoModesTable(PVBOXMP_DEVEXT pExt);
    40 #endif
    41 
    42 #ifdef VBOX_WDDM_MINIPORT
    43 PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateVideoModesInfoByMask(PVBOXMP_DEVEXT pExt, uint8_t *pScreenIdMask);
    44 void VBoxWddmInitVideoModes(PVBOXMP_DEVEXT pExt);
    45 NTSTATUS VBoxWddmGetModesForResolution(VIDEO_MODE_INFORMATION *pAllModes, uint32_t cAllModes, int iSearchPreferredMode,
    46                                        const D3DKMDT_2DREGION *pResolution, VIDEO_MODE_INFORMATION * pModes,
    47                                        uint32_t cModes, uint32_t *pcModes, int32_t *piPreferrableMode);
    48 PVBOXWDDM_VIDEOMODES_INFO VBoxWddmGetAllVideoModesInfos(PVBOXMP_DEVEXT pExt);
    49 PVBOXWDDM_VIDEOMODES_INFO VBoxWddmGetVideoModesInfo(PVBOXMP_DEVEXT pExt, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId);
    50 bool VBoxWddmFillMode(VIDEO_MODE_INFORMATION *pInfo, D3DDDIFORMAT enmFormat, ULONG w, ULONG h);
    51 bool VBoxWddmFillMode(VIDEO_MODE_INFORMATION *pInfo, D3DDDIFORMAT enmFormat, ULONG w, ULONG h);
    52 void VBoxWddmAdjustMode(PVBOXMP_DEVEXT pExt, PVBOXWDDM_ADJUSTVIDEOMODE pMode);
    53 void VBoxWddmAdjustModes(PVBOXMP_DEVEXT pExt, uint32_t cModes, PVBOXWDDM_ADJUSTVIDEOMODE aModes);
    5439#endif
    5540
  • trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPDevExt.h

    r51328 r52136  
    144144   VBOXVTLIST VhwaCmdList;
    145145#endif
    146    BOOL bNotifyDxDpc;
     146   BOOLEAN bNotifyDxDpc;
     147
     148   BOOLEAN fDisableTargetUpdate;
     149
     150
    147151
    148152#ifdef VBOX_VDMA_WITH_WATCHDOG
  • trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/common/VBoxMPVidModes.cpp

    r51943 r52136  
    874874}
    875875#endif /*VBOX_XPDM_MINIPORT*/
    876 
    877 #ifdef VBOX_WDDM_MINIPORT
    878 static VBOXWDDM_VIDEOMODES_INFO g_aVBoxVideoModeInfos[VBOX_VIDEO_MAX_SCREENS] = {0};
    879 static VBOXWDDM_VIDEOMODES_INFO g_VBoxVideoModeTmp;
    880 
    881 bool VBoxWddmFillMode(PVBOXMP_DEVEXT pExt, uint32_t iDisplay, VIDEO_MODE_INFORMATION *pInfo, D3DDDIFORMAT enmFormat, ULONG w, ULONG h)
    882 {
    883     switch (enmFormat)
    884     {
    885         case D3DDDIFMT_A8R8G8B8:
    886             if (!VBoxMPValidateVideoModeParamsGuest(pExt, iDisplay, w, h, 32))
    887             {
    888                 WARN(("unsupported mode info for format(%d)", enmFormat));
    889                 return false;
    890             }
    891             VBoxFillVidModeInfo(pInfo, w, h, 32, 0, 0);
    892             return true;
    893         case D3DDDIFMT_R8G8B8:
    894             if (!VBoxMPValidateVideoModeParamsGuest(pExt, iDisplay, w, h, 24))
    895             {
    896                 WARN(("unsupported mode info for format(%d)", enmFormat));
    897                 return false;
    898             }
    899             VBoxFillVidModeInfo(pInfo, w, h, 24, 0, 0);
    900             return true;
    901         case D3DDDIFMT_R5G6B5:
    902             if (!VBoxMPValidateVideoModeParamsGuest(pExt, iDisplay, w, h, 16))
    903             {
    904                 WARN(("unsupported mode info for format(%d)", enmFormat));
    905                 return false;
    906             }
    907             VBoxFillVidModeInfo(pInfo, w, h, 16, 0, 0);
    908             return true;
    909         case D3DDDIFMT_P8:
    910             if (!VBoxMPValidateVideoModeParamsGuest(pExt, iDisplay, w, h, 8))
    911             {
    912                 WARN(("unsupported mode info for format(%d)", enmFormat));
    913                 return false;
    914             }
    915             VBoxFillVidModeInfo(pInfo, w, h, 8, 0, 0);
    916             return true;
    917         default:
    918             WARN(("unsupported enmFormat(%d)", enmFormat));
    919             AssertBreakpoint();
    920             break;
    921     }
    922 
    923     return false;
    924 }
    925 
    926 static void
    927 VBoxWddmBuildResolutionTable(PVIDEO_MODE_INFORMATION pModesTable, size_t tableSize, int iPreferredMode,
    928                              SIZE *pResolutions, uint32_t * pcResolutions, int *piPreferredResolution)
    929 {
    930     uint32_t cResolutionsArray = *pcResolutions;
    931     uint32_t cResolutions = 0;
    932 
    933     *piPreferredResolution = -1;
    934     *pcResolutions = 0;
    935 
    936     for (uint32_t i=0; i<tableSize; ++i)
    937     {
    938         PVIDEO_MODE_INFORMATION pMode = &pModesTable[i];
    939         int iResolution = -1;
    940 
    941         for (uint32_t j=0; j<cResolutions; ++j)
    942         {
    943             if (pResolutions[j].cx == pMode->VisScreenWidth
    944                 && pResolutions[j].cy == pMode->VisScreenHeight)
    945             {
    946                 iResolution = j;
    947                 break;
    948             }
    949         }
    950 
    951         if (iResolution < 0)
    952         {
    953             if (cResolutions == cResolutionsArray)
    954             {
    955                 WARN(("table overflow!"));
    956                 break;
    957             }
    958 
    959             iResolution = cResolutions;
    960             pResolutions[cResolutions].cx = pMode->VisScreenWidth;
    961             pResolutions[cResolutions].cy = pMode->VisScreenHeight;
    962             ++cResolutions;
    963         }
    964 
    965         Assert(iResolution >= 0);
    966         if (i == iPreferredMode)
    967         {
    968             Assert(*piPreferredResolution == -1);
    969             *piPreferredResolution = iResolution;
    970         }
    971     }
    972 
    973     *pcResolutions = cResolutions;
    974     Assert(*piPreferredResolution >= 0);
    975 }
    976 
    977 static void VBoxWddmBuildResolutionTableForModes(PVBOXWDDM_VIDEOMODES_INFO pModes)
    978 {
    979     pModes->cResolutions = RT_ELEMENTS(pModes->aResolutions);
    980     VBoxWddmBuildResolutionTable(pModes->aModes, pModes->cModes, pModes->iPreferredMode,
    981             (SIZE*)((void*)pModes->aResolutions), &pModes->cResolutions, &pModes->iPreferredResolution);
    982     Assert(pModes->aResolutions[pModes->iPreferredResolution].cx == pModes->aModes[pModes->iPreferredMode].VisScreenWidth
    983             && pModes->aResolutions[pModes->iPreferredResolution].cy == pModes->aModes[pModes->iPreferredMode].VisScreenHeight);
    984     Assert(pModes->cModes >= pModes->cResolutions);
    985 }
    986 
    987 AssertCompile(sizeof (SIZE) == sizeof (D3DKMDT_2DREGION));
    988 AssertCompile(RT_OFFSETOF(SIZE, cx) == RT_OFFSETOF(D3DKMDT_2DREGION, cx));
    989 AssertCompile(RT_OFFSETOF(SIZE, cy) == RT_OFFSETOF(D3DKMDT_2DREGION, cy));
    990 static void
    991 VBoxWddmBuildVideoModesInfo(PVBOXMP_DEVEXT pExt, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId,
    992                             PVBOXWDDM_VIDEOMODES_INFO pModes, VIDEO_MODE_INFORMATION *paAddlModes,
    993                             UINT cAddlModes)
    994 {
    995     pModes->cResolutions = RT_ELEMENTS(pModes->aResolutions);
    996 
    997     /* Add default modes and ones read from registry. */
    998     pModes->cModes = VBoxMPFillModesTable(pExt, VidPnTargetId, pModes->aModes, RT_ELEMENTS(pModes->aModes), &pModes->iPreferredMode);
    999     Assert(pModes->cModes<=RT_ELEMENTS(pModes->aModes));
    1000 
    1001     if (!VBoxMPIsStartingUp(pExt, VidPnTargetId))
    1002     {
    1003         /* make sure we keep the current mode to avoid mode flickering */
    1004         PVBOXWDDM_ALLOC_DATA pAllocData = pExt->aSources[VidPnTargetId].pPrimaryAllocation ?
    1005                   &pExt->aSources[VidPnTargetId].pPrimaryAllocation->AllocData
    1006                 : &pExt->aSources[VidPnTargetId].AllocData;
    1007         if (pModes->cModes < RT_ELEMENTS(pModes->aModes))
    1008         {
    1009             /* VBox WDDM driver does not allow 24 modes since OS could choose the 24bit mode as default in that case,
    1010              * the pExt->aSources[iDisplay].AllocData.SurfDesc.bpp could be initially 24 though,
    1011              * i.e. when driver occurs the current mode on driver load via DxgkCbAcquirePostDisplayOwnership
    1012              * and until driver reports the supported modes
    1013              * This is true for Win8 Display-Only driver currently since DxgkCbAcquirePostDisplayOwnership is only used by it
    1014              *
    1015              * This is why we check the bpp to be supported here and add the current mode to the list only in that case */
    1016             if (VBoxMPIsSupportedBpp(pAllocData->SurfDesc.bpp))
    1017             {
    1018                 int foundIdx;
    1019                 VBoxFillVidModeInfo(&pModes->aModes[pModes->cModes], pAllocData->SurfDesc.width, pAllocData->SurfDesc.height, pAllocData->SurfDesc.bpp, 1/*index*/, 0);
    1020                 if ((foundIdx=VBoxMPFindVideoMode(pModes->aModes, pModes->cModes, &pModes->aModes[pModes->cModes]))>=0)
    1021                 {
    1022                     pModes->iPreferredMode = foundIdx;
    1023                 }
    1024                 else
    1025                 {
    1026                     pModes->iPreferredMode = pModes->cModes;
    1027                     ++pModes->cModes;
    1028                 }
    1029 
    1030 #ifdef VBOX_WITH_8BPP_MODES
    1031                 int bytesPerPixel=1;
    1032 #else
    1033                 int bytesPerPixel=2;
    1034 #endif
    1035                 for (; bytesPerPixel<=4; bytesPerPixel++)
    1036                 {
    1037                     int bpp = 8*bytesPerPixel;
    1038 
    1039                     if (bpp == pAllocData->SurfDesc.bpp)
    1040                         continue;
    1041 
    1042                     if (!VBoxMPValidateVideoModeParamsGuest(pExt, VidPnTargetId,
    1043                             pAllocData->SurfDesc.width, pAllocData->SurfDesc.height,
    1044                             bpp))
    1045                         continue;
    1046 
    1047                     if (pModes->cModes >= RT_ELEMENTS(pModes->aModes))
    1048                     {
    1049                         WARN(("ran out of video modes 2"));
    1050                         break;
    1051                     }
    1052 
    1053                     VBoxFillVidModeInfo(&pModes->aModes[pModes->cModes],
    1054                                             pAllocData->SurfDesc.width, pAllocData->SurfDesc.height,
    1055                                             bpp, pModes->cModes, 0);
    1056                     if (VBoxMPFindVideoMode(pModes->aModes, pModes->cModes, &pModes->aModes[pModes->cModes]) < 0)
    1057                     {
    1058                         ++pModes->cModes;
    1059                     }
    1060                 }
    1061             }
    1062         }
    1063         else
    1064         {
    1065             WARN(("ran out of video modes 1"));
    1066         }
    1067     }
    1068 
    1069     /* Check if there's a pending display change request for this adapter */
    1070     VIDEO_MODE_INFORMATION specialMode;
    1071     if (VBoxMPCheckPendingVideoMode(pExt, &specialMode) && (specialMode.ModeIndex==VidPnTargetId))
    1072     {
    1073         /*Minor hack, ModeIndex!=0 Means this mode has been validated already and not just read from registry */
    1074         specialMode.ModeIndex = 1;
    1075         memcpy(&g_CustomVideoModes[VidPnTargetId], &specialMode, sizeof(VIDEO_MODE_INFORMATION));
    1076 
    1077         /* Save mode to registry */
    1078         VBoxMPRegSaveModeInfo(pExt, VidPnTargetId, &specialMode);
    1079     }
    1080 
    1081     /* Validate the mode which has been read from registry */
    1082     if (!g_CustomVideoModes[VidPnTargetId].ModeIndex)
    1083     {
    1084         uint32_t xres, yres, bpp;
    1085 
    1086         xres = g_CustomVideoModes[VidPnTargetId].VisScreenWidth;
    1087         yres = g_CustomVideoModes[VidPnTargetId].VisScreenHeight;
    1088         bpp = g_CustomVideoModes[VidPnTargetId].BitsPerPlane;
    1089 
    1090         if (VBoxMPValidateVideoModeParams(pExt, VidPnTargetId, xres, yres, bpp))
    1091         {
    1092             VBoxFillVidModeInfo(&g_CustomVideoModes[VidPnTargetId], xres, yres, bpp, 1/*index*/, 0);
    1093             Assert(g_CustomVideoModes[VidPnTargetId].ModeIndex == 1);
    1094         }
    1095     }
    1096 
    1097     /* Add custom mode to the table */
    1098     if (g_CustomVideoModes[VidPnTargetId].ModeIndex)
    1099     {
    1100         if (RT_ELEMENTS(pModes->aModes) > pModes->cModes)
    1101         {
    1102             g_CustomVideoModes[VidPnTargetId].ModeIndex = pModes->cModes;
    1103             pModes->aModes[pModes->cModes] = g_CustomVideoModes[VidPnTargetId];
    1104 
    1105             /* Check if we already have this mode in the table */
    1106             int foundIdx;
    1107             if ((foundIdx=VBoxMPFindVideoMode(pModes->aModes, pModes->cModes, &pModes->aModes[pModes->cModes]))>=0)
    1108             {
    1109                 pModes->iPreferredMode = foundIdx;
    1110             }
    1111             else
    1112             {
    1113                 pModes->iPreferredMode = pModes->cModes;
    1114                 ++pModes->cModes;
    1115             }
    1116 
    1117             /* Add other bpp modes for this custom resolution */
    1118 #ifdef VBOX_WITH_8BPP_MODES
    1119         UINT bpp=8;
    1120 #else
    1121         UINT bpp=16;
    1122 #endif
    1123             for (; bpp<=32; bpp+=8)
    1124             {
    1125                 if (RT_ELEMENTS(pModes->aModes) == pModes->cModes)
    1126                 {
    1127                     WARN(("table full, can't add other bpp for specail mode!"));
    1128 #ifdef DEBUG_misha
    1129                     /* this is definitely something we do not expect */
    1130                     AssertFailed();
    1131 #endif
    1132                     break;
    1133                 }
    1134 
    1135                 AssertRelease(RT_ELEMENTS(pModes->aModes) > pModes->cModes); /* if not - the driver state is screwed up, @todo: better do KeBugCheckEx here */
    1136 
    1137                 if (pModes->aModes[pModes->iPreferredMode].BitsPerPlane == bpp)
    1138                     continue;
    1139 
    1140                 if (!VBoxMPValidateVideoModeParamsGuest(pExt, VidPnTargetId,
    1141                         pModes->aModes[pModes->iPreferredMode].VisScreenWidth,
    1142                         pModes->aModes[pModes->iPreferredMode].VisScreenHeight,
    1143                         bpp))
    1144                     continue;
    1145 
    1146                 VBoxFillVidModeInfo(&pModes->aModes[pModes->cModes],
    1147                                         pModes->aModes[pModes->iPreferredMode].VisScreenWidth,
    1148                                         pModes->aModes[pModes->iPreferredMode].VisScreenHeight,
    1149                                         bpp, pModes->cModes, 0);
    1150                 if (VBoxMPFindVideoMode(pModes->aModes, pModes->cModes, &pModes->aModes[pModes->cModes]) < 0)
    1151                 {
    1152                     ++pModes->cModes;
    1153                 }
    1154             }
    1155         }
    1156         else
    1157         {
    1158             AssertRelease(RT_ELEMENTS(pModes->aModes) == pModes->cModes); /* if not - the driver state is screwed up, @todo: better do KeBugCheckEx here */
    1159             WARN(("table full, can't add video mode for a host request!"));
    1160 #ifdef DEBUG_misha
    1161             /* this is definitely something we do not expect */
    1162             AssertFailed();
    1163 #endif
    1164         }
    1165     }
    1166 
    1167     /* Check and Add additional modes passed in paAddlModes */
    1168     for (UINT i=0; i<cAddlModes; ++i)
    1169     {
    1170         if (RT_ELEMENTS(pModes->aModes) == pModes->cModes)
    1171         {
    1172            WARN(("table full, can't add addl modes!"));
    1173 #ifdef DEBUG_misha
    1174             /* this is definitely something we do not expect */
    1175             AssertFailed();
    1176 #endif
    1177            break;
    1178         }
    1179 
    1180         AssertRelease(RT_ELEMENTS(pModes->aModes) > pModes->cModes); /* if not - the driver state is screwed up, @todo: better do KeBugCheckEx here */
    1181 
    1182         if (!VBoxCommonFromDeviceExt(pExt)->fAnyX)
    1183         {
    1184             paAddlModes[i].VisScreenWidth &= 0xFFF8;
    1185         }
    1186 
    1187         if (VBoxLikesVideoMode(VidPnTargetId, paAddlModes[i].VisScreenWidth, paAddlModes[i].VisScreenHeight, paAddlModes[i].BitsPerPlane))
    1188         {
    1189             int foundIdx;
    1190             if ((foundIdx=VBoxMPFindVideoMode(pModes->aModes, pModes->cModes, &paAddlModes[i]))>=0)
    1191             {
    1192                 pModes->iPreferredMode = foundIdx;
    1193             }
    1194             else
    1195             {
    1196                 memcpy(&pModes->aModes[pModes->cModes], &paAddlModes[i], sizeof(VIDEO_MODE_INFORMATION));
    1197                 pModes->aModes[pModes->cModes].ModeIndex = pModes->cModes;
    1198                 ++pModes->cModes;
    1199             }
    1200         }
    1201     }
    1202 
    1203     /* Build resolution table */
    1204     VBoxWddmBuildResolutionTableForModes(pModes);
    1205 }
    1206 
    1207 static void VBoxWddmInitVideoMode(PVBOXMP_DEVEXT pExt, int i)
    1208 {
    1209     VBoxWddmBuildVideoModesInfo(pExt, (D3DDDI_VIDEO_PRESENT_TARGET_ID)i, &g_aVBoxVideoModeInfos[i], NULL, 0);
    1210 }
    1211 
    1212 void VBoxWddmInitVideoModes(PVBOXMP_DEVEXT pExt)
    1213 {
    1214     for (int i = 0; i < VBoxCommonFromDeviceExt(pExt)->cDisplays; ++i)
    1215     {
    1216         VBoxWddmInitVideoMode(pExt, i);
    1217     }
    1218 }
    1219 
    1220 static NTSTATUS vboxWddmChildStatusReportPerform(PVBOXMP_DEVEXT pDevExt, PVBOXVDMA_CHILD_STATUS pChildStatus, D3DDDI_VIDEO_PRESENT_TARGET_ID iChild)
    1221 {
    1222     DXGK_CHILD_STATUS DdiChildStatus;
    1223 
    1224     Assert(iChild < UINT32_MAX/2);
    1225     Assert(iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
    1226 
    1227     PVBOXWDDM_TARGET pTarget = &pDevExt->aTargets[iChild];
    1228 
    1229     if ((pChildStatus->fFlags & VBOXVDMA_CHILD_STATUS_F_DISCONNECTED)
    1230             && pTarget->fConnected)
    1231     {
    1232         /* report disconnected */
    1233         memset(&DdiChildStatus, 0, sizeof (DdiChildStatus));
    1234         DdiChildStatus.Type = StatusConnection;
    1235         DdiChildStatus.ChildUid = iChild;
    1236         DdiChildStatus.HotPlug.Connected = FALSE;
    1237 
    1238         LOG(("Reporting DISCONNECT to child %d", DdiChildStatus.ChildUid));
    1239 
    1240         NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbIndicateChildStatus(pDevExt->u.primary.DxgkInterface.DeviceHandle, &DdiChildStatus);
    1241         if (!NT_SUCCESS(Status))
    1242         {
    1243             WARN(("DxgkCbIndicateChildStatus failed with Status (0x%x)", Status));
    1244             return Status;
    1245         }
    1246         pTarget->fConnected = FALSE;
    1247     }
    1248 
    1249     if ((pChildStatus->fFlags & VBOXVDMA_CHILD_STATUS_F_CONNECTED)
    1250             && !pTarget->fConnected)
    1251     {
    1252         /* report disconnected */
    1253         memset(&DdiChildStatus, 0, sizeof (DdiChildStatus));
    1254         DdiChildStatus.Type = StatusConnection;
    1255         DdiChildStatus.ChildUid = iChild;
    1256         DdiChildStatus.HotPlug.Connected = TRUE;
    1257 
    1258         LOG(("Reporting CONNECT to child %d", DdiChildStatus.ChildUid));
    1259 
    1260         NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbIndicateChildStatus(pDevExt->u.primary.DxgkInterface.DeviceHandle, &DdiChildStatus);
    1261         if (!NT_SUCCESS(Status))
    1262         {
    1263             WARN(("DxgkCbIndicateChildStatus failed with Status (0x%x)", Status));
    1264             return Status;
    1265         }
    1266         pTarget->fConnected = TRUE;
    1267     }
    1268 
    1269     if (pChildStatus->fFlags & VBOXVDMA_CHILD_STATUS_F_ROTATED)
    1270     {
    1271         /* report disconnected */
    1272         memset(&DdiChildStatus, 0, sizeof (DdiChildStatus));
    1273         DdiChildStatus.Type = StatusRotation;
    1274         DdiChildStatus.ChildUid = iChild;
    1275         DdiChildStatus.Rotation.Angle = pChildStatus->u8RotationAngle;
    1276 
    1277         LOG(("Reporting ROTATED to child %d", DdiChildStatus.ChildUid));
    1278 
    1279         NTSTATUS Status = pDevExt->u.primary.DxgkInterface.DxgkCbIndicateChildStatus(pDevExt->u.primary.DxgkInterface.DeviceHandle, &DdiChildStatus);
    1280         if (!NT_SUCCESS(Status))
    1281         {
    1282             WARN(("DxgkCbIndicateChildStatus failed with Status (0x%x)", Status));
    1283             return Status;
    1284         }
    1285     }
    1286 
    1287     return STATUS_SUCCESS;
    1288 }
    1289 
    1290 static NTSTATUS vboxWddmChildStatusHandleRequest(PVBOXMP_DEVEXT pDevExt, VBOXVDMACMD_CHILD_STATUS_IRQ *pBody)
    1291 {
    1292     NTSTATUS Status = STATUS_SUCCESS;
    1293 
    1294     for (UINT i = 0; i < pBody->cInfos; ++i)
    1295     {
    1296         PVBOXVDMA_CHILD_STATUS pInfo = &pBody->aInfos[i];
    1297         if (pBody->fFlags & VBOXVDMACMD_CHILD_STATUS_IRQ_F_APPLY_TO_ALL)
    1298         {
    1299             for (D3DDDI_VIDEO_PRESENT_TARGET_ID iChild = 0; iChild < (UINT)VBoxCommonFromDeviceExt(pDevExt)->cDisplays; ++iChild)
    1300             {
    1301                 Status = vboxWddmChildStatusReportPerform(pDevExt, pInfo, iChild);
    1302                 if (!NT_SUCCESS(Status))
    1303                 {
    1304                     WARN(("vboxWddmChildStatusReportPerform failed with Status (0x%x)", Status));
    1305                     break;
    1306                 }
    1307             }
    1308         }
    1309         else
    1310         {
    1311             Status = vboxWddmChildStatusReportPerform(pDevExt, pInfo, pInfo->iChild);
    1312             if (!NT_SUCCESS(Status))
    1313             {
    1314                 WARN(("vboxWddmChildStatusReportPerform failed with Status (0x%x)", Status));
    1315                 break;
    1316             }
    1317         }
    1318     }
    1319 
    1320     return Status;
    1321 }
    1322 
    1323 #ifdef VBOX_WDDM_MONITOR_REPLUG_IRQ
    1324 typedef struct VBOXWDDMCHILDSTATUSCB
    1325 {
    1326     PVBOXVDMACBUF_DR pDr;
    1327     PKEVENT pEvent;
    1328 } VBOXWDDMCHILDSTATUSCB, *PVBOXWDDMCHILDSTATUSCB;
    1329 
    1330 static DECLCALLBACK(VOID) vboxWddmChildStatusReportCompletion(PVBOXMP_DEVEXT pDevExt, PVBOXVDMADDI_CMD pCmd, PVOID pvContext)
    1331 {
    1332     /* we should be called from our DPC routine */
    1333     Assert(KeGetCurrentIrql() == DISPATCH_LEVEL);
    1334 
    1335     PVBOXWDDMCHILDSTATUSCB pCtx = (PVBOXWDDMCHILDSTATUSCB)pvContext;
    1336     PVBOXVDMACBUF_DR pDr = pCtx->pDr;
    1337     PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
    1338     VBOXVDMACMD_CHILD_STATUS_IRQ *pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_CHILD_STATUS_IRQ);
    1339 
    1340     vboxWddmChildStatusHandleRequest(pDevExt, pBody);
    1341 
    1342     vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
    1343 
    1344     if (pCtx->pEvent)
    1345     {
    1346         KeSetEvent(pCtx->pEvent, 0, FALSE);
    1347     }
    1348 }
    1349 #endif
    1350 
    1351 static NTSTATUS vboxWddmChildStatusReportReconnected(PVBOXMP_DEVEXT pDevExt, D3DDDI_VIDEO_PRESENT_TARGET_ID idTarget)
    1352 {
    1353 #ifdef VBOX_WDDM_MONITOR_REPLUG_IRQ
    1354     NTSTATUS Status = STATUS_UNSUCCESSFUL;
    1355     UINT cbCmd = VBOXVDMACMD_SIZE_FROMBODYSIZE(sizeof (VBOXVDMACMD_CHILD_STATUS_IRQ));
    1356 
    1357     PVBOXVDMACBUF_DR pDr = vboxVdmaCBufDrCreate(&pDevExt->u.primary.Vdma, cbCmd);
    1358     if (pDr)
    1359     {
    1360         // vboxVdmaCBufDrCreate zero initializes the pDr
    1361         /* the command data follows the descriptor */
    1362         pDr->fFlags = VBOXVDMACBUF_FLAG_BUF_FOLLOWS_DR;
    1363         pDr->cbBuf = cbCmd;
    1364         pDr->rc = VERR_NOT_IMPLEMENTED;
    1365 
    1366         PVBOXVDMACMD pHdr = VBOXVDMACBUF_DR_TAIL(pDr, VBOXVDMACMD);
    1367         pHdr->enmType = VBOXVDMACMD_TYPE_CHILD_STATUS_IRQ;
    1368         pHdr->u32CmdSpecific = 0;
    1369         PVBOXVDMACMD_CHILD_STATUS_IRQ pBody = VBOXVDMACMD_BODY(pHdr, VBOXVDMACMD_CHILD_STATUS_IRQ);
    1370         pBody->cInfos = 1;
    1371         if (idTarget == D3DDDI_ID_ALL)
    1372         {
    1373             pBody->fFlags |= VBOXVDMACMD_CHILD_STATUS_IRQ_F_APPLY_TO_ALL;
    1374         }
    1375         pBody->aInfos[0].iChild = idTarget;
    1376         pBody->aInfos[0].fFlags = VBOXVDMA_CHILD_STATUS_F_DISCONNECTED | VBOXVDMA_CHILD_STATUS_F_CONNECTED;
    1377         /* we're going to KeWaitForSingleObject */
    1378         Assert(KeGetCurrentIrql() < DISPATCH_LEVEL);
    1379 
    1380         PVBOXVDMADDI_CMD pDdiCmd = VBOXVDMADDI_CMD_FROM_BUF_DR(pDr);
    1381         VBOXWDDMCHILDSTATUSCB Ctx;
    1382         KEVENT Event;
    1383         KeInitializeEvent(&Event, NotificationEvent, FALSE);
    1384         Ctx.pDr = pDr;
    1385         Ctx.pEvent = &Event;
    1386         vboxVdmaDdiCmdInit(pDdiCmd, 0, 0, vboxWddmChildStatusReportCompletion, &Ctx);
    1387         /* mark command as submitted & invisible for the dx runtime since dx did not originate it */
    1388         vboxVdmaDdiCmdSubmittedNotDx(pDdiCmd);
    1389         int rc = vboxVdmaCBufDrSubmit(pDevExt, &pDevExt->u.primary.Vdma, pDr);
    1390         Assert(rc == VINF_SUCCESS);
    1391         if (RT_SUCCESS(rc))
    1392         {
    1393             Status = KeWaitForSingleObject(&Event, Executive, KernelMode, FALSE, NULL);
    1394             Assert(Status == STATUS_SUCCESS);
    1395             return STATUS_SUCCESS;
    1396         }
    1397 
    1398         Status = STATUS_UNSUCCESSFUL;
    1399 
    1400         vboxVdmaCBufDrFree(&pDevExt->u.primary.Vdma, pDr);
    1401     }
    1402     else
    1403     {
    1404         /* @todo: try flushing.. */
    1405         WARN(("vboxVdmaCBufDrCreate returned NULL"));
    1406         Status = STATUS_INSUFFICIENT_RESOURCES;
    1407     }
    1408 
    1409     return Status;
    1410 #else
    1411     VBOXVDMACMD_CHILD_STATUS_IRQ Body = {0};
    1412     Body.cInfos = 1;
    1413     if (idTarget == D3DDDI_ID_ALL)
    1414     {
    1415         Body.fFlags |= VBOXVDMACMD_CHILD_STATUS_IRQ_F_APPLY_TO_ALL;
    1416     }
    1417     Body.aInfos[0].iChild = idTarget;
    1418     Body.aInfos[0].fFlags = VBOXVDMA_CHILD_STATUS_F_DISCONNECTED | VBOXVDMA_CHILD_STATUS_F_CONNECTED;
    1419     Assert(KeGetCurrentIrql() <= DISPATCH_LEVEL);
    1420     return vboxWddmChildStatusHandleRequest(pDevExt, &Body);
    1421 #endif
    1422 }
    1423 
    1424 NTSTATUS vboxWddmChildStatusConnect(PVBOXMP_DEVEXT pDevExt, uint32_t iChild, BOOLEAN fConnect)
    1425 {
    1426 #ifdef VBOX_WDDM_MONITOR_REPLUG_IRQ
    1427 # error "port me!"
    1428 #else
    1429     Assert(iChild < (uint32_t)VBoxCommonFromDeviceExt(pDevExt)->cDisplays);
    1430     NTSTATUS Status = STATUS_SUCCESS;
    1431     VBOXVDMACMD_CHILD_STATUS_IRQ Body = {0};
    1432     Body.cInfos = 1;
    1433     Body.aInfos[0].iChild = iChild;
    1434     Body.aInfos[0].fFlags = fConnect ? VBOXVDMA_CHILD_STATUS_F_CONNECTED : VBOXVDMA_CHILD_STATUS_F_DISCONNECTED;
    1435     Assert(KeGetCurrentIrql() <= DISPATCH_LEVEL);
    1436     Status = vboxWddmChildStatusHandleRequest(pDevExt, &Body);
    1437     if (!NT_SUCCESS(Status))
    1438         WARN(("vboxWddmChildStatusHandleRequest failed Status 0x%x", Status));
    1439 
    1440     return Status;
    1441 #endif
    1442 }
    1443 
    1444 void VBoxWddmUpdateVideoMode(PVBOXMP_DEVEXT pExt, int i)
    1445 {
    1446     g_VBoxVideoModeTmp = g_aVBoxVideoModeInfos[i];
    1447 
    1448     Assert(g_aVBoxVideoModeInfos[i].cModes);
    1449 
    1450     VBoxWddmInitVideoMode(pExt, i);
    1451 
    1452     if (!memcmp(&g_VBoxVideoModeTmp, &g_aVBoxVideoModeInfos[i], sizeof (g_VBoxVideoModeTmp)))
    1453         return;
    1454 
    1455 #ifdef DEBUG_misha
    1456     LOGREL(("modes changed for target %d", i));
    1457 #else
    1458     LOG(("modes changed for target %d", i));
    1459 #endif
    1460     vboxWddmChildStatusReportReconnected(pExt, (D3DDDI_VIDEO_PRESENT_TARGET_ID)i);
    1461 }
    1462 
    1463 PVBOXWDDM_VIDEOMODES_INFO VBoxWddmUpdateVideoModesInfoByMask(PVBOXMP_DEVEXT pExt, uint8_t *pScreenIdMask)
    1464 {
    1465     for (int i = 0; i < VBoxCommonFromDeviceExt(pExt)->cDisplays; ++i)
    1466     {
    1467         if (!pScreenIdMask || ASMBitTest(pScreenIdMask, i))
    1468         {
    1469             VBoxWddmUpdateVideoMode(pExt, i);
    1470         }
    1471     }
    1472 
    1473     return g_aVBoxVideoModeInfos;
    1474 }
    1475 
    1476 void VBoxWddmAdjustMode(PVBOXMP_DEVEXT pExt, PVBOXWDDM_ADJUSTVIDEOMODE pMode)
    1477 {
    1478     pMode->fFlags = 0;
    1479 
    1480     if (pMode->Mode.Id >= (UINT)VBoxCommonFromDeviceExt(pExt)->cDisplays)
    1481     {
    1482         WARN(("invalid screen id (%d)", pMode->Mode.Id));
    1483         pMode->fFlags = VBOXWDDM_ADJUSTVIDEOMODE_F_INVALISCREENID;
    1484         return;
    1485     }
    1486 
    1487     /* @todo: this info should go from the target actually */
    1488     PVBOXWDDM_SOURCE pSource = &pExt->aSources[pMode->Mode.Id];
    1489 
    1490     UINT newWidth = pMode->Mode.Width;
    1491     UINT newHeight = pMode->Mode.Height;
    1492     UINT newBpp = pMode->Mode.BitsPerPixel;
    1493 
    1494     if (!VBoxMPValidateVideoModeParams(pExt, pMode->Mode.Id, newWidth, newHeight, newBpp))
    1495     {
    1496         PVBOXWDDM_SOURCE pSource = &pExt->aSources[pMode->Mode.Id];
    1497         pMode->fFlags |= VBOXWDDM_ADJUSTVIDEOMODE_F_UNSUPPORTED;
    1498     }
    1499 
    1500     if (pMode->Mode.Width != newWidth
    1501             || pMode->Mode.Height != newHeight
    1502             || pMode->Mode.BitsPerPixel != newBpp)
    1503     {
    1504         pMode->fFlags |= VBOXWDDM_ADJUSTVIDEOMODE_F_ADJUSTED;
    1505         pMode->Mode.Width = newWidth;
    1506         pMode->Mode.Height = newHeight;
    1507         pMode->Mode.BitsPerPixel = newBpp;
    1508     }
    1509 
    1510     if (pSource->cTargets /* <- active */
    1511             && pSource->AllocData.SurfDesc.width == pMode->Mode.Width
    1512             && pSource->AllocData.SurfDesc.height == pMode->Mode.Height
    1513             && pSource->AllocData.SurfDesc.bpp == pMode->Mode.BitsPerPixel)
    1514     {
    1515         pMode->fFlags |= VBOXWDDM_ADJUSTVIDEOMODE_F_CURRENT;
    1516         if (pMode->fFlags & VBOXWDDM_ADJUSTVIDEOMODE_F_UNSUPPORTED)
    1517         {
    1518             WARN(("current mode is reported as unsupported"));
    1519         }
    1520     }
    1521 }
    1522 
    1523 void VBoxWddmAdjustModes(PVBOXMP_DEVEXT pExt, uint32_t cModes, PVBOXWDDM_ADJUSTVIDEOMODE aModes)
    1524 {
    1525     for (UINT i = 0; i < cModes; ++i)
    1526     {
    1527         PVBOXWDDM_ADJUSTVIDEOMODE pMode = &aModes[i];
    1528         VBoxWddmAdjustMode(pExt, pMode);
    1529     }
    1530 }
    1531 
    1532 NTSTATUS VBoxWddmGetModesForResolution(VIDEO_MODE_INFORMATION *pAllModes, uint32_t cAllModes, int iSearchPreferredMode,
    1533         const D3DKMDT_2DREGION *pResolution, VIDEO_MODE_INFORMATION * pModes, uint32_t cModes, uint32_t *pcModes, int32_t *piPreferrableMode)
    1534 {
    1535     NTSTATUS Status = STATUS_SUCCESS;
    1536     uint32_t cFound = 0;
    1537     int iFoundPreferrableMode = -1;
    1538     for (uint32_t i = 0; i < cAllModes; ++i)
    1539     {
    1540         VIDEO_MODE_INFORMATION *pCur = &pAllModes[i];
    1541         if (pResolution->cx == pCur->VisScreenWidth
    1542                         && pResolution->cy == pCur->VisScreenHeight)
    1543         {
    1544             if (pModes && cModes > cFound)
    1545                 memcpy(&pModes[cFound], pCur, sizeof(VIDEO_MODE_INFORMATION));
    1546             else
    1547                 Status = STATUS_BUFFER_TOO_SMALL;
    1548 
    1549             if (i == iSearchPreferredMode)
    1550                 iFoundPreferrableMode = cFound;
    1551 
    1552             ++cFound;
    1553         }
    1554     }
    1555 
    1556     Assert(iFoundPreferrableMode < 0 || cFound > (uint32_t)iFoundPreferrableMode);
    1557 
    1558     *pcModes = cFound;
    1559     if (piPreferrableMode)
    1560         *piPreferrableMode = iFoundPreferrableMode;
    1561 
    1562     return Status;
    1563 }
    1564 
    1565 PVBOXWDDM_VIDEOMODES_INFO VBoxWddmGetAllVideoModesInfos(PVBOXMP_DEVEXT pExt)
    1566 {
    1567     return g_aVBoxVideoModeInfos;
    1568 }
    1569 
    1570 PVBOXWDDM_VIDEOMODES_INFO VBoxWddmGetVideoModesInfo(PVBOXMP_DEVEXT pExt, D3DDDI_VIDEO_PRESENT_TARGET_ID VidPnTargetId)
    1571 {
    1572     return &VBoxWddmGetAllVideoModesInfos(pExt)[VidPnTargetId];
    1573 }
    1574 
    1575 #endif /*VBOX_WDDM_MINIPORT*/
Note: See TracChangeset for help on using the changeset viewer.

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