Changeset 46757 in vbox for trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPMisc.cpp
- Timestamp:
- Jun 24, 2013 2:30:18 PM (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/VBoxMPMisc.cpp
r45132 r46757 194 194 pSwapchain->width = w; 195 195 pSwapchain->height = h; 196 VBox WddmVrListInit(&pSwapchain->VisibleRegions);196 VBoxVrListInit(&pSwapchain->VisibleRegions); 197 197 } 198 198 return pSwapchain; … … 225 225 if (!cRefs) 226 226 { 227 VBox WddmVrListClear(&pSwapchain->VisibleRegions);227 VBoxVrListClear(&pSwapchain->VisibleRegions); 228 228 vboxWddmMemFree(pSwapchain); 229 229 } … … 313 313 vboxWddmSwapchainAllocRemoveAllInternal(pDevExt, pSwapchain, TRUE); 314 314 315 #ifndef VBOX_WDDM_MINIPORT_WITH_VISIBLE_RECTS316 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 #endif326 327 315 vboxWddmSwapchainRelease(pSwapchain); 328 316 } … … 350 338 RemoveEntryList(&pSwapchain->DevExtListEntry); 351 339 pSwapchain->hSwapchainKm = NULL; 352 VBox WddmVrListClear(&pSwapchain->VisibleRegions);340 VBoxVrListClear(&pSwapchain->VisibleRegions); 353 341 vboxWddmSwapchainRelease(pSwapchain); 354 342 } … … 412 400 if (cbSize < RT_OFFSETOF(VBOXDISPIFESCAPE_SWAPCHAININFO, SwapchainInfo.ahAllocs[pSwapchainInfo->SwapchainInfo.cAllocs])) 413 401 return STATUS_INVALID_PARAMETER; 402 403 if (!pSwapchainInfo->SwapchainInfo.winHostID) 404 { 405 WARN(("Zero winHostID specified!")); 406 return STATUS_INVALID_PARAMETER; 407 } 414 408 415 409 PVBOXWDDM_SWAPCHAIN pSwapchain = NULL; … … 499 493 // memset(&pSwapchain->ViewRect, 0, sizeof (pSwapchain->ViewRect)); 500 494 /* @todo: do we really need to zero this up here ? */ 501 VBox WddmVrListClear(&pSwapchain->VisibleRegions);495 VBoxVrListClear(&pSwapchain->VisibleRegions); 502 496 503 497 vboxWddmSwapchainAllocRemoveAll(pDevExt, pSwapchain); … … 510 504 } 511 505 pSwapchain->hSwapchainUm = pSwapchainInfo->SwapchainInfo.hSwapchainUm; 506 if (pSwapchain->winHostID != pSwapchainInfo->SwapchainInfo.winHostID) 507 { 508 pSwapchain->fExposed = FALSE; 509 pSwapchain->winHostID = pSwapchainInfo->SwapchainInfo.winHostID; 510 } 512 511 } 513 512 else … … 1409 1408 break; 1410 1409 1410 Assert(0); 1411 1411 1412 Status = vboxVideoAMgrCtxAllocDestroy(pCtx, pRef->hSessionHandle); 1412 1413 Assert(Status == STATUS_SUCCESS); … … 1605 1606 #endif 1606 1607 1607 1608 /* visible rects */1609 typedef struct VBOXWDDMVR_REG1610 {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_misha1618 //# define VBOXVDBG_VR_LAL_DISABLE1619 #endif1620 1621 #ifndef VBOXVDBG_VR_LAL_DISABLE1622 static LOOKASIDE_LIST_EX g_VBoxWddmVrLookasideList;1623 #endif1624 1625 static PVBOXWDDMVR_REG vboxWddmVrRegCreate()1626 {1627 #ifndef VBOXVDBG_VR_LAL_DISABLE1628 PVBOXWDDMVR_REG pReg = (PVBOXWDDMVR_REG)ExAllocateFromLookasideListEx(&g_VBoxWddmVrLookasideList);1629 if (!pReg)1630 {1631 WARN(("ExAllocateFromLookasideListEx failed!"));1632 }1633 return pReg;1634 #else1635 return (PVBOXWDDMVR_REG)vboxWddmMemAlloc(sizeof (VBOXWDDMVR_REG));1636 #endif1637 }1638 1639 static void vboxWddmVrRegTerm(PVBOXWDDMVR_REG pReg)1640 {1641 #ifndef VBOXVDBG_VR_LAL_DISABLE1642 ExFreeToLookasideListEx(&g_VBoxWddmVrLookasideList, pReg);1643 #else1644 vboxWddmMemFree(pReg);1645 #endif1646 }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_DISABLE1665 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 #endif1680 1681 return STATUS_SUCCESS;1682 }1683 1684 void VBoxWddmVrTerm()1685 {1686 #ifndef VBOXVDBG_VR_LAL_DISABLE1687 ExDeleteLookasideListEx(&g_VBoxWddmVrLookasideList);1688 #endif1689 }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_misha1703 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 vboxWddmVrDbgListDoVerify1719 #else1720 #define vboxWddmVrDbgListVerify(_p) do {} while (0)1721 #endif1722 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 else1732 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 do1746 {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_misha1794 RECT tmpRect = pReg1->Rect;1795 vboxWddmVrDbgListVerify(pList1);1796 #endif1797 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 dimension1941 * 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 dimension1952 * and thus can match one of the previous rects */1953 pNext1 = pList->ListHead.Flink;1954 break;1955 }1956 else1957 {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 dimension1983 * 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 dimension1999 * and thus can match one of the previous rects */2000 pNext1 = pList->ListHead.Flink;2001 break;2002 }2003 continue;2004 }2005 }2006 else2007 {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_SUBST2054 {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 02105 static const RECT* vboxWddmVrRectsOrder(UINT cRects, const RECT *aRects)2106 {2107 #ifdef DEBUG2108 {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 #endif2120 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 #endif2166 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 02179 const RECT *pRects = vboxWddmVrRectsOrder(cRects, aRects);2180 if (!pRects)2181 {2182 WARN(("vboxWddmVrRectsOrder failed!"));2183 return STATUS_NO_MEMORY;2184 }2185 #endif2186 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 02201 if (pRects != aRects)2202 vboxWddmMemFree(pRects);2203 #endif2204 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 02212 #ifdef DEBUG2213 {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 #endif2225 #endif2226 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 else2276 {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 2351 1608 NTSTATUS vboxWddmDrvCfgInit(PUNICODE_STRING pRegStr) 2352 1609 {
Note:
See TracChangeset
for help on using the changeset viewer.