VirtualBox

Ignore:
Timestamp:
Sep 10, 2010 7:43:11 PM (14 years ago)
Author:
vboxsync
Message:

wddm/3d: multiple swapchain handling (needed for win7 & multi-screen)

Location:
trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispD3D.cpp

    r32325 r32425  
    868868    {
    869869        pRc->cAllocations = cAllocs;
     870        for (UINT i = 0; i < cAllocs; ++i)
     871        {
     872            pRc->aAllocations[i].pRc = pRc;
     873        }
    870874        return pRc;
    871875    }
     
    10971101}
    10981102
    1099 
     1103#if 0
    11001104static HRESULT vboxWddmRenderTargetUpdateSurface(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_ALLOCATION pAlloc, uint32_t iBBuf)
    11011105{
     
    11751179    return S_OK;
    11761180}
    1177 
    1178 #ifdef DEBUG
    1179 static void vboxWddmDbgRenderTargetUpdateCheckSurface(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_ALLOCATION pAlloc, uint32_t iBBuf)
    1180 {
    1181     IDirect3DSurface9 *pD3D9Surf;
    1182     Assert(pAlloc->enmD3DIfType == VBOXDISP_D3DIFTYPE_SURFACE);
    1183     IDirect3DDevice9 * pDevice9If = pDevice->aScreens[pDevice->iPrimaryScreen].pDevice9If;
    1184     HRESULT hr = pDevice9If->GetBackBuffer(0 /*UINT iSwapChain*/,
    1185             iBBuf, D3DBACKBUFFER_TYPE_MONO, &pD3D9Surf);
    1186     Assert(hr == S_OK);
    1187     if (hr == S_OK)
    1188     {
    1189         Assert(pD3D9Surf);
    1190         Assert(pD3D9Surf == pAlloc->pD3DIf);
    1191         pD3D9Surf->Release();
    1192     }
    1193 }
    1194 
    1195 static void vboxWddmDbgRenderTargetCheck(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_RESOURCE pRc, uint32_t iNewRTFB)
    1196 {
    1197     PVBOXWDDMDISP_ALLOCATION pAlloc;
    1198     UINT iBBuf = 0;
    1199     Assert(iNewRTFB < pRc->cAllocations);
    1200 
    1201     for (UINT i = 1; i < pRc->cAllocations; ++i, ++iBBuf)
    1202     {
    1203         UINT iAlloc = (iNewRTFB + i) % pRc->cAllocations;
    1204         Assert(iAlloc != iNewRTFB);
    1205         pAlloc = &pRc->aAllocations[iAlloc];
    1206         vboxWddmDbgRenderTargetUpdateCheckSurface(pDevice, pAlloc, iBBuf);
    1207     }
    1208 
    1209     pAlloc = &pRc->aAllocations[iNewRTFB];
    1210 #ifdef VBOXWDDM_WITH_VISIBLE_FB
    1211     vboxWddmDbgRenderTargetUpdateCheckSurface(pDevice, pAlloc, ~0UL /* <- for the frontbuffer */);
    1212 #else
    1213     Assert((!pAlloc->pD3DIf) == (pRc->cAllocations > 1));
    12141181#endif
    1215 
    1216     for (UINT i = 0; i < pRc->cAllocations; ++i)
    1217     {
    1218         pAlloc = &pRc->aAllocations[i];
    1219         if (iNewRTFB == i)
    1220         {
    1221             Assert((!pAlloc->pD3DIf) == (pRc->cAllocations > 1));
    1222         }
    1223 
    1224         for (UINT j = i+1; j < pRc->cAllocations; ++j)
    1225         {
    1226             PVBOXWDDMDISP_ALLOCATION pAllocJ = &pRc->aAllocations[j];
    1227             Assert(pAlloc->pD3DIf != pAllocJ->pD3DIf);
    1228         }
    1229     }
    1230 }
    1231 
    1232 # define VBOXVDBG_RTGT_STATECHECK(_pDev) (vboxWddmDbgRenderTargetCheck((_pDev), (_pDev)->aScreens[(_pDev)->iPrimaryScreen].pRenderTargetRc, (_pDev)->aScreens[(_pDev)->iPrimaryScreen].iRenderTargetFrontBuf))
    1233 #else
    1234 # define VBOXVDBG_RTGT_STATECHECK(_pDev) do{}while(0)
    1235 #endif
    1236 
    1237 static HRESULT vboxWddmD3DDeviceCreate(PVBOXWDDMDISP_DEVICE pDevice, UINT iScreen, PVBOXWDDMDISP_RESOURCE pRc, D3DPRESENT_PARAMETERS * pParams, BOOL bLockable)
    1238 {
    1239     UINT cSurfs = pParams->BackBufferCount + 1;
    1240     Assert(pRc->cAllocations = cSurfs);
    1241     IDirect3DDevice9 *pPrimaryDevice = pDevice->aScreens[pDevice->iPrimaryScreen].pDevice9If;
    1242     PVBOXWDDMDISP_SCREEN pScreen = &pDevice->aScreens[iScreen];
    1243     PVBOXWDDMDISP_ADAPTER pAdapter = pDevice->pAdapter;
    1244     HRESULT hr;
    1245     HWND hWnd = NULL;
    1246     Assert(!pScreen->pDevice9If);
    1247     Assert(!pScreen->hWnd);
    1248     hr = VBoxDispWndCreate(pAdapter, pParams->BackBufferWidth, pParams->BackBufferHeight, &hWnd);
    1249     Assert(hr == S_OK);
    1250     if (hr == S_OK)
    1251     {
    1252         pScreen->hWnd = hWnd;
    1253 
    1254         DWORD fFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
    1255         if (pDevice->fFlags.AllowMultithreading)
    1256             fFlags |= D3DCREATE_MULTITHREADED;
    1257 
    1258         IDirect3DDevice9 *pDevice9If = NULL;
    1259         pParams->hDeviceWindow = hWnd;
    1260                     /* @todo: it seems there should be a way to detect this correctly since
    1261                      * our vboxWddmDDevSetDisplayMode will be called in case we are using full-screen */
    1262         pParams->Windowed = TRUE;
    1263         //            params.EnableAutoDepthStencil = FALSE;
    1264         //            params.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
    1265         //            params.Flags;
    1266         //            params.FullScreen_RefreshRateInHz;
    1267         //            params.FullScreen_PresentationInterval;
    1268         hr = pAdapter->pD3D9If->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, fFlags, pParams, &pDevice9If);
    1269         Assert(hr == S_OK);
    1270         if (hr == S_OK)
    1271         {
    1272             pScreen->pDevice9If = pDevice9If;
    1273             pScreen->pRenderTargetRc = pRc;
    1274             ++pDevice->cScreens;
    1275 
    1276             for (UINT i = 0; i < cSurfs; ++i)
    1277             {
    1278                 PVBOXWDDMDISP_ALLOCATION pAllocation = &pRc->aAllocations[i];
    1279                 pAllocation->enmD3DIfType = VBOXDISP_D3DIFTYPE_SURFACE;
    1280             }
    1281 
    1282             if (pPrimaryDevice)
    1283             {
    1284                 for (UINT i = 0; i < cSurfs; ++i)
    1285                 {
    1286                     PVBOXWDDMDISP_ALLOCATION pAllocation = &pRc->aAllocations[i];
    1287                     IDirect3DSurface9 *pRt;
    1288                     IDirect3DSurface9 *pSecondaryOpenedRt;
    1289                     HANDLE hSharedHandle = NULL;
    1290                     hr = pPrimaryDevice->CreateRenderTarget(
    1291                             pParams->BackBufferWidth, pParams->BackBufferHeight,
    1292                             pParams->BackBufferFormat,
    1293                             pParams->MultiSampleType,
    1294                             pParams->MultiSampleQuality,
    1295                             TRUE, /*BOOL Lockable*/
    1296                             &pRt,
    1297                             &hSharedHandle);
    1298                     Assert(hr == S_OK);
    1299                     if (hr == S_OK)
    1300                     {
    1301                         Assert(hSharedHandle != NULL);
    1302                         /* open render target for primary device */
    1303                         hr = pDevice9If->CreateRenderTarget(
    1304                                     pParams->BackBufferWidth, pParams->BackBufferHeight,
    1305                                     pParams->BackBufferFormat,
    1306                                     pParams->MultiSampleType,
    1307                                     pParams->MultiSampleQuality,
    1308                                     TRUE, /*BOOL Lockable*/
    1309                                     &pSecondaryOpenedRt,
    1310                                     &hSharedHandle);
    1311                         Assert(hr == S_OK);
    1312                         if (hr == S_OK)
    1313                         {
    1314                             pAllocation->pD3DIf = pRt;
    1315                             pAllocation->pSecondaryOpenedD3DIf = pSecondaryOpenedRt;
    1316                             pAllocation->hSharedHandle = hSharedHandle;
    1317                             continue;
    1318                         }
    1319                         pRt->Release();
    1320                     }
    1321 
    1322                     for (UINT j = 0; j < i; ++j)
    1323                     {
    1324                         PVBOXWDDMDISP_ALLOCATION pAlloc = &pRc->aAllocations[j];
    1325                         pAlloc->pD3DIf->Release();
    1326                         pAlloc->pSecondaryOpenedD3DIf->Release();
    1327                     }
    1328 
    1329                     break;
    1330                 }
    1331             }
    1332             else
    1333             {
    1334                 pDevice->iPrimaryScreen = iScreen;
    1335                 hr = vboxWddmRenderTargetUpdate(pDevice, pRc, 0);
    1336                 Assert(hr == S_OK);
    1337             }
    1338 
    1339             if (hr == S_OK)
    1340             {
    1341                 for (UINT i = 0; i < cSurfs; ++i)
    1342                 {
    1343                     PVBOXWDDMDISP_ALLOCATION pAllocation = &pRc->aAllocations[i];
    1344                     pAllocation->enmD3DIfType = VBOXDISP_D3DIFTYPE_SURFACE;
    1345                     hr = vboxWddmSurfSynchMem(pRc, pAllocation);
    1346                     Assert(hr == S_OK);
    1347                     if (hr != S_OK)
    1348                     {
    1349                         break;
    1350                     }
    1351                 }
    1352 
    1353 #ifndef VBOXWDDM_WITH_VISIBLE_FB
    1354                 if (!pPrimaryDevice)
    1355                 {
    1356                     if (hr == S_OK)
    1357                     {
    1358                         IDirect3DSurface9* pD3D9Surf;
    1359                         hr = pDevice9If->CreateRenderTarget(
    1360                                 pParams->BackBufferWidth, pParams->BackBufferHeight,
    1361                                 pParams->BackBufferFormat,
    1362                                 pParams->MultiSampleType,
    1363                                 pParams->MultiSampleQuality,
    1364                                 bLockable,
    1365                                 &pD3D9Surf,
    1366                                 NULL /* HANDLE* pSharedHandle */
    1367                                 );
    1368                         Assert(hr == S_OK);
    1369                         if (hr == S_OK)
    1370                         {
    1371                             pDevice->pRenderTargetFbCopy = pD3D9Surf;
    1372                         }
    1373                     }
    1374                 }
    1375 #endif
    1376 
    1377                 if (hr != S_OK)
    1378                 {
    1379                     for (UINT i = 0; i < cSurfs; ++i)
    1380                     {
    1381                         PVBOXWDDMDISP_ALLOCATION pAllocation = &pRc->aAllocations[i];
    1382                         pAllocation->pD3DIf->Release();
    1383                     }
    1384                 }
    1385             }
    1386 
    1387             if (hr != S_OK)
    1388             {
    1389                 pDevice9If->Release();
    1390                 --pDevice->cScreens;
    1391                 Assert(pDevice->cScreens < UINT32_MAX/2);
    1392             }
    1393         }
    1394 
    1395         if (hr != S_OK)
    1396         {
    1397             HRESULT tmpHr = VBoxDispWndDestroy(pAdapter, pScreen->hWnd);
    1398             Assert(tmpHr == S_OK);
    1399         }
    1400     }
    1401 
    1402     return hr;
    1403 }
    1404 
    1405 static HRESULT vboxWddmD3DDeviceCreateDummy(PVBOXWDDMDISP_DEVICE pDevice)
    1406 {
    1407     HRESULT hr;
    1408     PVBOXWDDMDISP_RESOURCE pRc = vboxResourceAlloc(2);
    1409     Assert(pRc);
    1410     if (pRc)
    1411     {
    1412         D3DPRESENT_PARAMETERS params;
    1413         memset(&params, 0, sizeof (params));
    1414 //                        params.BackBufferWidth = 640;
    1415 //                        params.BackBufferHeight = 480;
    1416         params.BackBufferWidth = 0x400;
    1417         params.BackBufferHeight = 0x300;
    1418         params.BackBufferFormat = D3DFMT_A8R8G8B8;
    1419 //                        params.BackBufferCount = 0;
    1420         params.BackBufferCount = 1;
    1421         params.MultiSampleType = D3DMULTISAMPLE_NONE;
    1422         params.SwapEffect = D3DSWAPEFFECT_DISCARD;
    1423 //                    params.hDeviceWindow = hWnd;
    1424                     /* @todo: it seems there should be a way to detect this correctly since
    1425                      * our vboxWddmDDevSetDisplayMode will be called in case we are using full-screen */
    1426         params.Windowed = TRUE;
    1427         //            params.EnableAutoDepthStencil = FALSE;
    1428         //            params.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
    1429         //            params.Flags;
    1430         //            params.FullScreen_RefreshRateInHz;
    1431         //            params.FullScreen_PresentationInterval;
    1432 
    1433         hr = vboxWddmD3DDeviceCreate(pDevice, 0, pRc, &params, TRUE /*BOOL bLockable*/);
    1434         Assert(hr == S_OK);
    1435         if (hr != S_OK)
    1436             vboxResourceFree(pRc);
    1437     }
    1438     else
    1439     {
    1440         hr = E_OUTOFMEMORY;
    1441     }
    1442 
    1443     return hr;
    1444 }
    1445 
    1446 DECLINLINE(IDirect3DDevice9*) vboxWddmD3DDeviceGetPrimary(PVBOXWDDMDISP_DEVICE pDevice)
    1447 {
    1448     PVBOXWDDMDISP_SCREEN pScreen = &pDevice->aScreens[pDevice->iPrimaryScreen];
    1449     if (pScreen->pDevice9If)
    1450         return pScreen->pDevice9If;
    1451     HRESULT hr = vboxWddmD3DDeviceCreateDummy(pDevice);
    1452     Assert(hr == S_OK);
    1453     Assert(pScreen->pDevice9If);
    1454     return pScreen->pDevice9If;
    1455 }
    1456 
    1457 static HRESULT APIENTRY vboxWddmDDevDestroyResource(HANDLE hDevice, HANDLE hResource);
    1458 
    1459 static HRESULT vboxWddmD3DDeviceUpdate(PVBOXWDDMDISP_DEVICE pDevice, UINT iScreen, PVBOXWDDMDISP_RESOURCE pRc, D3DPRESENT_PARAMETERS * pParams, BOOL bLockable)
    1460 {
    1461     UINT cSurfs = pParams->BackBufferCount + 1;
    1462     Assert(pRc->cAllocations = cSurfs);
    1463     Assert(iScreen == pDevice->iPrimaryScreen);
    1464     PVBOXWDDMDISP_SCREEN pScreen = &pDevice->aScreens[iScreen];
    1465     PVBOXWDDMDISP_RESOURCE pCurRc = pScreen->pRenderTargetRc;
    1466     IDirect3DDevice9Ex *pNewDevice;
    1467     HRESULT hr = pDevice->pAdapter->D3D.pfnVBoxWineExD3DDev9Update((IDirect3DDevice9Ex*)pScreen->pDevice9If, pParams, &pNewDevice);
    1468     Assert(hr == S_OK);
    1469     if (hr == S_OK)
    1470     {
    1471         pScreen->pDevice9If->Release();
    1472         pScreen->pDevice9If = pNewDevice;
    1473         pScreen->pRenderTargetRc = pRc;
    1474 
    1475         for (UINT i = 0; i < cSurfs; ++i)
    1476         {
    1477             PVBOXWDDMDISP_ALLOCATION pAllocation = &pRc->aAllocations[i];
    1478             pAllocation->enmD3DIfType = VBOXDISP_D3DIFTYPE_SURFACE;
    1479         }
    1480 
    1481 #ifndef VBOXWDDM_WITH_VISIBLE_FB
    1482         if (pDevice->pRenderTargetFbCopy)
    1483         {
    1484             pDevice->pRenderTargetFbCopy->Release();
    1485         }
    1486         IDirect3DSurface9* pD3D9Surf;
    1487         hr = pNewDevice->CreateRenderTarget(
    1488                     pParams->BackBufferWidth, pParams->BackBufferHeight,
    1489                     pParams->BackBufferFormat,
    1490                     pParams->MultiSampleType,
    1491                     pParams->MultiSampleQuality,
    1492                     bLockable,
    1493                     &pD3D9Surf,
    1494                     NULL /* HANDLE* pSharedHandle */
    1495                     );
    1496         Assert(hr == S_OK);
    1497         if (hr == S_OK)
    1498         {
    1499             pDevice->pRenderTargetFbCopy = pD3D9Surf;
    1500         }
    1501 #endif
    1502         if (hr == S_OK)
    1503         {
    1504             hr = vboxWddmRenderTargetUpdate(pDevice, pRc, 0);
    1505             Assert(hr == S_OK);
    1506             if (hr == S_OK)
    1507             {
    1508                 for (UINT i = 0; i < cSurfs; ++i)
    1509                 {
    1510                     PVBOXWDDMDISP_ALLOCATION pAllocation = &pRc->aAllocations[i];
    1511                     pAllocation->enmD3DIfType = VBOXDISP_D3DIFTYPE_SURFACE;
    1512                     hr = vboxWddmSurfSynchMem(pRc, pAllocation);
    1513                     Assert(hr == S_OK);
    1514                     if (hr != S_OK)
    1515                     {
    1516                         break;
    1517                     }
    1518                 }
    1519             }
    1520         }
    1521     }
    1522 
    1523 
    1524     if (!pCurRc->hResource)
    1525     {
    1526         HRESULT tmpHr = vboxWddmDDevDestroyResource(pDevice, pCurRc);
    1527         Assert(tmpHr == S_OK);
    1528     }
    1529 
    1530     return hr;
    1531 }
    15321182
    15331183static D3DFORMAT vboxDDI2D3DFormat(D3DDDIFORMAT format)
     
    16781328    return D3DTEXF_NONE;
    16791329}
     1330
     1331
     1332/******/
     1333DECLINLINE(VOID) vboxWddmSwapchainInit(PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
     1334{
     1335    RTLISTNODE ListEntry = pSwapchain->ListEntry;
     1336    memset(pSwapchain, 0, sizeof (VBOXWDDMDISP_SWAPCHAIN));
     1337    pSwapchain->ListEntry = ListEntry;
     1338    pSwapchain->iBB = VBOXWDDMDISP_INDEX_UNDEFINED;
     1339}
     1340
     1341static HRESULT vboxWddmSwapchainDestroyIf(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
     1342{
     1343    if (pSwapchain->pSwapChainIf)
     1344    {
     1345        pSwapchain->pRenderTargetFbCopy->Release();
     1346        pSwapchain->pSwapChainIf->Release();
     1347        Assert(pSwapchain->hWnd);
     1348        HRESULT hr = VBoxDispWndDestroy(pDevice->pAdapter, pSwapchain->hWnd);
     1349        Assert(hr == S_OK);
     1350        pSwapchain->pRenderTargetFbCopy = NULL;
     1351        pSwapchain->pSwapChainIf = NULL;
     1352        pSwapchain->hWnd = NULL;
     1353        return hr;
     1354    }
     1355
     1356    Assert(!pSwapchain->hWnd);
     1357    return S_OK;
     1358}
     1359
     1360DECLINLINE(VOID) vboxWddmSwapchainClear(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
     1361{
     1362    for (UINT i = 0; i < pSwapchain->cRTs; ++i)
     1363    {
     1364        pSwapchain->aRTs[i].pAlloc->pSwapchain = NULL;
     1365    }
     1366    vboxWddmSwapchainDestroyIf(pDevice, pSwapchain);
     1367    vboxWddmSwapchainInit(pSwapchain);
     1368}
     1369
     1370static VOID vboxWddmSwapchainDestroy(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
     1371{
     1372    vboxWddmSwapchainClear(pDevice, pSwapchain);
     1373    RTListNodeRemove(&pSwapchain->ListEntry);
     1374    RTMemFree(pSwapchain);
     1375}
     1376
     1377static VOID vboxWddmSwapchainDestroyAll(PVBOXWDDMDISP_DEVICE pDevice)
     1378{
     1379    PVBOXWDDMDISP_SWAPCHAIN pCur = RTListNodeGetFirst(&pDevice->SwapchainList, VBOXWDDMDISP_SWAPCHAIN, ListEntry);
     1380    while (pCur)
     1381    {
     1382        PVBOXWDDMDISP_SWAPCHAIN pNext = NULL;
     1383        if (!RTListNodeIsLast(&pDevice->SwapchainList, &pCur->ListEntry))
     1384        {
     1385            pNext = RTListNodeGetNext(&pCur->ListEntry, VBOXWDDMDISP_SWAPCHAIN, ListEntry);
     1386        }
     1387
     1388        vboxWddmSwapchainDestroy(pDevice, pCur);
     1389
     1390        pCur = pNext;
     1391    }
     1392}
     1393
     1394static PVBOXWDDMDISP_SWAPCHAIN vboxWddmSwapchainAlloc(PVBOXWDDMDISP_DEVICE pDevice)
     1395{
     1396    PVBOXWDDMDISP_SWAPCHAIN pSwapchain = (PVBOXWDDMDISP_SWAPCHAIN)RTMemAllocZ(sizeof (VBOXWDDMDISP_SWAPCHAIN));
     1397    Assert(pSwapchain);
     1398    if (pSwapchain)
     1399    {
     1400        RTListAppend(&pDevice->SwapchainList, &pSwapchain->ListEntry);
     1401        vboxWddmSwapchainInit(pSwapchain);
     1402        return pSwapchain;
     1403    }
     1404    return NULL;
     1405}
     1406
     1407DECLINLINE(VOID) vboxWddmSwapchainRtInit(PVBOXWDDMDISP_SWAPCHAIN pSwapchain, PVBOXWDDMDISP_RENDERTGT pRt, PVBOXWDDMDISP_ALLOCATION pAlloc)
     1408{
     1409    pSwapchain->fFlags.bChanged = 1;
     1410    pRt->pAlloc = pAlloc;
     1411    pRt->cNumFlips = 0;
     1412    pRt->fFlags.Value = 0;
     1413    pRt->fFlags.bAdded = 1;
     1414}
     1415
     1416DECLINLINE(VOID) vboxWddmSwapchainBbAddTail(PVBOXWDDMDISP_SWAPCHAIN pSwapchain, PVBOXWDDMDISP_ALLOCATION pAlloc, BOOL bAssignAsBb)
     1417{
     1418    pAlloc->pSwapchain = pSwapchain;
     1419    VBOXWDDMDISP_SWAPCHAIN_FLAGS fOldFlags = pSwapchain->fFlags;
     1420    PVBOXWDDMDISP_RENDERTGT pRt = &pSwapchain->aRTs[pSwapchain->cRTs];
     1421    ++pSwapchain->cRTs;
     1422    vboxWddmSwapchainRtInit(pSwapchain, pRt, pAlloc);
     1423    if (pSwapchain->cRTs == 1)
     1424    {
     1425        Assert(pSwapchain->iBB == VBOXWDDMDISP_INDEX_UNDEFINED);
     1426        pSwapchain->iBB = 0;
     1427    }
     1428    else if (bAssignAsBb)
     1429    {
     1430        pSwapchain->iBB = pSwapchain->cRTs - 1;
     1431    }
     1432    else if (pSwapchain->cRTs == 2) /* the first one is a frontbuffer */
     1433    {
     1434        pSwapchain->iBB = 1;
     1435    }
     1436}
     1437
     1438DECLINLINE(UINT) vboxWddmSwapchainIdxFb(PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
     1439{
     1440    return (pSwapchain->iBB + pSwapchain->cRTs - 1) % pSwapchain->cRTs;
     1441}
     1442
     1443/* if swapchain contains only one surface returns this surface */
     1444DECLINLINE(PVBOXWDDMDISP_RENDERTGT) vboxWddmSwapchainGetBb(PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
     1445{
     1446    if (pSwapchain->cRTs)
     1447    {
     1448        Assert(pSwapchain->iBB < pSwapchain->cRTs);
     1449        return &pSwapchain->aRTs[pSwapchain->iBB];
     1450    }
     1451    return NULL;
     1452}
     1453
     1454DECLINLINE(PVBOXWDDMDISP_RENDERTGT) vboxWddmSwapchainGetFb(PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
     1455{
     1456    if (pSwapchain->cRTs)
     1457    {
     1458        UINT iFb = vboxWddmSwapchainIdxFb(pSwapchain);
     1459        return &pSwapchain->aRTs[iFb];
     1460    }
     1461    return NULL;
     1462}
     1463
     1464DECLINLINE(VOID) vboxWddmSwapchainFlip(PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
     1465{
     1466    pSwapchain->iBB = (pSwapchain->iBB + 1) % pSwapchain->cRTs;
     1467}
     1468
     1469DECLINLINE(UINT) vboxWddmSwapchainNumRTs(PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
     1470{
     1471    return pSwapchain->cRTs;
     1472}
     1473
     1474
     1475DECLINLINE(PVBOXWDDMDISP_RENDERTGT) vboxWddmSwapchainRtForAlloc(PVBOXWDDMDISP_SWAPCHAIN pSwapchain, PVBOXWDDMDISP_ALLOCATION pAlloc)
     1476{
     1477    if (pAlloc->pSwapchain != pSwapchain)
     1478        return NULL;
     1479
     1480    for (UINT i = 0; i < pSwapchain->cRTs; ++i)
     1481    {
     1482        Assert(pSwapchain->aRTs[i].pAlloc->pSwapchain = pSwapchain);
     1483        if (pSwapchain->aRTs[i].pAlloc == pAlloc)
     1484            return &pSwapchain->aRTs[i];
     1485    }
     1486
     1487    /* should never happen */
     1488    Assert(0);
     1489    return NULL;
     1490}
     1491
     1492DECLINLINE(UINT) vboxWddmSwapchainRtIndex(PVBOXWDDMDISP_SWAPCHAIN pSwapchain, PVBOXWDDMDISP_RENDERTGT pRT)
     1493{
     1494    UINT offFirst = RT_OFFSETOF(VBOXWDDMDISP_SWAPCHAIN, aRTs);
     1495    UINT offRT = UINT((uintptr_t)pRT - (uintptr_t)pSwapchain);
     1496    Assert(offRT < sizeof (VBOXWDDMDISP_SWAPCHAIN));
     1497    Assert(offRT >= offFirst);
     1498    Assert(!((offRT - offFirst) % sizeof (VBOXWDDMDISP_RENDERTGT)));
     1499    UINT iRt = (offRT - offFirst) / sizeof (VBOXWDDMDISP_RENDERTGT);
     1500    Assert(iRt < pSwapchain->cRTs);
     1501    return iRt;
     1502}
     1503
     1504DECLINLINE(PVBOXWDDMDISP_SWAPCHAIN) vboxWddmSwapchainForAlloc(PVBOXWDDMDISP_ALLOCATION pAlloc)
     1505{
     1506    return pAlloc->pSwapchain;
     1507}
     1508
     1509DECLINLINE(VOID) vboxWddmSwapchainRtRemove(PVBOXWDDMDISP_SWAPCHAIN pSwapchain, PVBOXWDDMDISP_RENDERTGT pRT)
     1510{
     1511    UINT iRt = vboxWddmSwapchainRtIndex(pSwapchain, pRT);
     1512    Assert(iRt < pSwapchain->cRTs);
     1513    pRT->pAlloc->pSwapchain = NULL;
     1514    for (UINT i = iRt; i < pSwapchain->cRTs - 1; ++i)
     1515    {
     1516        pSwapchain->aRTs[i] = pSwapchain->aRTs[i + 1];
     1517    }
     1518
     1519    --pSwapchain->cRTs;
     1520    if (pSwapchain->cRTs)
     1521    {
     1522        if (pSwapchain->iBB > iRt)
     1523        {
     1524            --pSwapchain->iBB;
     1525        }
     1526        else if (pSwapchain->iBB == iRt)
     1527        {
     1528            Assert(0);
     1529            pSwapchain->iBB = 0;
     1530        }
     1531    }
     1532    else
     1533    {
     1534        pSwapchain->iBB = VBOXWDDMDISP_INDEX_UNDEFINED;
     1535    }
     1536    pSwapchain->fFlags.bChanged = TRUE;
     1537}
     1538
     1539#if 0
     1540
     1541
     1542DECLINLINE(VOID) vboxWddmSwapchainSetBb(PVBOXWDDMDISP_SWAPCHAIN pSwapchain, PVBOXWDDMDISP_RENDERTGT pRT)
     1543{
     1544    UINT iRt = vboxWddmSwapchainRtIndex(pSwapchain, pRT);
     1545    Assert(iRt < pSwapchain->cRTs);
     1546    pSwapchain->iBB = iRt;
     1547}
     1548
     1549/* the paRemoved buffer should at least contain VBOXWDDMDISP_MAX_SWAPCHAIN_SIZE elements,
     1550 * the function does not validate its size in any way */
     1551static BOOL vboxWddmSwapchainAdjust(PVBOXWDDMDISP_SWAPCHAIN pSwapchain, PVBOXWDDMDISP_ALLOCATION pBbAlloc, PUINT pcRemoved, PVBOXWDDMDISP_ALLOCATION paRemoved)
     1552{
     1553    UINT cRemoved = 0;
     1554    BOOL bChanged = FALSE;
     1555    PVBOXWDDMDISP_RENDERTGT pCurBbRt = vboxWddmSwapchainGetBb(pSwapchain);
     1556    if (pCurBb)
     1557    {
     1558        if (pCurBbRt->pAlloc != pBbAlloc)
     1559        {
     1560            bChanged = TRUE;
     1561
     1562            /* determine whether we need to add the current BB
     1563             * or remove part or all of the current RTs in the swapchain */
     1564            PVBOXWDDMDISP_RENDERTGT pCorrectRt = vboxWddmSwapchainSearchRt(pSwapchain, pBbAlloc);
     1565            if (pCorrectRt)
     1566            {
     1567                paRemoved[cRemoved] = pCurBbRt->pAlloc;
     1568                ++cRemoved;
     1569                vboxWddmSwapchainRemoveRt(pSwapchain, pCurBbRt);
     1570                vboxWddmSwapchainSetBb(pSwapchain, pBbAlloc);
     1571            }
     1572            else
     1573            {
     1574                /* check if the pCurBbRt stored in the swapchain match those of the pBbAlloc */
     1575                if (pBbAlloc->SurfDesc.width == pCurBbRt->pAlloc->SurfDesc.width
     1576                        && pBbAlloc->SurfDesc.height == pCurBbRt->pAlloc->SurfDesc.height
     1577                        && pBbAlloc->SurfDesc.format == pCurBbRt->pAlloc->SurfDesc.format)
     1578                {
     1579                    for (UINT i = 0; i < pSwapchain->cRTs;)
     1580                    {
     1581                        if (pSwapchain->aRTs[i].cNumFlips > 1)
     1582                        {
     1583                            paRemoved[cRemoved] = pSwapchain->aRTs[i].pAlloc;
     1584                            ++cRemoved;
     1585                            vboxWddmSwapchainRemoveRt(pSwapchain, &pSwapchain->aRTs[i]);
     1586                        }
     1587                        else
     1588                        {
     1589                            ++i;
     1590                        }
     1591                    }
     1592                }
     1593                else
     1594                {
     1595                    /* remove all */
     1596                    for (UINT i = 0; i < pSwapchain->cRTs; ++i)
     1597                    {
     1598                        paRemoved[cRemoved] = pSwapchain->aRTs[i].pAlloc;
     1599                        ++cRemoved;
     1600                    }
     1601
     1602                    vboxWddmSwapchainClear(pSwapchain);
     1603                }
     1604
     1605                vboxWddmSwapchainAllocAddTail(pSwapchain, pBbAlloc);
     1606                vboxWddmSwapchainSetBb(pSwapchain, pBbAlloc);
     1607            }
     1608        }
     1609    }
     1610    else
     1611    {
     1612        vboxWddmSwapchainAllocAddTail(pSwapchain, pBbAlloc);
     1613        bChanged = TRUE;
     1614    }
     1615
     1616    if (!bChanged)
     1617    {
     1618        Assert(cRemoved == 0);
     1619    }
     1620
     1621    *pcRemoved = cRemoved;
     1622
     1623    return bChanged;
     1624}
     1625#endif
     1626static PVBOXWDDMDISP_SWAPCHAIN vboxWddmSwapchainFindCreate(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_ALLOCATION pBbAlloc)
     1627{
     1628    PVBOXWDDMDISP_SWAPCHAIN pSwapchain = pBbAlloc->pSwapchain;
     1629    if (pSwapchain)
     1630    {
     1631        /* check if this is what we expect */
     1632        PVBOXWDDMDISP_RENDERTGT pRt = vboxWddmSwapchainGetBb(pSwapchain);
     1633        if (pRt->pAlloc != pBbAlloc)
     1634        {
     1635            /* bad, @todo: correct the swapchain by either removing the Rt and adding it to another swapchain
     1636             * or by removing the pBbAlloc out of it */
     1637            Assert(0);
     1638        }
     1639    }
     1640    if (!pSwapchain)
     1641    {
     1642        Assert(0);
     1643        /* first search for the swapchain the alloc might be added to */
     1644        PVBOXWDDMDISP_SWAPCHAIN pCur = RTListNodeGetFirst(&pDevice->SwapchainList, VBOXWDDMDISP_SWAPCHAIN, ListEntry);
     1645        while (pCur)
     1646        {
     1647            PVBOXWDDMDISP_RENDERTGT pRt = vboxWddmSwapchainGetBb(pCur);
     1648            Assert(pRt);
     1649            if (pRt->cNumFlips < 2
     1650                    && vboxWddmSwapchainRtIndex(pCur, pRt) == 0) /* <- in case we add a rt to the swapchain on present this would mean
     1651                                                            * that the last RT in the swapchain array is now a frontbuffer and
     1652                                                            * thus the aRTs[0] is a backbuffer */
     1653            {
     1654                PVBOXWDDMDISP_RESOURCE pBbRc = pBbAlloc->pRc;
     1655                PVBOXWDDMDISP_RESOURCE pRtRc = pRt->pAlloc->pRc;
     1656                if (pBbAlloc->SurfDesc.width == pRt->pAlloc->SurfDesc.width
     1657                            && pBbAlloc->SurfDesc.height == pRt->pAlloc->SurfDesc.height
     1658                            && pBbAlloc->SurfDesc.format == pRt->pAlloc->SurfDesc.format
     1659                            && pBbAlloc->SurfDesc.VidPnSourceId == pRt->pAlloc->SurfDesc.VidPnSourceId
     1660                            && (pBbRc == pRtRc
     1661                                    || (pBbRc->fFlags == pRtRc->fFlags
     1662                                            && pBbRc->RcDesc.enmPool == pRtRc->RcDesc.enmPool
     1663                                            && pBbRc->RcDesc.fFlags.Value == pRtRc->RcDesc.fFlags.Value
     1664                                        )
     1665                                ))
     1666                {
     1667                    vboxWddmSwapchainBbAddTail(pCur, pBbAlloc, TRUE);
     1668                    pSwapchain = pCur;
     1669                    break;
     1670                }
     1671            }
     1672            if (RTListNodeIsLast(&pDevice->SwapchainList, &pCur->ListEntry))
     1673                break;
     1674            pCur = RTListNodeGetNext(&pCur->ListEntry, VBOXWDDMDISP_SWAPCHAIN, ListEntry);
     1675        }
     1676
     1677//        if (!pSwapchain) need to create a new one (see below)
     1678    }
     1679
     1680    if (!pSwapchain)
     1681    {
     1682        pSwapchain = vboxWddmSwapchainAlloc(pDevice);
     1683        Assert(pSwapchain);
     1684        if (pSwapchain)
     1685        {
     1686            vboxWddmSwapchainBbAddTail(pSwapchain, pBbAlloc, FALSE);
     1687        }
     1688    }
     1689
     1690    return pSwapchain;
     1691}
     1692
     1693static PVBOXWDDMDISP_SWAPCHAIN vboxWddmSwapchainCreateForRc(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_RESOURCE pRc)
     1694{
     1695    PVBOXWDDMDISP_SWAPCHAIN pSwapchain = vboxWddmSwapchainAlloc(pDevice);
     1696    Assert(pSwapchain);
     1697    if (pSwapchain)
     1698    {
     1699        for (UINT i = 0; i < pRc->cAllocations; ++i)
     1700        {
     1701            vboxWddmSwapchainBbAddTail(pSwapchain, &pRc->aAllocations[i], FALSE);
     1702        }
     1703        return pSwapchain;
     1704    }
     1705    return NULL;
     1706}
     1707
     1708DECLINLINE(UINT) vboxWddmSwapchainIdxBb2Rt(PVBOXWDDMDISP_SWAPCHAIN pSwapchain, uint32_t iBb)
     1709{
     1710    return iBb != (~0) ? (iBb + pSwapchain->iBB) % pSwapchain->cRTs : vboxWddmSwapchainIdxFb(pSwapchain);
     1711}
     1712
     1713static HRESULT vboxWddmSwapchainRtSynch(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain, uint32_t iBb, BOOL bSynchContents)
     1714{
     1715    IDirect3DSurface9 *pD3D9Surf;
     1716    UINT iRt = vboxWddmSwapchainIdxBb2Rt(pSwapchain, iBb);
     1717    PVBOXWDDMDISP_RENDERTGT pRt = &pSwapchain->aRTs[iRt];
     1718    HRESULT hr = pSwapchain->pSwapChainIf->GetBackBuffer(iBb, D3DBACKBUFFER_TYPE_MONO, &pD3D9Surf);
     1719    Assert(hr == S_OK);
     1720    if (hr == S_OK)
     1721    {
     1722        PVBOXWDDMDISP_ALLOCATION pAlloc = pRt->pAlloc;
     1723        Assert(pD3D9Surf);
     1724        Assert(pAlloc->enmD3DIfType == VBOXDISP_D3DIFTYPE_SURFACE);
     1725        if (pAlloc->pD3DIf)
     1726        {
     1727            if (bSynchContents)
     1728            {
     1729                IDirect3DSurface9 *pD3D9OldSurf = (IDirect3DSurface9*)pAlloc->pD3DIf;
     1730                hr = pDevice->pDevice9If->StretchRect(pD3D9OldSurf, NULL, pD3D9Surf, NULL, D3DTEXF_NONE);
     1731                Assert(hr == S_OK);
     1732            }
     1733            pAlloc->pD3DIf->Release();
     1734        }
     1735        pAlloc->pD3DIf = pD3D9Surf;
     1736        pRt->fFlags.Value = 0;
     1737    }
     1738    return hr;
     1739}
     1740static HRESULT vboxWddmSwapchainSynch(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
     1741{
     1742    BOOL bSynchContents = pSwapchain->fFlags.bChanged && pSwapchain->fFlags.bInited;
     1743    for (int iBb = -1; iBb < int(pSwapchain->cRTs - 1); ++iBb)
     1744    {
     1745        HRESULT hr = vboxWddmSwapchainRtSynch(pDevice, pSwapchain, (UINT)iBb, bSynchContents);
     1746        Assert(hr == S_OK);
     1747    }
     1748    pSwapchain->fFlags.bChanged = 0;
     1749    pSwapchain->fFlags.bInited = 1;
     1750    return S_OK;
     1751}
     1752
     1753static VOID vboxWddmSwapchainFillParams(PVBOXWDDMDISP_SWAPCHAIN pSwapchain, D3DPRESENT_PARAMETERS *pParams)
     1754{
     1755    memset(pParams, 0, sizeof (D3DPRESENT_PARAMETERS));
     1756    PVBOXWDDMDISP_RENDERTGT pRt = vboxWddmSwapchainGetBb(pSwapchain);
     1757    PVBOXWDDMDISP_RESOURCE pRc = pRt->pAlloc->pRc;
     1758    pParams->BackBufferWidth = pRt->pAlloc->SurfDesc.width;
     1759    pParams->BackBufferHeight = pRt->pAlloc->SurfDesc.height;
     1760    pParams->BackBufferFormat = vboxDDI2D3DFormat(pRt->pAlloc->SurfDesc.format);
     1761    pParams->BackBufferCount = pSwapchain->cRTs - 1;
     1762    pParams->MultiSampleType = vboxDDI2D3DMultiSampleType(pRc->RcDesc.enmMultisampleType);
     1763    pParams->MultiSampleQuality = pRc->RcDesc.MultisampleQuality;
     1764    if (pRc->RcDesc.fFlags.DiscardRenderTarget)
     1765        pParams->SwapEffect = D3DSWAPEFFECT_DISCARD;
     1766}
     1767
     1768static HRESULT vboxWddmSwapchainChkCreateIf(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
     1769{
     1770    if (!pSwapchain->fFlags.bChanged && pSwapchain->pSwapChainIf)
     1771        return S_OK;
     1772    /* preserve the old one */
     1773    IDirect3DSwapChain9 * pOldIf = pSwapchain->pSwapChainIf;
     1774    HWND hOldWnd = pSwapchain->hWnd;
     1775    /* first create the new one */
     1776    D3DPRESENT_PARAMETERS Params;
     1777    vboxWddmSwapchainFillParams(pSwapchain, &Params);
     1778    IDirect3DSwapChain9 * pNewIf;
     1779    ///
     1780    PVBOXWDDMDISP_ADAPTER pAdapter = pDevice->pAdapter;
     1781    UINT cSurfs = pSwapchain->cRTs;
     1782    HRESULT hr;
     1783    HWND hWnd = NULL;
     1784    IDirect3DDevice9 *pDevice9If = NULL;
     1785    hr = VBoxDispWndCreate(pAdapter, Params.BackBufferWidth, Params.BackBufferHeight, &hWnd);
     1786    Assert(hr == S_OK);
     1787    if (hr == S_OK)
     1788    {
     1789        pSwapchain->hWnd = hWnd;
     1790        DWORD fFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
     1791        if (pDevice->fFlags.AllowMultithreading)
     1792            fFlags |= D3DCREATE_MULTITHREADED;
     1793
     1794        Params.hDeviceWindow = hWnd;
     1795                    /* @todo: it seems there should be a way to detect this correctly since
     1796                     * our vboxWddmDDevSetDisplayMode will be called in case we are using full-screen */
     1797        Params.Windowed = TRUE;
     1798        //            params.EnableAutoDepthStencil = FALSE;
     1799        //            params.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
     1800        //            params.Flags;
     1801        //            params.FullScreen_RefreshRateInHz;
     1802        //            params.FullScreen_PresentationInterval;
     1803        if (!pDevice->pDevice9If)
     1804        {
     1805            hr = pAdapter->pD3D9If->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, fFlags, &Params, &pDevice9If);
     1806            Assert(hr == S_OK);
     1807            if (hr == S_OK)
     1808            {
     1809                pDevice->pDevice9If = pDevice9If;
     1810                hr = pDevice9If->GetSwapChain(0, &pNewIf);
     1811                Assert(hr == S_OK);
     1812                if (hr == S_OK)
     1813                {
     1814                    Assert(pNewIf);
     1815                }
     1816                else
     1817                {
     1818                    pDevice9If->Release();
     1819                }
     1820            }
     1821        }
     1822        else
     1823        {
     1824            pDevice9If = pDevice->pDevice9If;
     1825            hr = pDevice->pDevice9If->CreateAdditionalSwapChain(&Params, &pNewIf);
     1826            Assert(hr == S_OK);
     1827            if (hr == S_OK)
     1828            {
     1829                Assert(pNewIf);
     1830            }
     1831        }
     1832
     1833        if (hr == S_OK)
     1834        {
     1835            Assert(pNewIf);
     1836            pSwapchain->pSwapChainIf = pNewIf;
     1837#ifndef VBOXWDDM_WITH_VISIBLE_FB
     1838            if (!pSwapchain->pRenderTargetFbCopy)
     1839            {
     1840                IDirect3DSurface9* pD3D9Surf;
     1841                hr = pDevice9If->CreateRenderTarget(
     1842                                    Params.BackBufferWidth, Params.BackBufferHeight,
     1843                                    Params.BackBufferFormat,
     1844                                    Params.MultiSampleType,
     1845                                    Params.MultiSampleQuality,
     1846                                    TRUE, /*bLockable*/
     1847                                    &pD3D9Surf,
     1848                                    NULL /* HANDLE* pSharedHandle */
     1849                                    );
     1850                Assert(hr == S_OK);
     1851                if (hr == S_OK)
     1852                {
     1853                    Assert(pD3D9Surf);
     1854                    pSwapchain->pRenderTargetFbCopy = pD3D9Surf;
     1855                }
     1856            }
     1857#endif
     1858
     1859            if (hr == S_OK)
     1860            {
     1861                for (UINT i = 0; i < cSurfs; ++i)
     1862                {
     1863                    PVBOXWDDMDISP_RENDERTGT pRt = &pSwapchain->aRTs[i];
     1864                    pRt->pAlloc->enmD3DIfType = VBOXDISP_D3DIFTYPE_SURFACE;
     1865                }
     1866
     1867                hr = vboxWddmSwapchainSynch(pDevice, pSwapchain);
     1868                Assert(hr == S_OK);
     1869                if (hr == S_OK)
     1870                {
     1871                    for (UINT i = 0; i < cSurfs; ++i)
     1872                    {
     1873                        PVBOXWDDMDISP_RENDERTGT pRt = &pSwapchain->aRTs[i];
     1874                        hr = vboxWddmSurfSynchMem(pRt->pAlloc->pRc, pRt->pAlloc);
     1875                        Assert(hr == S_OK);
     1876                        if (hr != S_OK)
     1877                        {
     1878                            break;
     1879                        }
     1880                    }
     1881
     1882                    Assert(hr == S_OK);
     1883                    if (hr == S_OK)
     1884                    {
     1885                        Assert(pSwapchain->fFlags.Value == 2); /* bInited */
     1886                        if (pOldIf)
     1887                        {
     1888                            Assert(hOldWnd);
     1889                            pOldIf->Release();
     1890                            VBoxDispWndDestroy(pAdapter, hOldWnd);
     1891                        }
     1892                        else
     1893                        {
     1894                            Assert(!hOldWnd);
     1895                        }
     1896                        return S_OK;
     1897                    }
     1898                }
     1899            }
     1900            pNewIf->Release();
     1901            pSwapchain->pSwapChainIf = pOldIf;
     1902        }
     1903
     1904        Assert(hr != S_OK);
     1905
     1906        HRESULT tmpHr = VBoxDispWndDestroy(pAdapter, hWnd);
     1907        Assert(tmpHr == S_OK);
     1908        pSwapchain->hWnd = hOldWnd;
     1909    }
     1910
     1911    return hr;
     1912}
     1913
     1914static HRESULT vboxWddmSwapchainCreateIfForRc(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_RESOURCE pRc, PVBOXWDDMDISP_SWAPCHAIN *ppSwapchain)
     1915{
     1916    PVBOXWDDMDISP_SWAPCHAIN pSwapchain = vboxWddmSwapchainCreateForRc(pDevice, pRc);
     1917    Assert(pSwapchain);
     1918    *ppSwapchain = NULL;
     1919    if (pSwapchain)
     1920    {
     1921        HRESULT hr = vboxWddmSwapchainChkCreateIf(pDevice, pSwapchain);
     1922        Assert(hr == S_OK);
     1923        if (hr == S_OK)
     1924        {
     1925            *ppSwapchain = pSwapchain;
     1926        }
     1927        return hr;
     1928    }
     1929    return E_OUTOFMEMORY;
     1930}
     1931
     1932static HRESULT vboxWddmSwapchainPresentPerform(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_SWAPCHAIN pSwapchain)
     1933{
     1934    HRESULT hr = pSwapchain->pSwapChainIf->Present(NULL, NULL, NULL, NULL, 0);
     1935    Assert(hr == S_OK);
     1936    if (hr == S_OK)
     1937    {
     1938        vboxWddmSwapchainFlip(pSwapchain);
     1939        Assert(pSwapchain->fFlags.Value == 2); /* bInited */
     1940        hr = vboxWddmSwapchainSynch(pDevice, pSwapchain);
     1941        Assert(hr == S_OK);
     1942    }
     1943    return hr;
     1944}
     1945
     1946static HRESULT vboxWddmSwapchainPresent(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_ALLOCATION pBbAlloc)
     1947{
     1948    BOOL bChanged = FALSE;
     1949    PVBOXWDDMDISP_SWAPCHAIN pSwapchain = vboxWddmSwapchainFindCreate(pDevice, pBbAlloc);
     1950    Assert(pSwapchain);
     1951    if (pSwapchain)
     1952    {
     1953        HRESULT hr = vboxWddmSwapchainChkCreateIf(pDevice, pSwapchain);
     1954        Assert(hr == S_OK);
     1955        if (hr == S_OK)
     1956        {
     1957            hr = vboxWddmSwapchainPresentPerform(pDevice, pSwapchain);
     1958            Assert(hr == S_OK);
     1959        }
     1960        return hr;
     1961    }
     1962    return E_OUTOFMEMORY;
     1963}
     1964
     1965#if 0 //def DEBUG
     1966static void vboxWddmDbgRenderTargetUpdateCheckSurface(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_ALLOCATION pAlloc, uint32_t iBBuf)
     1967{
     1968    IDirect3DSurface9 *pD3D9Surf;
     1969    Assert(pAlloc->enmD3DIfType == VBOXDISP_D3DIFTYPE_SURFACE);
     1970    IDirect3DDevice9 * pDevice9If = pDevice->aScreens[pDevice->iPrimaryScreen].pDevice9If;
     1971    HRESULT hr = pDevice9If->GetBackBuffer(0 /*UINT iSwapChain*/,
     1972            iBBuf, D3DBACKBUFFER_TYPE_MONO, &pD3D9Surf);
     1973    Assert(hr == S_OK);
     1974    if (hr == S_OK)
     1975    {
     1976        Assert(pD3D9Surf);
     1977        Assert(pD3D9Surf == pAlloc->pD3DIf);
     1978        pD3D9Surf->Release();
     1979    }
     1980}
     1981
     1982static void vboxWddmDbgRenderTargetCheck(PVBOXWDDMDISP_DEVICE pDevice, PVBOXWDDMDISP_RESOURCE pRc, uint32_t iNewRTFB)
     1983{
     1984    PVBOXWDDMDISP_ALLOCATION pAlloc;
     1985    UINT iBBuf = 0;
     1986    Assert(iNewRTFB < pRc->cAllocations);
     1987
     1988    for (UINT i = 1; i < pRc->cAllocations; ++i, ++iBBuf)
     1989    {
     1990        UINT iAlloc = (iNewRTFB + i) % pRc->cAllocations;
     1991        Assert(iAlloc != iNewRTFB);
     1992        pAlloc = &pRc->aAllocations[iAlloc];
     1993        vboxWddmDbgRenderTargetUpdateCheckSurface(pDevice, pAlloc, iBBuf);
     1994    }
     1995
     1996    pAlloc = &pRc->aAllocations[iNewRTFB];
     1997#ifdef VBOXWDDM_WITH_VISIBLE_FB
     1998    vboxWddmDbgRenderTargetUpdateCheckSurface(pDevice, pAlloc, ~0UL /* <- for the frontbuffer */);
     1999#else
     2000    Assert((!pAlloc->pD3DIf) == (pRc->cAllocations > 1));
     2001#endif
     2002
     2003    for (UINT i = 0; i < pRc->cAllocations; ++i)
     2004    {
     2005        pAlloc = &pRc->aAllocations[i];
     2006        if (iNewRTFB == i)
     2007        {
     2008            Assert((!pAlloc->pD3DIf) == (pRc->cAllocations > 1));
     2009        }
     2010
     2011        for (UINT j = i+1; j < pRc->cAllocations; ++j)
     2012        {
     2013            PVBOXWDDMDISP_ALLOCATION pAllocJ = &pRc->aAllocations[j];
     2014            Assert(pAlloc->pD3DIf != pAllocJ->pD3DIf);
     2015        }
     2016    }
     2017}
     2018
     2019# define VBOXVDBG_RTGT_STATECHECK(_pDev) (vboxWddmDbgRenderTargetCheck((_pDev), (_pDev)->aScreens[(_pDev)->iPrimaryScreen].pRenderTargetRc, (_pDev)->aScreens[(_pDev)->iPrimaryScreen].iRenderTargetFrontBuf))
     2020#else
     2021# define VBOXVDBG_RTGT_STATECHECK(_pDev) do{}while(0)
     2022#endif
     2023
     2024#if 0
     2025static HRESULT vboxWddmD3DDeviceCreate(PVBOXWDDMDISP_DEVICE pDevice, UINT iScreen, PVBOXWDDMDISP_RESOURCE pRc, D3DPRESENT_PARAMETERS * pParams, BOOL bLockable)
     2026{
     2027    UINT cSurfs = pParams->BackBufferCount + 1;
     2028    Assert(pRc->cAllocations = cSurfs);
     2029    IDirect3DDevice9 *pPrimaryDevice = pDevice->aScreens[pDevice->iPrimaryScreen].pDevice9If;
     2030    PVBOXWDDMDISP_SCREEN pScreen = &pDevice->aScreens[iScreen];
     2031    PVBOXWDDMDISP_ADAPTER pAdapter = pDevice->pAdapter;
     2032    HRESULT hr;
     2033    HWND hWnd = NULL;
     2034    Assert(!pScreen->pDevice9If);
     2035    Assert(!pScreen->hWnd);
     2036    hr = VBoxDispWndCreate(pAdapter, pParams->BackBufferWidth, pParams->BackBufferHeight, &hWnd);
     2037    Assert(hr == S_OK);
     2038    if (hr == S_OK)
     2039    {
     2040        pScreen->hWnd = hWnd;
     2041
     2042        DWORD fFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING;
     2043        if (pDevice->fFlags.AllowMultithreading)
     2044            fFlags |= D3DCREATE_MULTITHREADED;
     2045
     2046        IDirect3DDevice9 *pDevice9If = NULL;
     2047        pParams->hDeviceWindow = hWnd;
     2048                    /* @todo: it seems there should be a way to detect this correctly since
     2049                     * our vboxWddmDDevSetDisplayMode will be called in case we are using full-screen */
     2050        pParams->Windowed = TRUE;
     2051        //            params.EnableAutoDepthStencil = FALSE;
     2052        //            params.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
     2053        //            params.Flags;
     2054        //            params.FullScreen_RefreshRateInHz;
     2055        //            params.FullScreen_PresentationInterval;
     2056        hr = pAdapter->pD3D9If->CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, fFlags, pParams, &pDevice9If);
     2057        Assert(hr == S_OK);
     2058        if (hr == S_OK)
     2059        {
     2060            pScreen->pDevice9If = pDevice9If;
     2061            pScreen->pRenderTargetRc = pRc;
     2062            ++pDevice->cScreens;
     2063
     2064            for (UINT i = 0; i < cSurfs; ++i)
     2065            {
     2066                PVBOXWDDMDISP_ALLOCATION pAllocation = &pRc->aAllocations[i];
     2067                pAllocation->enmD3DIfType = VBOXDISP_D3DIFTYPE_SURFACE;
     2068            }
     2069
     2070            if (pPrimaryDevice)
     2071            {
     2072                for (UINT i = 0; i < cSurfs; ++i)
     2073                {
     2074                    PVBOXWDDMDISP_ALLOCATION pAllocation = &pRc->aAllocations[i];
     2075                    IDirect3DSurface9 *pRt;
     2076                    IDirect3DSurface9 *pSecondaryOpenedRt;
     2077                    HANDLE hSharedHandle = NULL;
     2078                    hr = pPrimaryDevice->CreateRenderTarget(
     2079                            pParams->BackBufferWidth, pParams->BackBufferHeight,
     2080                            pParams->BackBufferFormat,
     2081                            pParams->MultiSampleType,
     2082                            pParams->MultiSampleQuality,
     2083                            TRUE, /*BOOL Lockable*/
     2084                            &pRt,
     2085                            &hSharedHandle);
     2086                    Assert(hr == S_OK);
     2087                    if (hr == S_OK)
     2088                    {
     2089                        Assert(hSharedHandle != NULL);
     2090                        /* open render target for primary device */
     2091                        hr = pDevice9If->CreateRenderTarget(
     2092                                    pParams->BackBufferWidth, pParams->BackBufferHeight,
     2093                                    pParams->BackBufferFormat,
     2094                                    pParams->MultiSampleType,
     2095                                    pParams->MultiSampleQuality,
     2096                                    TRUE, /*BOOL Lockable*/
     2097                                    &pSecondaryOpenedRt,
     2098                                    &hSharedHandle);
     2099                        Assert(hr == S_OK);
     2100                        if (hr == S_OK)
     2101                        {
     2102                            pAllocation->pD3DIf = pRt;
     2103                            pAllocation->pSecondaryOpenedD3DIf = pSecondaryOpenedRt;
     2104                            pAllocation->hSharedHandle = hSharedHandle;
     2105                            continue;
     2106                        }
     2107                        pRt->Release();
     2108                    }
     2109
     2110                    for (UINT j = 0; j < i; ++j)
     2111                    {
     2112                        PVBOXWDDMDISP_ALLOCATION pAlloc = &pRc->aAllocations[j];
     2113                        pAlloc->pD3DIf->Release();
     2114                        pAlloc->pSecondaryOpenedD3DIf->Release();
     2115                    }
     2116
     2117                    break;
     2118                }
     2119            }
     2120            else
     2121            {
     2122                pDevice->iPrimaryScreen = iScreen;
     2123                hr = vboxWddmRenderTargetUpdate(pDevice, pRc, 0);
     2124                Assert(hr == S_OK);
     2125            }
     2126
     2127            if (hr == S_OK)
     2128            {
     2129                for (UINT i = 0; i < cSurfs; ++i)
     2130                {
     2131                    PVBOXWDDMDISP_ALLOCATION pAllocation = &pRc->aAllocations[i];
     2132                    pAllocation->enmD3DIfType = VBOXDISP_D3DIFTYPE_SURFACE;
     2133                    hr = vboxWddmSurfSynchMem(pRc, pAllocation);
     2134                    Assert(hr == S_OK);
     2135                    if (hr != S_OK)
     2136                    {
     2137                        break;
     2138                    }
     2139                }
     2140
     2141#ifndef VBOXWDDM_WITH_VISIBLE_FB
     2142                if (!pPrimaryDevice)
     2143                {
     2144                    if (hr == S_OK)
     2145                    {
     2146                        IDirect3DSurface9* pD3D9Surf;
     2147                        hr = pDevice9If->CreateRenderTarget(
     2148                                pParams->BackBufferWidth, pParams->BackBufferHeight,
     2149                                pParams->BackBufferFormat,
     2150                                pParams->MultiSampleType,
     2151                                pParams->MultiSampleQuality,
     2152                                bLockable,
     2153                                &pD3D9Surf,
     2154                                NULL /* HANDLE* pSharedHandle */
     2155                                );
     2156                        Assert(hr == S_OK);
     2157                        if (hr == S_OK)
     2158                        {
     2159                            pDevice->pRenderTargetFbCopy = pD3D9Surf;
     2160                        }
     2161                    }
     2162                }
     2163#endif
     2164
     2165                if (hr != S_OK)
     2166                {
     2167                    for (UINT i = 0; i < cSurfs; ++i)
     2168                    {
     2169                        PVBOXWDDMDISP_ALLOCATION pAllocation = &pRc->aAllocations[i];
     2170                        pAllocation->pD3DIf->Release();
     2171                    }
     2172                }
     2173            }
     2174
     2175            if (hr != S_OK)
     2176            {
     2177                pDevice9If->Release();
     2178                --pDevice->cScreens;
     2179                Assert(pDevice->cScreens < UINT32_MAX/2);
     2180            }
     2181        }
     2182
     2183        if (hr != S_OK)
     2184        {
     2185            HRESULT tmpHr = VBoxDispWndDestroy(pAdapter, pScreen->hWnd);
     2186            Assert(tmpHr == S_OK);
     2187        }
     2188    }
     2189
     2190    return hr;
     2191}
     2192#endif
     2193static HRESULT vboxWddmD3DDeviceCreateDummy(PVBOXWDDMDISP_DEVICE pDevice)
     2194{
     2195    HRESULT hr;
     2196    PVBOXWDDMDISP_RESOURCE pRc = vboxResourceAlloc(2);
     2197    Assert(pRc);
     2198    if (pRc)
     2199    {
     2200        pRc->RcDesc.enmFormat = D3DDDIFMT_A8R8G8B8;
     2201        pRc->RcDesc.enmMultisampleType = D3DDDIMULTISAMPLE_NONE;
     2202        pRc->RcDesc.MultisampleQuality = 0;
     2203        for (UINT i = 0 ; i < pRc->cAllocations; ++i)
     2204        {
     2205            PVBOXWDDMDISP_ALLOCATION pAlloc = &pRc->aAllocations[i];
     2206            pAlloc->SurfDesc.width = 0x400;
     2207            pAlloc->SurfDesc.height = 0x300;
     2208            pAlloc->SurfDesc.format = D3DDDIFMT_A8R8G8B8;
     2209        }
     2210
     2211        PVBOXWDDMDISP_SWAPCHAIN pSwapchain;
     2212        hr = vboxWddmSwapchainCreateIfForRc(pDevice, pRc, &pSwapchain);
     2213        Assert(hr == S_OK);
     2214        if (hr != S_OK)
     2215            vboxResourceFree(pRc);
     2216    }
     2217    else
     2218    {
     2219        hr = E_OUTOFMEMORY;
     2220    }
     2221
     2222    return hr;
     2223}
     2224
     2225DECLINLINE(IDirect3DDevice9*) vboxWddmD3DDeviceGet(PVBOXWDDMDISP_DEVICE pDevice)
     2226{
     2227    if (pDevice->pDevice9If)
     2228        return pDevice->pDevice9If;
     2229    HRESULT hr = vboxWddmD3DDeviceCreateDummy(pDevice);
     2230    Assert(hr == S_OK);
     2231    Assert(pDevice->pDevice9If);
     2232    return pDevice->pDevice9If;
     2233}
     2234
     2235#if 0
     2236static HRESULT APIENTRY vboxWddmDDevDestroyResource(HANDLE hDevice, HANDLE hResource);
     2237
     2238static HRESULT vboxWddmD3DDeviceUpdate(PVBOXWDDMDISP_DEVICE pDevice, UINT iScreen, PVBOXWDDMDISP_RESOURCE pRc, D3DPRESENT_PARAMETERS * pParams, BOOL bLockable)
     2239{
     2240    UINT cSurfs = pParams->BackBufferCount + 1;
     2241    Assert(pRc->cAllocations = cSurfs);
     2242    Assert(iScreen == pDevice->iPrimaryScreen);
     2243    PVBOXWDDMDISP_SCREEN pScreen = &pDevice->aScreens[iScreen];
     2244    PVBOXWDDMDISP_RESOURCE pCurRc = pScreen->pRenderTargetRc;
     2245    IDirect3DDevice9Ex *pNewDevice;
     2246    HRESULT hr = pDevice->pAdapter->D3D.pfnVBoxWineExD3DDev9Update((IDirect3DDevice9Ex*)pScreen->pDevice9If, pParams, &pNewDevice);
     2247    Assert(hr == S_OK);
     2248    if (hr == S_OK)
     2249    {
     2250        pScreen->pDevice9If->Release();
     2251        pScreen->pDevice9If = pNewDevice;
     2252        pScreen->pRenderTargetRc = pRc;
     2253
     2254        for (UINT i = 0; i < cSurfs; ++i)
     2255        {
     2256            PVBOXWDDMDISP_ALLOCATION pAllocation = &pRc->aAllocations[i];
     2257            pAllocation->enmD3DIfType = VBOXDISP_D3DIFTYPE_SURFACE;
     2258        }
     2259
     2260#ifndef VBOXWDDM_WITH_VISIBLE_FB
     2261        if (pDevice->pRenderTargetFbCopy)
     2262        {
     2263            pDevice->pRenderTargetFbCopy->Release();
     2264        }
     2265        IDirect3DSurface9* pD3D9Surf;
     2266        hr = pNewDevice->CreateRenderTarget(
     2267                    pParams->BackBufferWidth, pParams->BackBufferHeight,
     2268                    pParams->BackBufferFormat,
     2269                    pParams->MultiSampleType,
     2270                    pParams->MultiSampleQuality,
     2271                    bLockable,
     2272                    &pD3D9Surf,
     2273                    NULL /* HANDLE* pSharedHandle */
     2274                    );
     2275        Assert(hr == S_OK);
     2276        if (hr == S_OK)
     2277        {
     2278            pDevice->pRenderTargetFbCopy = pD3D9Surf;
     2279        }
     2280#endif
     2281        if (hr == S_OK)
     2282        {
     2283            hr = vboxWddmRenderTargetUpdate(pDevice, pRc, 0);
     2284            Assert(hr == S_OK);
     2285            if (hr == S_OK)
     2286            {
     2287                for (UINT i = 0; i < cSurfs; ++i)
     2288                {
     2289                    PVBOXWDDMDISP_ALLOCATION pAllocation = &pRc->aAllocations[i];
     2290                    pAllocation->enmD3DIfType = VBOXDISP_D3DIFTYPE_SURFACE;
     2291                    hr = vboxWddmSurfSynchMem(pRc, pAllocation);
     2292                    Assert(hr == S_OK);
     2293                    if (hr != S_OK)
     2294                    {
     2295                        break;
     2296                    }
     2297                }
     2298            }
     2299        }
     2300    }
     2301
     2302
     2303    if (!pCurRc->hResource)
     2304    {
     2305        HRESULT tmpHr = vboxWddmDDevDestroyResource(pDevice, pCurRc);
     2306        Assert(tmpHr == S_OK);
     2307    }
     2308
     2309    return hr;
     2310}
     2311#endif
     2312/******/
     2313
    16802314
    16812315static CRITICAL_SECTION g_VBoxCritSect;
     
    30163650    if (VBOXDISPMODE_IS_3D(pDevice->pAdapter))
    30173651    {
    3018         PVBOXWDDMDISP_SCREEN pScreen = &pDevice->aScreens[pDevice->iPrimaryScreen];
    3019 
    3020         Assert(pRc != pScreen->pRenderTargetRc || pScreen->iRenderTargetFrontBuf != pData->SubResourceIndex);
     3652//        Assert(pRc != pScreen->pRenderTargetRc || pScreen->iRenderTargetFrontBuf != pData->SubResourceIndex);
    30213653
    30223654        if (pRc->aAllocations[0].enmD3DIfType == VBOXDISP_D3DIFTYPE_TEXTURE)
     
    36544286            pAllocation->hAllocation = NULL;
    36554287            pAllocation->enmType = VBOXWDDM_ALLOC_TYPE_UMD_RC_GENERIC;
     4288            pAllocation->pRc = pRc;
    36564289            pAllocation->pvMem = (void*)pSurf->pSysMem;
    36574290            pAllocation->SurfDesc.pitch = pSurf->SysMemPitch;
     
    39034536                bIssueCreateResource = true;
    39044537                Assert(pResource->SurfCount);
    3905                 PVBOXWDDMDISP_SCREEN pScreen = &pDevice->aScreens[pResource->VidPnSourceId];
    3906                 bool bDevAdjusted = pScreen->pRenderTargetRc && pScreen->pRenderTargetRc->hResource;
    3907                 bool bIsPrimary = !(pDevice->aScreens[pDevice->iPrimaryScreen].pRenderTargetRc
    3908                         && pDevice->aScreens[pDevice->iPrimaryScreen].pRenderTargetRc->hResource);
    3909                 if (!bDevAdjusted)
    3910                 {
    3911                     D3DPRESENT_PARAMETERS params;
    3912                     memset(&params, 0, sizeof (params));
    3913                     params.BackBufferWidth = pResource->pSurfList[0].Width;
    3914                     params.BackBufferHeight = pResource->pSurfList[0].Height;
    3915                     params.BackBufferFormat = vboxDDI2D3DFormat(pResource->Format);
    3916                     Assert(pResource->SurfCount);
    3917                     params.BackBufferCount = bIsPrimary ? pResource->SurfCount - 1 : 0;
    3918                     params.MultiSampleType = vboxDDI2D3DMultiSampleType(pResource->MultisampleType);
    3919                     if (pResource->Flags.DiscardRenderTarget)
    3920                         params.SwapEffect = D3DSWAPEFFECT_DISCARD;
    3921 //                    params.hDeviceWindow = hWnd;
    3922                                 /* @todo: it seems there should be a way to detect this correctly since
    3923                                  * our vboxWddmDDevSetDisplayMode will be called in case we are using full-screen */
    3924                     params.Windowed = TRUE;
    3925                     //            params.EnableAutoDepthStencil = FALSE;
    3926                     //            params.AutoDepthStencilFormat = D3DFMT_UNKNOWN;
    3927                     //            params.Flags;
    3928                     //            params.FullScreen_RefreshRateInHz;
    3929                     //            params.FullScreen_PresentationInterval;
    3930 
    3931                     if (!pScreen->pDevice9If)
    3932                     {
    3933 #ifdef VBOXDISP_EARLYCREATEDEVICE
    3934                         Assert(!bIsPrimary);
    3935 #endif
    3936                         hr = vboxWddmD3DDeviceCreate(pDevice, pResource->VidPnSourceId, pRc, &params, !pResource->Flags.NotLockable /*BOOL bLockable*/);
    3937                         Assert(hr == S_OK);
    3938                     }
    3939                     else
    3940                     {
    3941                         Assert(bIsPrimary);
    3942                         hr = vboxWddmD3DDeviceUpdate(pDevice, pResource->VidPnSourceId, pRc, &params, !pResource->Flags.NotLockable /*BOOL bLockable*/);
    3943                         Assert(hr == S_OK);
    3944                     }
     4538                if (RTListIsEmpty(&pDevice->SwapchainList))
     4539                {
     4540                    PVBOXWDDMDISP_SWAPCHAIN pSwapchain;
     4541                    hr = vboxWddmSwapchainCreateIfForRc(pDevice, pRc, &pSwapchain);
     4542                    Assert(hr == S_OK);
    39454543                }
    39464544                else
    39474545                {
    3948                     PVBOXWDDMDISP_SCREEN pScreen = &pDevice->aScreens[pDevice->iPrimaryScreen];
    3949                     Assert(pScreen->hWnd);
    3950                     Assert(pScreen->pDevice9If);
    39514546                    for (UINT i = 0; i < pResource->SurfCount; ++i)
    39524547                    {
     
    39544549
    39554550                        IDirect3DSurface9* pD3D9Surf;
    3956                         hr = pScreen->pDevice9If->CreateRenderTarget(pAllocation->SurfDesc.width,
     4551                        hr = pDevice->pDevice9If->CreateRenderTarget(pAllocation->SurfDesc.width,
    39574552                                pAllocation->SurfDesc.height,
    39584553                                vboxDDI2D3DFormat(pResource->Format),
     
    39884583            else
    39894584            {
    3990                 PVBOXWDDMDISP_SCREEN pScreen = &pDevice->aScreens[pDevice->iPrimaryScreen];
    3991                 Assert(pScreen->hWnd);
    3992                 Assert(pScreen->pDevice9If);
     4585//                PVBOXWDDMDISP_SCREEN pScreen = &pDevice->aScreens[pDevice->iPrimaryScreen];
     4586//                Assert(pScreen->hWnd);
     4587//                Assert(pScreen->pDevice9If);
    39934588                Assert(0);
    39944589            }
     
    41734768                pAlloc->pSecondaryOpenedD3DIf->Release();
    41744769
     4770            PVBOXWDDMDISP_SWAPCHAIN pSwapchain = vboxWddmSwapchainForAlloc(pAlloc);
     4771            if (pSwapchain)
     4772            {
     4773                PVBOXWDDMDISP_RENDERTGT pRt = vboxWddmSwapchainRtForAlloc(pSwapchain, pAlloc);
     4774                vboxWddmSwapchainRtRemove(pSwapchain, pRt);
     4775                Assert(!vboxWddmSwapchainForAlloc(pAlloc));
     4776            }
     4777
    41754778            EnterCriticalSection(&pDevice->DirtyAllocListLock);
    41764779            if (pAlloc->DirtyAllocListEntry.pNext)
     
    42314834    Assert(pAlloc->enmD3DIfType == VBOXDISP_D3DIFTYPE_SURFACE);
    42324835    Assert(pAlloc->hAllocation);
    4233     PVBOXWDDMDISP_SCREEN pScreen = &pDevice->aScreens[pRc->RcDesc.VidPnSourceId];
    4234     Assert(pScreen->hWnd);
    4235     Assert(pScreen->pDevice9If);
     4836//    PVBOXWDDMDISP_SCREEN pScreen = &pDevice->aScreens[pRc->RcDesc.VidPnSourceId];
     4837//    Assert(pScreen->hWnd);
     4838//    Assert(pScreen->pDevice9If);
    42364839    D3DDDICB_SETDISPLAYMODE DdiDm = {0};
    42374840    DdiDm.hPrimaryAllocation = pAlloc->hAllocation;
    42384841//    DdiDm.PrivateDriverFormatAttribute = 0;
    4239     Assert(pScreen->pRenderTargetRc == pRc);
    4240     Assert(pScreen->iRenderTargetFrontBuf == pData->SubResourceIndex);
     4842//    Assert(pScreen->pRenderTargetRc == pRc);
     4843//    Assert(pScreen->iRenderTargetFrontBuf == pData->SubResourceIndex);
    42414844
    42424845#if 0
     
    42624865    if (VBOXDISPMODE_IS_3D(pDevice->pAdapter))
    42634866    {
     4867#if 1
     4868        PVBOXWDDMDISP_RESOURCE pRc = (PVBOXWDDMDISP_RESOURCE)pData->hSrcResource;
     4869        Assert(pRc);
     4870        Assert(pRc->cAllocations > pData->SrcSubResourceIndex);
     4871        PVBOXWDDMDISP_ALLOCATION pAlloc = &pRc->aAllocations[pData->SrcSubResourceIndex];
     4872        hr = vboxWddmSwapchainPresent(pDevice, pAlloc);
     4873        Assert(hr == S_OK);
     4874#else
    42644875        PVBOXWDDMDISP_RESOURCE pRc = (PVBOXWDDMDISP_RESOURCE)pData->hSrcResource;
    42654876        Assert(pRc);
     
    43054916        Assert(hr == S_OK);
    43064917#endif
     4918#endif
    43074919    }
    43084920#if 0
     
    43104922#endif
    43114923    {
    4312         if (pData->Flags.Flip)
    4313         {
    4314             Assert(pData->hSrcResource);
    4315             PVBOXWDDMDISP_RESOURCE pRc = (PVBOXWDDMDISP_RESOURCE)pData->hSrcResource;
    4316             PVBOXWDDMDISP_SCREEN pScreen = &pDevice->aScreens[pRc->RcDesc.VidPnSourceId];
    4317             Assert(pScreen->hWnd);
    4318             Assert(pScreen->pDevice9If);
    4319             Assert(pScreen->pRenderTargetRc == pRc);
    4320             Assert(pRc->cAllocations >= 2);
    4321             Assert(pRc->aAllocations[0].enmD3DIfType == VBOXDISP_D3DIFTYPE_SURFACE);
    4322             Assert(pRc->RcDesc.fFlags.RenderTarget);
    4323             uint32_t iNewRTFB = (pScreen->iRenderTargetFrontBuf + 1) % pRc->cAllocations;
    4324 
    4325             Assert(pScreen->iRenderTargetFrontBuf != iNewRTFB);
    4326             Assert(pData->SrcSubResourceIndex == iNewRTFB);
    4327 
    4328             vboxWddmRenderTargetUpdate(pDevice, pRc, iNewRTFB);
    4329 
    4330             /* assign a new frontbuffer index */
    4331             pScreen->iRenderTargetFrontBuf = iNewRTFB;
    4332 
    4333             VBOXVDBG_RTGT_STATECHECK(pDevice);
    4334         }
     4924//        if (pData->Flags.Flip)
     4925//        {
     4926//            Assert(pData->hSrcResource);
     4927//            PVBOXWDDMDISP_RESOURCE pRc = (PVBOXWDDMDISP_RESOURCE)pData->hSrcResource;
     4928//            PVBOXWDDMDISP_SCREEN pScreen = &pDevice->aScreens[pRc->RcDesc.VidPnSourceId];
     4929//            Assert(pScreen->hWnd);
     4930//            Assert(pScreen->pDevice9If);
     4931//            Assert(pScreen->pRenderTargetRc == pRc);
     4932//            Assert(pRc->cAllocations >= 2);
     4933//            Assert(pRc->aAllocations[0].enmD3DIfType == VBOXDISP_D3DIFTYPE_SURFACE);
     4934//            Assert(pRc->RcDesc.fFlags.RenderTarget);
     4935//            uint32_t iNewRTFB = (pScreen->iRenderTargetFrontBuf + 1) % pRc->cAllocations;
     4936//
     4937//            Assert(pScreen->iRenderTargetFrontBuf != iNewRTFB);
     4938//            Assert(pData->SrcSubResourceIndex == iNewRTFB);
     4939//
     4940//            vboxWddmRenderTargetUpdate(pDevice, pRc, iNewRTFB);
     4941//
     4942//            /* assign a new frontbuffer index */
     4943//            pScreen->iRenderTargetFrontBuf = iNewRTFB;
     4944//
     4945//            VBOXVDBG_RTGT_STATECHECK(pDevice);
     4946//        }
    43354947        D3DDDICB_PRESENT DdiPresent = {0};
    43364948        if (pData->hSrcResource)
     
    44855097    if (VBOXDISPMODE_IS_3D(pDevice->pAdapter))
    44865098    {
    4487         Assert(pDevice->cScreens);
    4488         UINT cProcessed = 0;
    4489         for (UINT i = 0; cProcessed < pDevice->cScreens && i < RT_ELEMENTS(pDevice->aScreens); ++i)
    4490         {
    4491             PVBOXWDDMDISP_SCREEN pScreen = &pDevice->aScreens[i];
    4492             if (pScreen->pDevice9If)
    4493             {
    4494                 ++cProcessed;
    4495 //                if (pScreen->pRenderTargetRc->cAllocations == 1)
    4496 //                {
    4497 //                    hr = pScreen->pDevice9If->Present(NULL, NULL, NULL, NULL);
    4498 //                    Assert(hr == S_OK);
    4499 //                }
    4500 //                else
    4501                 {
    4502                     hr = pDevice->pAdapter->D3D.pfnVBoxWineExD3DDev9Flush((IDirect3DDevice9Ex*)pScreen->pDevice9If);
     5099//        Assert(pDevice->cScreens);
     5100//        UINT cProcessed = 0;
     5101//        for (UINT i = 0; cProcessed < pDevice->cScreens && i < RT_ELEMENTS(pDevice->aScreens); ++i)
     5102//        {
     5103//            PVBOXWDDMDISP_SCREEN pScreen = &pDevice->aScreens[i];
     5104//            if (pScreen->pDevice9If)
     5105//            {
     5106//                ++cProcessed;
     5107////                if (pScreen->pRenderTargetRc->cAllocations == 1)
     5108////                {
     5109////                    hr = pScreen->pDevice9If->Present(NULL, NULL, NULL, NULL);
     5110////                    Assert(hr == S_OK);
     5111////                }
     5112////                else
     5113                {
     5114                    hr = pDevice->pAdapter->D3D.pfnVBoxWineExD3DDev9Flush((IDirect3DDevice9Ex*)pDevice->pDevice9If);
    45035115                    Assert(hr == S_OK);
    45045116                }
    4505             }
    4506         }
     5117//            }
     5118//        }
    45075119
    45085120        vboxWddmNotifySharedChange(pDevice);
     
    48395451    PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
    48405452    Assert(pDevice);
    4841     PVBOXWDDMDISP_SCREEN pScreen = &pDevice->aScreens[pDevice->iPrimaryScreen];
     5453//    PVBOXWDDMDISP_SCREEN pScreen = &pDevice->aScreens[pDevice->iPrimaryScreen];
    48425454    IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
    48435455    PVBOXWDDMDISP_RESOURCE pDstRc = (PVBOXWDDMDISP_RESOURCE)pData->hDstResource;
     
    48455457    Assert(pDstRc->cAllocations > pData->DstSubResourceIndex);
    48465458    Assert(pSrcRc->cAllocations > pData->SrcSubResourceIndex);
    4847     Assert(pDstRc != pScreen->pRenderTargetRc || pScreen->iRenderTargetFrontBuf != pData->DstSubResourceIndex);
    48485459    HRESULT hr = S_OK;
     5460    PVBOXWDDMDISP_ALLOCATION pSrcAlloc = &pSrcRc->aAllocations[pData->SrcSubResourceIndex];
     5461    PVBOXWDDMDISP_ALLOCATION pDstAlloc = &pDstRc->aAllocations[pData->DstSubResourceIndex];
     5462    PVBOXWDDMDISP_SWAPCHAIN pSrcSwapchain = vboxWddmSwapchainForAlloc(pSrcAlloc);
     5463    PVBOXWDDMDISP_SWAPCHAIN pDstSwapchain = vboxWddmSwapchainForAlloc(pDstAlloc);
     5464    Assert(!pDstSwapchain || vboxWddmSwapchainGetFb(pDstSwapchain)->pAlloc != pDstAlloc);
    48495465    /* try StretchRect */
    48505466    IDirect3DSurface9 *pSrcSurfIf = NULL;
     
    48585474        {
    48595475#ifndef VBOXWDDM_WITH_VISIBLE_FB
    4860             if (pSrcRc == pScreen->pRenderTargetRc && pScreen->iRenderTargetFrontBuf == pData->SrcSubResourceIndex
    4861                     && pScreen->pRenderTargetRc->cAllocations > 1) /* work-around wine backbuffer */
    4862             {
    4863                 PVBOXWDDMDISP_ALLOCATION pSrcAlloc = &pSrcRc->aAllocations[pData->SrcSubResourceIndex];
    4864                 PVBOXWDDMDISP_ALLOCATION pDstAlloc = &pDstRc->aAllocations[pData->DstSubResourceIndex];
     5476            if (pSrcSwapchain && vboxWddmSwapchainGetFb(pSrcSwapchain)->pAlloc != pSrcAlloc
     5477                    && vboxWddmSwapchainNumRTs(pSrcSwapchain) > 1) /* work-around wine backbuffer */
     5478            {
    48655479//                Assert(pSrcAlloc->SurfDesc.width == pDstAlloc->SurfDesc.width);
    48665480//                Assert(pSrcAlloc->SurfDesc.height == pDstAlloc->SurfDesc.height);
     
    48975511#endif
    48985512                {
    4899                     pSrcSurfIf = pDevice->pRenderTargetFbCopy;
     5513                    pSrcSurfIf = pSrcSwapchain->pRenderTargetFbCopy;
    49005514                    Assert(pSrcSurfIf);
    4901                     hr = pDevice9If->GetFrontBufferData(0, pDevice->pRenderTargetFbCopy);
     5515                    hr = pDevice9If->GetFrontBufferData(0, pSrcSurfIf);
    49025516                    Assert(hr == S_OK);
    49035517                    if (hr == S_OK)
     
    51655779    PVBOXWDDMDISP_DEVICE pDevice = (PVBOXWDDMDISP_DEVICE)hDevice;
    51665780    Assert(pDevice);
    5167     PVBOXWDDMDISP_SCREEN pScreen = &pDevice->aScreens[pDevice->iPrimaryScreen];
     5781//    PVBOXWDDMDISP_SCREEN pScreen = &pDevice->aScreens[pDevice->iPrimaryScreen];
    51685782    IDirect3DDevice9 * pDevice9If = VBOXDISP_D3DEV(pDevice);
    51695783    PVBOXWDDMDISP_RESOURCE pRc = (PVBOXWDDMDISP_RESOURCE)pData->hRenderTarget;
    51705784    Assert(pRc);
    51715785    Assert(pData->SubResourceIndex < pRc->cAllocations);
    5172     PVBOXWDDMDISP_SCREEN pVisibleScreen = pRc->RcDesc.fFlags.Primary ? &pDevice->aScreens[pRc->RcDesc.VidPnSourceId] : pScreen;
    5173     if (pRc == pVisibleScreen->pRenderTargetRc)
     5786    PVBOXWDDMDISP_ALLOCATION pAlloc = &pRc->aAllocations[pData->SubResourceIndex];
     5787    PVBOXWDDMDISP_SWAPCHAIN pSwapchain = vboxWddmSwapchainForAlloc(pAlloc);
     5788//    PVBOXWDDMDISP_SCREEN pVisibleScreen = pRc->RcDesc.fFlags.Primary ? &pDevice->aScreens[pRc->RcDesc.VidPnSourceId] : pScreen;
     5789    if (pSwapchain)
    51745790    {
    51755791        /* backbuffer */
    5176         Assert(pData->SubResourceIndex == ((pVisibleScreen->iRenderTargetFrontBuf + 1) % pVisibleScreen->pRenderTargetRc->cAllocations));
     5792        Assert(vboxWddmSwapchainGetBb(pSwapchain)->pAlloc == pAlloc);
    51775793    }
    51785794
    51795795    HRESULT hr = S_OK;
    51805796    IDirect3DSurface9 *pD3D9Surf;
    5181     if (pRc == pScreen->pRenderTargetRc && pRc->cAllocations == 1 && pData->RenderTargetIndex == 0)
     5797    if (pSwapchain && vboxWddmSwapchainNumRTs(pSwapchain) == 1 && pData->RenderTargetIndex == 0)
    51825798    {
    51835799        /* work-around wine double-buffering for the case we have no backbuffers */
     
    53986014    PVBOXWDDMDISP_ADAPTER pAdapter = pDevice->pAdapter;
    53996015//    Assert(!pDevice->cScreens);
    5400 #ifndef VBOXWDDM_WITH_VISIBLE_FB
    5401     if(pDevice->pRenderTargetFbCopy)
    5402         pDevice->pRenderTargetFbCopy->Release();
    5403 #endif
    5404     for (UINT i = 0; i < RT_ELEMENTS(pDevice->aScreens); ++i)
    5405     {
    5406         PVBOXWDDMDISP_SCREEN pScreen = &pDevice->aScreens[i];
    5407         if (pScreen->pDevice9If)
    5408         {
    5409             pScreen->pDevice9If->Release();
    5410             Assert(pScreen->hWnd);
    5411             HRESULT tmpHr = VBoxDispWndDestroy(pAdapter, pScreen->hWnd);
    5412             Assert(tmpHr == S_OK);
    5413         }
    5414     }
     6016    vboxWddmSwapchainDestroyAll(pDevice);
     6017    pDevice->pDevice9If->Release();
    54156018
    54166019    HRESULT hr = vboxDispCmCtxDestroy(pDevice, &pDevice->DefaultContext);
     
    59606563        do
    59616564        {
     6565            RTListInit(&pDevice->SwapchainList);
    59626566            Assert(!pCreateData->AllocationListSize
    59636567                    && !pCreateData->PatchLocationListSize);
     
    62766880    if (bPrimary)
    62776881    {
    6278         PVBOXWDDMDISP_SCREEN pScreen = &pDevice->aScreens[pRc->RcDesc.VidPnSourceId];
    6279         Assert(pRc == pScreen->pRenderTargetRc);
    6280         bFrontBuf = (iAlloc == pScreen->iRenderTargetFrontBuf);
     6882        PVBOXWDDMDISP_SWAPCHAIN pSwapchain = vboxWddmSwapchainForAlloc(pAlloc);
     6883        Assert(pSwapchain);
     6884        bFrontBuf = (vboxWddmSwapchainGetBb(pSwapchain)->pAlloc == pAlloc);
    62816885    }
    62826886    vboxVDbgDoMpPrintF(pDevice, "%s width(%d), height(%d), format(%d), usage(%s), %s", pPrefix,
  • trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispD3D.h

    r32325 r32425  
    2323
    2424#define VBOXWDDMDISP_MAX_VERTEX_STREAMS 16
     25#define VBOXWDDMDISP_MAX_SWAPCHAIN_SIZE 16
    2526
    2627#ifdef VBOX_WITH_VIDEOHWACCEL
     
    9192} VBOXWDDMDISP_INDICES_INFO;
    9293
    93 typedef struct VBOXWDDMDISP_SCREEN
    94 {
    95     IDirect3DDevice9 *pDevice9If;
    96     struct VBOXWDDMDISP_RESOURCE *pRenderTargetRc;
    97 //    struct VBOXWDDMDISP_RESOURCE *pDstSharedRc;
    98     uint32_t iRenderTargetFrontBuf;
     94typedef struct VBOXWDDMDISP_RENDERTGT_FLAGS
     95{
     96    union
     97    {
     98        struct
     99        {
     100            UINT bAdded : 1;
     101            UINT bRemoved : 1;
     102            UINT Reserved : 30;
     103        };
     104        uint32_t Value;
     105    };
     106}VBOXWDDMDISP_RENDERTGT_FLAGS;
     107
     108typedef struct VBOXWDDMDISP_RENDERTGT
     109{
     110    struct VBOXWDDMDISP_ALLOCATION *pAlloc;
     111    UINT cNumFlips;
     112    VBOXWDDMDISP_RENDERTGT_FLAGS fFlags;
     113} VBOXWDDMDISP_RENDERTGT, *PVBOXWDDMDISP_RENDERTGT;
     114
     115#define VBOXWDDMDISP_INDEX_UNDEFINED (~0)
     116typedef struct VBOXWDDMDISP_SWAPCHAIN_FLAGS
     117{
     118    union
     119    {
     120        struct
     121        {
     122            UINT bChanged : 1;
     123            UINT bInited  : 1;
     124            UINT Reserved : 30;
     125        };
     126        uint32_t Value;
     127    };
     128}VBOXWDDMDISP_SWAPCHAIN_FLAGS;
     129
     130typedef struct VBOXWDDMDISP_SWAPCHAIN
     131{
     132    RTLISTNODE ListEntry;
     133    UINT iBB; /* Backbuffer index */
     134    UINT cRTs; /* Number of render targets in the swapchain */
     135    VBOXWDDMDISP_SWAPCHAIN_FLAGS fFlags;
     136#ifndef VBOXWDDM_WITH_VISIBLE_FB
     137    IDirect3DSurface9 *pRenderTargetFbCopy;
     138#endif
     139    IDirect3DSwapChain9 *pSwapChainIf;
    99140    HWND hWnd;
    100 } VBOXWDDMDISP_SCREEN, *PVBOXWDDMDISP_SCREEN;
     141    VBOXWDDMDISP_RENDERTGT aRTs[VBOXWDDMDISP_MAX_SWAPCHAIN_SIZE];
     142} VBOXWDDMDISP_SWAPCHAIN, *PVBOXWDDMDISP_SWAPCHAIN;
     143
     144
     145//typedef struct VBOXWDDMDISP_SCREEN
     146//{
     147//    RTLISTNODE SwapchainList;
     148//    IDirect3DDevice9 *pDevice9If;
     149////    struct VBOXWDDMDISP_RESOURCE *pDstSharedRc;
     150//    uint32_t iRenderTargetFrontBuf;
     151//    HWND hWnd;
     152//} VBOXWDDMDISP_SCREEN, *PVBOXWDDMDISP_SCREEN;
    101153
    102154typedef struct VBOXWDDMDISP_DEVICE
     
    104156    HANDLE hDevice;
    105157    PVBOXWDDMDISP_ADAPTER pAdapter;
     158    IDirect3DDevice9 *pDevice9If;
     159    RTLISTNODE SwapchainList;
    106160    UINT u32IfVersion;
    107161    UINT uRtVersion;
     
    110164    UINT cbCmdBuffer;
    111165    D3DDDI_CREATEDEVICEFLAGS fFlags;
    112 #ifndef VBOXWDDM_WITH_VISIBLE_FB
    113     IDirect3DSurface9 *pRenderTargetFbCopy;
    114 #endif
    115166    /* number of StreamSources set */
    116167    UINT cStreamSources;
     
    128179    CRITICAL_SECTION DirtyAllocListLock;
    129180    RTLISTNODE DirtyAllocList;
    130 
    131     UINT iPrimaryScreen;
    132     UINT cScreens;
    133     VBOXWDDMDISP_SCREEN aScreens[VBOX_VIDEO_MAX_SCREENS];
    134181} VBOXWDDMDISP_DEVICE, *PVBOXWDDMDISP_DEVICE;
    135182
     
    159206    D3DKMT_HANDLE hAllocation;
    160207    VBOXWDDM_ALLOC_TYPE enmType;
     208    struct VBOXWDDMDISP_RESOURCE *pRc;
    161209    void* pvMem;
    162210    /* object type is defined by enmD3DIfType enum */
     
    169217    VBOXWDDM_DIRTYREGION DirtyRegion; /* <- dirty region to notify host about */
    170218    VBOXWDDM_SURFACE_DESC SurfDesc;
     219    PVBOXWDDMDISP_SWAPCHAIN pSwapchain;
    171220} VBOXWDDMDISP_ALLOCATION, *PVBOXWDDMDISP_ALLOCATION;
    172221
     
    199248#define VBOXDISP_D3DEV(_p) (_p)->pDevice9If
    200249#else
    201 #define VBOXDISP_D3DEV(_p) vboxWddmD3DDeviceGetPrimary(_p)
     250#define VBOXDISP_D3DEV(_p) vboxWddmD3DDeviceGet(_p)
    202251#endif
    203252
  • trunk/src/VBox/Additions/WINNT/Graphics/Display/wddm/VBoxDispMp.cpp

    r31797 r32425  
    139139        VBOXWDDMDISP_CONTEXT *pContext = (VBOXWDDMDISP_CONTEXT*)pHdr->u64UmData;
    140140        PVBOXVIDEOCM_CMD_RECTS_INTERNAL pCmdInternal = (PVBOXVIDEOCM_CMD_RECTS_INTERNAL)(((uint8_t*)pHdr) + sizeof (VBOXVIDEOCM_CMD_HDR));
    141         UINT iScreen = pContext->pDevice->cScreens == 1 ? pContext->pDevice->iPrimaryScreen : pCmdInternal->VidPnSourceId;
    142         PVBOXWDDMDISP_SCREEN pScreen = &pContext->pDevice->aScreens[iScreen];
    143         Assert(pScreen->hWnd);
    144         Assert(pScreen->pDevice9If);
    145         pRegions->hWnd = pScreen->hWnd;
     141//        UINT iScreen = pContext->pDevice->cScreens == 1 ? pContext->pDevice->iPrimaryScreen : pCmdInternal->VidPnSourceId;
     142//        PVBOXWDDMDISP_SCREEN pScreen = &pContext->pDevice->aScreens[iScreen];
     143//        Assert(pScreen->hWnd);
     144//        Assert(pScreen->pDevice9If);
     145//        pRegions->hWnd = pScreen->hWnd;
     146        PVBOXWDDMDISP_SWAPCHAIN pSwapchain = RTListNodeGetLast(&pContext->pDevice->SwapchainList, VBOXWDDMDISP_SWAPCHAIN, ListEntry);
     147        Assert(pSwapchain);
     148        pRegions->hWnd = pSwapchain->hWnd;
    146149        pRegions->pRegions = &pCmdInternal->Cmd;
    147150    }
Note: See TracChangeset for help on using the changeset viewer.

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