VirtualBox

Ignore:
Timestamp:
Jun 24, 2013 2:30:18 PM (11 years ago)
Author:
vboxsync
Message:

wddm/crOpenGL: r0-based visible regions handling, r0-based chromium commands submission debugged, more on new presentation mechanism, cleanup, etc.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPMisc.cpp

    r45132 r46757  
    194194        pSwapchain->width = w;
    195195        pSwapchain->height = h;
    196         VBoxWddmVrListInit(&pSwapchain->VisibleRegions);
     196        VBoxVrListInit(&pSwapchain->VisibleRegions);
    197197    }
    198198    return pSwapchain;
     
    225225    if (!cRefs)
    226226    {
    227         VBoxWddmVrListClear(&pSwapchain->VisibleRegions);
     227        VBoxVrListClear(&pSwapchain->VisibleRegions);
    228228        vboxWddmMemFree(pSwapchain);
    229229    }
     
    313313    vboxWddmSwapchainAllocRemoveAllInternal(pDevExt, pSwapchain, TRUE);
    314314
    315 #ifndef VBOX_WDDM_MINIPORT_WITH_VISIBLE_RECTS
    316     Assert(pSwapchain->pContext);
    317     if (pSwapchain->pContext)
    318     {
    319         NTSTATUS tmpStatus = vboxVdmaGgCmdCancel(pDevExt, pSwapchain->pContext, pSwapchain);
    320         if (tmpStatus != STATUS_SUCCESS)
    321         {
    322             WARN(("vboxVdmaGgCmdCancel returned Status (0x%x)", tmpStatus));
    323         }
    324     }
    325 #endif
    326 
    327315    vboxWddmSwapchainRelease(pSwapchain);
    328316}
     
    350338    RemoveEntryList(&pSwapchain->DevExtListEntry);
    351339    pSwapchain->hSwapchainKm = NULL;
    352     VBoxWddmVrListClear(&pSwapchain->VisibleRegions);
     340    VBoxVrListClear(&pSwapchain->VisibleRegions);
    353341    vboxWddmSwapchainRelease(pSwapchain);
    354342}
     
    412400    if (cbSize < RT_OFFSETOF(VBOXDISPIFESCAPE_SWAPCHAININFO, SwapchainInfo.ahAllocs[pSwapchainInfo->SwapchainInfo.cAllocs]))
    413401        return STATUS_INVALID_PARAMETER;
     402
     403    if (!pSwapchainInfo->SwapchainInfo.winHostID)
     404    {
     405        WARN(("Zero winHostID specified!"));
     406        return STATUS_INVALID_PARAMETER;
     407    }
    414408
    415409    PVBOXWDDM_SWAPCHAIN pSwapchain = NULL;
     
    499493//        memset(&pSwapchain->ViewRect, 0, sizeof (pSwapchain->ViewRect));
    500494        /* @todo: do we really need to zero this up here ? */
    501         VBoxWddmVrListClear(&pSwapchain->VisibleRegions);
     495        VBoxVrListClear(&pSwapchain->VisibleRegions);
    502496
    503497        vboxWddmSwapchainAllocRemoveAll(pDevExt, pSwapchain);
     
    510504            }
    511505            pSwapchain->hSwapchainUm = pSwapchainInfo->SwapchainInfo.hSwapchainUm;
     506            if (pSwapchain->winHostID != pSwapchainInfo->SwapchainInfo.winHostID)
     507            {
     508                pSwapchain->fExposed = FALSE;
     509                pSwapchain->winHostID = pSwapchainInfo->SwapchainInfo.winHostID;
     510            }
    512511        }
    513512        else
     
    14091408            break;
    14101409
     1410        Assert(0);
     1411
    14111412        Status = vboxVideoAMgrCtxAllocDestroy(pCtx, pRef->hSessionHandle);
    14121413        Assert(Status == STATUS_SUCCESS);
     
    16051606#endif
    16061607
    1607 
    1608 /* visible rects */
    1609 typedef struct VBOXWDDMVR_REG
    1610 {
    1611     LIST_ENTRY ListEntry;
    1612     RECT Rect;
    1613 } VBOXWDDMVR_REG, *PVBOXWDDMVR_REG;
    1614 
    1615 #define PVBOXWDDMVR_REG_FROM_ENTRY(_pEntry) ((PVBOXWDDMVR_REG)(((uint8_t*)(_pEntry)) - RT_OFFSETOF(VBOXWDDMVR_REG, ListEntry)))
    1616 
    1617 #ifdef DEBUG_misha
    1618 //# define VBOXVDBG_VR_LAL_DISABLE
    1619 #endif
    1620 
    1621 #ifndef VBOXVDBG_VR_LAL_DISABLE
    1622 static LOOKASIDE_LIST_EX g_VBoxWddmVrLookasideList;
    1623 #endif
    1624 
    1625 static PVBOXWDDMVR_REG vboxWddmVrRegCreate()
    1626 {
    1627 #ifndef VBOXVDBG_VR_LAL_DISABLE
    1628     PVBOXWDDMVR_REG pReg = (PVBOXWDDMVR_REG)ExAllocateFromLookasideListEx(&g_VBoxWddmVrLookasideList);
    1629     if (!pReg)
    1630     {
    1631         WARN(("ExAllocateFromLookasideListEx failed!"));
    1632     }
    1633     return pReg;
    1634 #else
    1635     return (PVBOXWDDMVR_REG)vboxWddmMemAlloc(sizeof (VBOXWDDMVR_REG));
    1636 #endif
    1637 }
    1638 
    1639 static void vboxWddmVrRegTerm(PVBOXWDDMVR_REG pReg)
    1640 {
    1641 #ifndef VBOXVDBG_VR_LAL_DISABLE
    1642     ExFreeToLookasideListEx(&g_VBoxWddmVrLookasideList, pReg);
    1643 #else
    1644     vboxWddmMemFree(pReg);
    1645 #endif
    1646 }
    1647 
    1648 void VBoxWddmVrListClear(PVBOXWDDMVR_LIST pList)
    1649 {
    1650     PLIST_ENTRY pNext;
    1651     for (PLIST_ENTRY pEntry = pList->ListHead.Flink; pEntry != &pList->ListHead; pEntry = pNext)
    1652     {
    1653         pNext = pEntry->Flink;
    1654         PVBOXWDDMVR_REG pReg = PVBOXWDDMVR_REG_FROM_ENTRY(pEntry);
    1655         vboxWddmVrRegTerm(pReg);
    1656     }
    1657     VBoxWddmVrListInit(pList);
    1658 }
    1659 
    1660 #define VBOXWDDMVR_MEMTAG 'vDBV'
    1661 
    1662 NTSTATUS VBoxWddmVrInit()
    1663 {
    1664 #ifndef VBOXVDBG_VR_LAL_DISABLE
    1665     NTSTATUS Status = ExInitializeLookasideListEx(&g_VBoxWddmVrLookasideList,
    1666                             NULL, /* PALLOCATE_FUNCTION_EX Allocate */
    1667                             NULL, /* PFREE_FUNCTION_EX Free */
    1668                             NonPagedPool,
    1669                             0, /* ULONG Flags */
    1670                             sizeof (VBOXWDDMVR_REG),
    1671                             VBOXWDDMVR_MEMTAG,
    1672                             0 /* USHORT Depth - reserved, must be null */
    1673                             );
    1674     if (!NT_SUCCESS(Status))
    1675     {
    1676         WARN(("ExInitializeLookasideListEx failed, Status (0x%x)", Status));
    1677         return Status;
    1678     }
    1679 #endif
    1680 
    1681     return STATUS_SUCCESS;
    1682 }
    1683 
    1684 void VBoxWddmVrTerm()
    1685 {
    1686 #ifndef VBOXVDBG_VR_LAL_DISABLE
    1687     ExDeleteLookasideListEx(&g_VBoxWddmVrLookasideList);
    1688 #endif
    1689 }
    1690 
    1691 typedef DECLCALLBACK(int) FNVBOXWDDMVR_CB_COMPARATOR(const VBOXWDDMVR_REG *pReg1, const VBOXWDDMVR_REG *pReg2);
    1692 typedef FNVBOXWDDMVR_CB_COMPARATOR *PFNVBOXWDDMVR_CB_COMPARATOR;
    1693 
    1694 static DECLCALLBACK(int) vboxWddmVrRegNonintersectedComparator(const RECT* pRect1, const RECT* pRect2)
    1695 {
    1696     Assert(!vboxWddmRectIsIntersect(pRect1, pRect2));
    1697     if (pRect1->top != pRect2->top)
    1698         return pRect1->top - pRect2->top;
    1699     return pRect1->left - pRect2->left;
    1700 }
    1701 
    1702 #ifdef DEBUG_misha
    1703 static void vboxWddmVrDbgListDoVerify(PVBOXWDDMVR_LIST pList)
    1704 {
    1705     PLIST_ENTRY pEntry1 = pList->ListHead.Flink;
    1706 
    1707     for (PLIST_ENTRY pEntry1 = pList->ListHead.Flink; pEntry1 != &pList->ListHead; pEntry1 = pEntry1->Flink)
    1708     {
    1709         PVBOXWDDMVR_REG pReg1 = PVBOXWDDMVR_REG_FROM_ENTRY(pEntry1);
    1710         for (PLIST_ENTRY pEntry2 = pEntry1->Flink; pEntry2 != &pList->ListHead; pEntry2 = pEntry2->Flink)
    1711         {
    1712             PVBOXWDDMVR_REG pReg2 = PVBOXWDDMVR_REG_FROM_ENTRY(pEntry2);
    1713             Assert(vboxWddmVrRegNonintersectedComparator(&pReg1->Rect, &pReg2->Rect) < 0);
    1714         }
    1715     }
    1716 }
    1717 
    1718 #define vboxWddmVrDbgListVerify vboxWddmVrDbgListDoVerify
    1719 #else
    1720 #define vboxWddmVrDbgListVerify(_p) do {} while (0)
    1721 #endif
    1722 
    1723 static NTSTATUS vboxWddmVrListUniteIntersection(PVBOXWDDMVR_LIST pList, PVBOXWDDMVR_LIST pIntersection);
    1724 
    1725 #define VBOXWDDMVR_INVALID_COORD (~0UL)
    1726 
    1727 DECLINLINE(void) vboxWddmVrListRegAdd(PVBOXWDDMVR_LIST pList, PVBOXWDDMVR_REG pReg, PLIST_ENTRY pPlace, BOOLEAN fAfter)
    1728 {
    1729     if (fAfter)
    1730         InsertHeadList(pPlace, &pReg->ListEntry);
    1731     else
    1732         InsertTailList(pPlace, &pReg->ListEntry);
    1733     ++pList->cEntries;
    1734     vboxWddmVrDbgListVerify(pList);
    1735 }
    1736 
    1737 DECLINLINE(void) vboxWddmVrListRegRemove(PVBOXWDDMVR_LIST pList, PVBOXWDDMVR_REG pReg)
    1738 {
    1739     RemoveEntryList(&pReg->ListEntry);
    1740     --pList->cEntries;
    1741 }
    1742 
    1743 static void vboxWddmVrListRegAddOrder(PVBOXWDDMVR_LIST pList, PLIST_ENTRY pMemberEntry, PVBOXWDDMVR_REG pReg)
    1744 {
    1745     do
    1746     {
    1747         if (pMemberEntry != &pList->ListHead)
    1748         {
    1749             PVBOXWDDMVR_REG pMemberReg = PVBOXWDDMVR_REG_FROM_ENTRY(pMemberEntry);
    1750             if (vboxWddmVrRegNonintersectedComparator(&pMemberReg->Rect, &pReg->Rect) < 0)
    1751             {
    1752                 pMemberEntry = pMemberEntry->Flink;
    1753                 continue;
    1754             }
    1755         }
    1756         vboxWddmVrListRegAdd(pList, pReg, pMemberEntry, FALSE);
    1757         break;
    1758     } while (1);
    1759 }
    1760 
    1761 static void vboxWddmVrListAddNonintersected(PVBOXWDDMVR_LIST pList1, PVBOXWDDMVR_LIST pList2)
    1762 {
    1763     PLIST_ENTRY pEntry1 = pList1->ListHead.Flink;
    1764 
    1765     for (PLIST_ENTRY pEntry2 = pList2->ListHead.Flink; pEntry2 != &pList2->ListHead; pEntry2 = pList2->ListHead.Flink)
    1766     {
    1767         PVBOXWDDMVR_REG pReg2 = PVBOXWDDMVR_REG_FROM_ENTRY(pEntry2);
    1768         do {
    1769             if (pEntry1 != &pList1->ListHead)
    1770             {
    1771                 PVBOXWDDMVR_REG pReg1 = PVBOXWDDMVR_REG_FROM_ENTRY(pEntry1);
    1772                 if (vboxWddmVrRegNonintersectedComparator(&pReg1->Rect, &pReg2->Rect) < 0)
    1773                 {
    1774                     pEntry1 = pEntry1->Flink;
    1775                     continue;
    1776                 }
    1777             }
    1778             vboxWddmVrListRegRemove(pList2, pReg2);
    1779             vboxWddmVrListRegAdd(pList1, pReg2, pEntry1, FALSE);
    1780             break;
    1781         } while (1);
    1782     }
    1783 
    1784     Assert(VBoxWddmVrListIsEmpty(pList2));
    1785 }
    1786 
    1787 static NTSTATUS vboxWddmVrListRegIntersectSubstNoJoin(PVBOXWDDMVR_LIST pList1, PVBOXWDDMVR_REG pReg1, const RECT * pRect2)
    1788 {
    1789     UINT topLim = VBOXWDDMVR_INVALID_COORD;
    1790     UINT bottomLim = VBOXWDDMVR_INVALID_COORD;
    1791     LIST_ENTRY List;
    1792     PVBOXWDDMVR_REG pBottomReg = NULL;
    1793 #ifdef DEBUG_misha
    1794     RECT tmpRect = pReg1->Rect;
    1795     vboxWddmVrDbgListVerify(pList1);
    1796 #endif
    1797 
    1798     InitializeListHead(&List);
    1799 
    1800     Assert(vboxWddmRectIsIntersect(&pReg1->Rect, pRect2));
    1801 
    1802     if (pReg1->Rect.top < pRect2->top)
    1803     {
    1804         Assert(pRect2->top < pReg1->Rect.bottom);
    1805         PVBOXWDDMVR_REG pRegResult = vboxWddmVrRegCreate();
    1806         pRegResult->Rect.top = pReg1->Rect.top;
    1807         pRegResult->Rect.left = pReg1->Rect.left;
    1808         pRegResult->Rect.bottom = pRect2->top;
    1809         pRegResult->Rect.right = pReg1->Rect.right;
    1810         topLim = pRect2->top;
    1811         InsertTailList(&List, &pRegResult->ListEntry);
    1812     }
    1813 
    1814     if (pReg1->Rect.bottom > pRect2->bottom)
    1815     {
    1816         Assert(pRect2->bottom > pReg1->Rect.top);
    1817         PVBOXWDDMVR_REG pRegResult = vboxWddmVrRegCreate();
    1818         pRegResult->Rect.top = pRect2->bottom;
    1819         pRegResult->Rect.left = pReg1->Rect.left;
    1820         pRegResult->Rect.bottom = pReg1->Rect.bottom;
    1821         pRegResult->Rect.right = pReg1->Rect.right;
    1822         bottomLim = pRect2->bottom;
    1823         pBottomReg = pRegResult;
    1824     }
    1825 
    1826     if (pReg1->Rect.left < pRect2->left)
    1827     {
    1828         Assert(pRect2->left < pReg1->Rect.right);
    1829         PVBOXWDDMVR_REG pRegResult = vboxWddmVrRegCreate();
    1830         pRegResult->Rect.top = topLim == VBOXWDDMVR_INVALID_COORD ? pReg1->Rect.top : topLim;
    1831         pRegResult->Rect.left = pReg1->Rect.left;
    1832         pRegResult->Rect.bottom = bottomLim == VBOXWDDMVR_INVALID_COORD ? pReg1->Rect.bottom : bottomLim;
    1833         pRegResult->Rect.right = pRect2->left;
    1834         InsertTailList(&List, &pRegResult->ListEntry);
    1835     }
    1836 
    1837     if (pReg1->Rect.right > pRect2->right)
    1838     {
    1839         Assert(pRect2->right > pReg1->Rect.left);
    1840         PVBOXWDDMVR_REG pRegResult = vboxWddmVrRegCreate();
    1841         pRegResult->Rect.top = topLim == VBOXWDDMVR_INVALID_COORD ? pReg1->Rect.top : topLim;
    1842         pRegResult->Rect.left = pRect2->right;
    1843         pRegResult->Rect.bottom = bottomLim == VBOXWDDMVR_INVALID_COORD ? pReg1->Rect.bottom : bottomLim;
    1844         pRegResult->Rect.right = pReg1->Rect.right;
    1845         InsertTailList(&List, &pRegResult->ListEntry);
    1846     }
    1847 
    1848     if (pBottomReg)
    1849         InsertTailList(&List, &pBottomReg->ListEntry);
    1850 
    1851     PLIST_ENTRY pMemberEntry = pReg1->ListEntry.Flink;
    1852     vboxWddmVrListRegRemove(pList1, pReg1);
    1853     vboxWddmVrRegTerm(pReg1);
    1854 
    1855     if (IsListEmpty(&List))
    1856         return STATUS_SUCCESS; /* the region is covered by the pRect2 */
    1857 
    1858     PLIST_ENTRY pEntry = List.Flink, pNext;
    1859     for (; pEntry != &List; pEntry = pNext)
    1860     {
    1861         pNext = pEntry->Flink;
    1862         PVBOXWDDMVR_REG pReg = PVBOXWDDMVR_REG_FROM_ENTRY(pEntry);
    1863 
    1864         vboxWddmVrListRegAddOrder(pList1, pMemberEntry, pReg);
    1865         pMemberEntry = pEntry->Flink; /* the following elements should go after the given pEntry since they are ordered already */
    1866     }
    1867     return STATUS_SUCCESS;
    1868 }
    1869 
    1870 typedef DECLCALLBACK(PLIST_ENTRY) FNVBOXWDDMVR_CB_INTERSECTED_VISITOR(PVBOXWDDMVR_LIST pList1, PVBOXWDDMVR_REG pReg1, const RECT * pRect2, void *pvContext, PLIST_ENTRY *ppNext);
    1871 typedef FNVBOXWDDMVR_CB_INTERSECTED_VISITOR *PFNVBOXWDDMVR_CB_INTERSECTED_VISITOR;
    1872 
    1873 static void vboxWddmVrListVisitIntersected(PVBOXWDDMVR_LIST pList1, UINT cRects, const RECT *aRects, PFNVBOXWDDMVR_CB_INTERSECTED_VISITOR pfnVisitor, void* pvVisitor)
    1874 {
    1875     PLIST_ENTRY pEntry1 = pList1->ListHead.Flink;
    1876     PLIST_ENTRY pNext1;
    1877     UINT iFirst2 = 0;
    1878 
    1879     for (; pEntry1 != &pList1->ListHead; pEntry1 = pNext1)
    1880     {
    1881         pNext1 = pEntry1->Flink;
    1882         PVBOXWDDMVR_REG pReg1 = PVBOXWDDMVR_REG_FROM_ENTRY(pEntry1);
    1883         for (UINT i = iFirst2; i < cRects; ++i)
    1884         {
    1885             const RECT *pRect2 = &aRects[i];
    1886             if (pReg1->Rect.bottom <= pRect2->top)
    1887                 continue;
    1888             else if (pRect2->bottom <= pReg1->Rect.top)
    1889                 continue;
    1890             /* y coords intersect */
    1891             else if (pReg1->Rect.right <= pRect2->left)
    1892                 continue;
    1893             else if (pRect2->right <= pReg1->Rect.left)
    1894                 continue;
    1895             /* x coords intersect */
    1896 
    1897             /* the visitor can modify the list 1, apply necessary adjustments after it */
    1898             PLIST_ENTRY pEntry1 = pfnVisitor (pList1, pReg1, pRect2, pvVisitor, &pNext1);
    1899             if (pEntry1 == &pList1->ListHead)
    1900                 break;
    1901         }
    1902     }
    1903 }
    1904 
    1905 
    1906 static void vboxWddmVrListJoinRectsHV(PVBOXWDDMVR_LIST pList, BOOLEAN fHorizontal)
    1907 {
    1908     PLIST_ENTRY pNext1, pNext2;
    1909 
    1910     for (PLIST_ENTRY pEntry1 = pList->ListHead.Flink; pEntry1 != &pList->ListHead; pEntry1 = pNext1)
    1911     {
    1912         PVBOXWDDMVR_REG pReg1 = PVBOXWDDMVR_REG_FROM_ENTRY(pEntry1);
    1913         pNext1 = pEntry1->Flink;
    1914         for (PLIST_ENTRY pEntry2 = pEntry1->Flink; pEntry2 != &pList->ListHead; pEntry2 = pNext2)
    1915         {
    1916             PVBOXWDDMVR_REG pReg2 = PVBOXWDDMVR_REG_FROM_ENTRY(pEntry2);
    1917             pNext2 = pEntry2->Flink;
    1918             if (fHorizontal)
    1919             {
    1920                 if (pReg1->Rect.top == pReg2->Rect.top)
    1921                 {
    1922                     if (pReg1->Rect.right == pReg2->Rect.left)
    1923                     {
    1924                         /* join rectangles */
    1925                         vboxWddmVrListRegRemove(pList, pReg2);
    1926                         if (pReg1->Rect.bottom > pReg2->Rect.bottom)
    1927                         {
    1928                             LONG oldRight1 = pReg1->Rect.right;
    1929                             LONG oldBottom1 = pReg1->Rect.bottom;
    1930                             pReg1->Rect.right = pReg2->Rect.right;
    1931                             pReg1->Rect.bottom = pReg2->Rect.bottom;
    1932 
    1933                             vboxWddmVrDbgListVerify(pList);
    1934 
    1935                             pReg2->Rect.left = pReg1->Rect.left;
    1936                             pReg2->Rect.top = pReg1->Rect.bottom;
    1937                             pReg2->Rect.right = oldRight1;
    1938                             pReg2->Rect.bottom = oldBottom1;
    1939                             vboxWddmVrListRegAddOrder(pList, pReg1->ListEntry.Flink, pReg2);
    1940                             /* restart the pNext1 & pNext2 since regs are splitted into smaller ones in y dimension
    1941                              * and thus can match one of the previous rects */
    1942                             pNext1 = pList->ListHead.Flink;
    1943                             break;
    1944                         }
    1945                         else if (pReg1->Rect.bottom < pReg2->Rect.bottom)
    1946                         {
    1947                             pReg1->Rect.right = pReg2->Rect.right;
    1948                             vboxWddmVrDbgListVerify(pList);
    1949                             pReg2->Rect.top = pReg1->Rect.bottom;
    1950                             vboxWddmVrListRegAddOrder(pList, pReg1->ListEntry.Flink, pReg2);
    1951                             /* restart the pNext1 & pNext2 since regs are splitted into smaller ones in y dimension
    1952                              * and thus can match one of the previous rects */
    1953                             pNext1 = pList->ListHead.Flink;
    1954                             break;
    1955                         }
    1956                         else
    1957                         {
    1958                             pReg1->Rect.right = pReg2->Rect.right;
    1959                             vboxWddmVrDbgListVerify(pList);
    1960                             /* reset the pNext1 since it could be the pReg2 being destroyed */
    1961                             pNext1 = pEntry1->Flink;
    1962                             /* pNext2 stays the same since it is pReg2->ListEntry.pNext, which is kept intact */
    1963                             vboxWddmVrRegTerm(pReg2);
    1964                         }
    1965                     }
    1966                     continue;
    1967                 }
    1968                 else if (pReg1->Rect.bottom == pReg2->Rect.bottom)
    1969                 {
    1970                     Assert(pReg1->Rect.top < pReg2->Rect.top); /* <- since pReg1 > pReg2 && pReg1->Rect.top != pReg2->Rect.top*/
    1971                     if (pReg1->Rect.right == pReg2->Rect.left)
    1972                     {
    1973                         /* join rectangles */
    1974                         vboxWddmVrListRegRemove(pList, pReg2);
    1975 
    1976                         pReg1->Rect.bottom = pReg2->Rect.top;
    1977                         vboxWddmVrDbgListVerify(pList);
    1978                         pReg2->Rect.left = pReg1->Rect.left;
    1979 
    1980                         vboxWddmVrListRegAddOrder(pList, pReg2->ListEntry.Flink, pReg2);
    1981 
    1982                         /* restart the pNext1 & pNext2 since regs are splitted into smaller ones in y dimension
    1983                          * and thus can match one of the previous rects */
    1984                         pNext1 = pList->ListHead.Flink;
    1985                         break;
    1986                     }
    1987                     else if (pReg1->Rect.left == pReg2->Rect.right)
    1988                     {
    1989                         /* join rectangles */
    1990                         vboxWddmVrListRegRemove(pList, pReg2);
    1991 
    1992                         pReg1->Rect.bottom = pReg2->Rect.top;
    1993                         vboxWddmVrDbgListVerify(pList);
    1994                         pReg2->Rect.right = pReg1->Rect.right;
    1995 
    1996                         vboxWddmVrListRegAddOrder(pList, pReg2->ListEntry.Flink, pReg2);
    1997 
    1998                         /* restart the pNext1 & pNext2 since regs are splitted into smaller ones in y dimension
    1999                          * and thus can match one of the previous rects */
    2000                         pNext1 = pList->ListHead.Flink;
    2001                         break;
    2002                     }
    2003                     continue;
    2004                 }
    2005             }
    2006             else
    2007             {
    2008                 if (pReg1->Rect.bottom == pReg2->Rect.top)
    2009                 {
    2010                     if (pReg1->Rect.left == pReg2->Rect.left)
    2011                     {
    2012                         if (pReg1->Rect.right == pReg2->Rect.right)
    2013                         {
    2014                             /* join rects */
    2015                             vboxWddmVrListRegRemove(pList, pReg2);
    2016 
    2017                             pReg1->Rect.bottom = pReg2->Rect.bottom;
    2018                             vboxWddmVrDbgListVerify(pList);
    2019 
    2020                             /* reset the pNext1 since it could be the pReg2 being destroyed */
    2021                             pNext1 = pEntry1->Flink;
    2022                             /* pNext2 stays the same since it is pReg2->ListEntry.pNext, which is kept intact */
    2023                             vboxWddmVrRegTerm(pReg2);
    2024                             continue;
    2025                         }
    2026                         /* no more to be done for for pReg1 */
    2027                         break;
    2028                     }
    2029                     else if (pReg1->Rect.right > pReg2->Rect.left)
    2030                     {
    2031                         /* no more to be done for for pReg1 */
    2032                         break;
    2033                     }
    2034 
    2035                     continue;
    2036                 }
    2037                 else if (pReg1->Rect.bottom < pReg2->Rect.top)
    2038                 {
    2039                     /* no more to be done for for pReg1 */
    2040                     break;
    2041                 }
    2042             }
    2043         }
    2044     }
    2045 }
    2046 
    2047 static void vboxWddmVrListJoinRects(PVBOXWDDMVR_LIST pList)
    2048 {
    2049     vboxWddmVrListJoinRectsHV(pList, TRUE);
    2050     vboxWddmVrListJoinRectsHV(pList, FALSE);
    2051 }
    2052 
    2053 typedef struct VBOXWDDMVR_CBDATA_SUBST
    2054 {
    2055     NTSTATUS Status;
    2056     BOOLEAN fChanged;
    2057 } VBOXWDDMVR_CBDATA_SUBST, *PVBOXWDDMVR_CBDATA_SUBST;
    2058 
    2059 static DECLCALLBACK(PLIST_ENTRY) vboxWddmVrListSubstNoJoinCb(PVBOXWDDMVR_LIST pList, PVBOXWDDMVR_REG pReg1, const RECT *pRect2, void *pvContext, PLIST_ENTRY *ppNext)
    2060 {
    2061     PVBOXWDDMVR_CBDATA_SUBST pData = (PVBOXWDDMVR_CBDATA_SUBST)pvContext;
    2062     /* store the prev to get the new Flink out of it*/
    2063     PLIST_ENTRY pPrev = pReg1->ListEntry.Blink;
    2064     pData->fChanged = TRUE;
    2065 
    2066     Assert(vboxWddmRectIsIntersect(&pReg1->Rect, pRect2));
    2067 
    2068     /* NOTE: the pReg1 will be invalid after the vboxWddmVrListRegIntersectSubstNoJoin call!!! */
    2069     NTSTATUS Status = vboxWddmVrListRegIntersectSubstNoJoin(pList, pReg1, pRect2);
    2070     if (NT_SUCCESS(Status))
    2071     {
    2072         *ppNext = pPrev->Flink;
    2073         return &pList->ListHead;
    2074     }
    2075     WARN(("vboxWddmVrListRegIntersectSubstNoJoin failed!"));
    2076     Assert(!NT_SUCCESS(Status));
    2077     pData->Status = Status;
    2078     *ppNext = &pList->ListHead;
    2079     return &pList->ListHead;
    2080 }
    2081 
    2082 static NTSTATUS vboxWddmVrListSubstNoJoin(PVBOXWDDMVR_LIST pList, UINT cRects, const RECT *aRects, BOOLEAN *pfChanged)
    2083 {
    2084     if (VBoxWddmVrListIsEmpty(pList))
    2085         return STATUS_SUCCESS;
    2086 
    2087     VBOXWDDMVR_CBDATA_SUBST Data;
    2088     Data.Status = STATUS_SUCCESS;
    2089     Data.fChanged = FALSE;
    2090 
    2091     *pfChanged = FALSE;
    2092 
    2093     vboxWddmVrListVisitIntersected(pList, cRects, aRects, vboxWddmVrListSubstNoJoinCb, &Data);
    2094     if (!NT_SUCCESS(Data.Status))
    2095     {
    2096         WARN(("vboxWddmVrListVisitIntersected failed!"));
    2097         return Data.Status;
    2098     }
    2099 
    2100     *pfChanged = Data.fChanged;
    2101     return STATUS_SUCCESS;
    2102 }
    2103 
    2104 #if 0
    2105 static const RECT* vboxWddmVrRectsOrder(UINT cRects, const RECT *aRects)
    2106 {
    2107 #ifdef DEBUG
    2108     {
    2109         for (UINT i = 0; i < cRects; ++i)
    2110         {
    2111             RECT *pRectI = &aRects[i];
    2112             for (UINT j = i + 1; j < cRects; ++j)
    2113             {
    2114                 RECT *pRectJ = &aRects[j];
    2115                 Assert(!vboxWddmRectIsIntersect(pRectI, pRectJ));
    2116             }
    2117         }
    2118     }
    2119 #endif
    2120 
    2121     RECT * pRects = (RECT *)aRects;
    2122     /* check if rects are ordered already */
    2123     for (UINT i = 0; i < cRects - 1; ++i)
    2124     {
    2125         RECT *pRect1 = &pRects[i];
    2126         RECT *pRect2 = &pRects[i+1];
    2127         if (vboxWddmVrRegNonintersectedComparator(pRect1, pRect2) < 0)
    2128             continue;
    2129 
    2130         WARN(("rects are unoreded!"));
    2131 
    2132         if (pRects == aRects)
    2133         {
    2134             pRects = (RECT *)vboxWddmMemAlloc(sizeof (RECT) * cRects);
    2135             if (!pRects)
    2136             {
    2137                 WARN(("vboxWddmMemAlloc failed!"));
    2138                 return NULL;
    2139             }
    2140 
    2141             memcpy(pRects, aRects, sizeof (RECT) * cRects);
    2142         }
    2143 
    2144         Assert(pRects != aRects);
    2145 
    2146         int j = (int)i - 1;
    2147         do {
    2148             RECT Tmp = *pRect1;
    2149             *pRect1 = *pRect2;
    2150             *pRect2 = Tmp;
    2151 
    2152             if (j < 0)
    2153                 break;
    2154 
    2155             if (vboxWddmVrRegNonintersectedComparator(pRect1, pRect1-1) > 0)
    2156                 break;
    2157 
    2158             pRect2 = pRect1--;
    2159             --j;
    2160         } while (1);
    2161     }
    2162 
    2163     return pRects;
    2164 }
    2165 #endif
    2166 
    2167 void VBoxWddmVrListTranslate(PVBOXWDDMVR_LIST pList, LONG x, LONG y)
    2168 {
    2169     for (PLIST_ENTRY pEntry1 = pList->ListHead.Flink; pEntry1 != &pList->ListHead; pEntry1 = pEntry1->Flink)
    2170     {
    2171         PVBOXWDDMVR_REG pReg1 = PVBOXWDDMVR_REG_FROM_ENTRY(pEntry1);
    2172         vboxWddmRectTranslate(&pReg1->Rect, x, y);
    2173     }
    2174 }
    2175 
    2176 NTSTATUS VBoxWddmVrListRectsSubst(PVBOXWDDMVR_LIST pList, UINT cRects, const RECT *aRects, BOOLEAN *pfChanged)
    2177 {
    2178 #if 0
    2179     const RECT *pRects = vboxWddmVrRectsOrder(cRects, aRects);
    2180     if (!pRects)
    2181     {
    2182         WARN(("vboxWddmVrRectsOrder failed!"));
    2183         return STATUS_NO_MEMORY;
    2184     }
    2185 #endif
    2186 
    2187     NTSTATUS Status = vboxWddmVrListSubstNoJoin(pList, cRects, aRects, pfChanged);
    2188     if (!NT_SUCCESS(Status))
    2189     {
    2190         WARN(("vboxWddmVrListSubstNoJoin failed!"));
    2191         goto done;
    2192     }
    2193 
    2194     if (!*pfChanged)
    2195         goto done;
    2196 
    2197     vboxWddmVrListJoinRects(pList);
    2198 
    2199 done:
    2200 #if 0
    2201     if (pRects != aRects)
    2202         vboxWddmMemFree(pRects);
    2203 #endif
    2204     return Status;
    2205 }
    2206 
    2207 NTSTATUS VBoxWddmVrListRectsAdd(PVBOXWDDMVR_LIST pList, UINT cRects, const RECT *aRects, BOOLEAN *pfChanged)
    2208 {
    2209     UINT cCovered = 0;
    2210 
    2211 #if 0
    2212 #ifdef DEBUG
    2213     {
    2214         for (UINT i = 0; i < cRects; ++i)
    2215         {
    2216             RECT *pRectI = &aRects[i];
    2217             for (UINT j = i + 1; j < cRects; ++j)
    2218             {
    2219                 RECT *pRectJ = &aRects[j];
    2220                 Assert(!vboxWddmRectIsIntersect(pRectI, pRectJ));
    2221             }
    2222         }
    2223     }
    2224 #endif
    2225 #endif
    2226 
    2227     /* early sort out the case when there are no new rects */
    2228     for (UINT i = 0; i < cRects; ++i)
    2229     {
    2230         for (PLIST_ENTRY pEntry1 = pList->ListHead.Flink; pEntry1 != &pList->ListHead; pEntry1 = pEntry1->Flink)
    2231         {
    2232             PVBOXWDDMVR_REG pReg1 = PVBOXWDDMVR_REG_FROM_ENTRY(pEntry1);
    2233             if (vboxWddmRectIsCoveres(&pReg1->Rect, &aRects[i]))
    2234             {
    2235                 cCovered++;
    2236                 break;
    2237             }
    2238         }
    2239     }
    2240 
    2241     if (cCovered == cRects)
    2242     {
    2243         *pfChanged = FALSE;
    2244         return STATUS_SUCCESS;
    2245     }
    2246 
    2247     /* rects are not covered, need to go the slow way */
    2248 
    2249     VBOXWDDMVR_LIST DiffList;
    2250     VBoxWddmVrListInit(&DiffList);
    2251     PRECT pListRects = NULL;
    2252     UINT cAllocatedRects = 0;
    2253     BOOLEAN fNeedRectreate = TRUE;
    2254     BOOLEAN fChanged = FALSE;
    2255     NTSTATUS Status = STATUS_SUCCESS;
    2256 
    2257     for (UINT i = 0; i < cRects; ++i)
    2258     {
    2259         PVBOXWDDMVR_REG pReg = vboxWddmVrRegCreate();
    2260         if (!pReg)
    2261         {
    2262             WARN(("vboxWddmVrRegCreate failed!"));
    2263             Status = STATUS_NO_MEMORY;
    2264             break;
    2265         }
    2266         pReg->Rect = aRects[i];
    2267 
    2268         UINT cListRects = VBoxWddmVrListRectsCount(pList);
    2269         if (!cListRects)
    2270         {
    2271             vboxWddmVrListRegAdd(pList, pReg, &pList->ListHead, FALSE);
    2272             fChanged = TRUE;
    2273             continue;
    2274         }
    2275         else
    2276         {
    2277             Assert(VBoxWddmVrListIsEmpty(&DiffList));
    2278             vboxWddmVrListRegAdd(&DiffList, pReg, &DiffList.ListHead, FALSE);
    2279         }
    2280 
    2281         if (cAllocatedRects < cListRects)
    2282         {
    2283             cAllocatedRects = cListRects + cRects;
    2284             Assert(fNeedRectreate);
    2285             if (pListRects)
    2286                 vboxWddmMemFree(pListRects);
    2287             pListRects = (PRECT)vboxWddmMemAlloc(sizeof (RECT) * cAllocatedRects);
    2288             if (!pListRects)
    2289             {
    2290                 WARN(("vboxWddmMemAllocZero failed!"));
    2291                 Status = STATUS_NO_MEMORY;
    2292                 break;
    2293             }
    2294         }
    2295 
    2296 
    2297         if (fNeedRectreate)
    2298         {
    2299             Status = VBoxWddmVrListRectsGet(pList, cListRects, pListRects);
    2300             Assert(Status == STATUS_SUCCESS);
    2301             fNeedRectreate = FALSE;
    2302         }
    2303 
    2304         BOOLEAN fDummyChanged = FALSE;
    2305         Status = vboxWddmVrListSubstNoJoin(&DiffList, cListRects, pListRects, &fDummyChanged);
    2306         if (!NT_SUCCESS(Status))
    2307         {
    2308             WARN(("vboxWddmVrListSubstNoJoin failed!"));
    2309             Status = STATUS_NO_MEMORY;
    2310             break;
    2311         }
    2312 
    2313         if (!VBoxWddmVrListIsEmpty(&DiffList))
    2314         {
    2315             vboxWddmVrListAddNonintersected(pList, &DiffList);
    2316             fNeedRectreate = TRUE;
    2317             fChanged = TRUE;
    2318         }
    2319 
    2320         Assert(VBoxWddmVrListIsEmpty(&DiffList));
    2321     }
    2322 
    2323     if (pListRects)
    2324         vboxWddmMemFree(pListRects);
    2325 
    2326     Assert(VBoxWddmVrListIsEmpty(&DiffList) || Status != STATUS_SUCCESS);
    2327     VBoxWddmVrListClear(&DiffList);
    2328 
    2329     if (fChanged)
    2330         vboxWddmVrListJoinRects(pList);
    2331 
    2332     *pfChanged = fChanged;
    2333 
    2334     return STATUS_SUCCESS;
    2335 }
    2336 
    2337 NTSTATUS VBoxWddmVrListRectsGet(PVBOXWDDMVR_LIST pList, UINT cRects, PRECT aRects)
    2338 {
    2339     if (cRects < VBoxWddmVrListRectsCount(pList))
    2340         return STATUS_BUFFER_TOO_SMALL;
    2341 
    2342     UINT i = 0;
    2343     for (PLIST_ENTRY pEntry1 = pList->ListHead.Flink; pEntry1 != &pList->ListHead; pEntry1 = pEntry1->Flink, ++i)
    2344     {
    2345         PVBOXWDDMVR_REG pReg1 = PVBOXWDDMVR_REG_FROM_ENTRY(pEntry1);
    2346         aRects[i] = pReg1->Rect;
    2347     }
    2348     return STATUS_SUCCESS;
    2349 }
    2350 
    23511608NTSTATUS vboxWddmDrvCfgInit(PUNICODE_STRING pRegStr)
    23521609{
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