VirtualBox

Changeset 95086 in vbox for trunk/src/VBox/Additions/WINNT


Ignore:
Timestamp:
May 25, 2022 5:31:21 AM (3 years ago)
Author:
vboxsync
Message:

WDDM: [C]OTables. bugref:9845

Location:
trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/gallium
Files:
6 edited

Legend:

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

    r94927 r95086  
    5151    for (uint32_t i = 0; i < RT_ELEMENTS(pSvga->aOT); ++i)
    5252    {
    53         SvgaMobFree(pSvga, pSvga->aOT[i].pMob);
    54         pSvga->aOT[i].pMob = 0;
     53        SvgaGboFree(&pSvga->aOT[i].gbo);
    5554
    5655        RTR0MemObjFree(pSvga->aOT[i].hMemObj, true);
     
    6160}
    6261
    63 static NTSTATUS SvgaObjectTablesInit(VBOXWDDM_EXT_VMSVGA *pSvga)
    64 {
    65     NTSTATUS Status = STATUS_SUCCESS;
    66 
    67     /* Allocate OTables. */
    68     for (uint32_t i = 0; i < RT_ELEMENTS(pSvga->aOT); ++i)
    69     {
    70         /** @todo Proper size for each. */
    71         uint32_t cbOT = 16 * PAGE_SIZE;
    72 
    73         /* Allocate pages for the new OTable. */
    74         int rc = RTR0MemObjAllocPageTag(&pSvga->aOT[i].hMemObj, cbOT, false /* executable R0 mapping */, "VMSVGAOT");
    75         AssertRCBreakStmt(rc, Status = STATUS_INSUFFICIENT_RESOURCES);
    76 
    77         /* Allocate a new mob. */
    78         Status = SvgaMobCreate(pSvga, &pSvga->aOT[i].pMob, cbOT >> PAGE_SHIFT, 0);
    79         AssertBreak(NT_SUCCESS(Status));
    80 
    81         Status = SvgaMobFillPageTableForMemObj(pSvga, pSvga->aOT[i].pMob, pSvga->aOT[i].hMemObj);
    82         AssertBreak(NT_SUCCESS(Status));
    83     }
    84 
    85     if (NT_SUCCESS(Status))
    86     {
    87         /* Emit commands */
    88         for (uint32_t i = 0; i < RT_ELEMENTS(pSvga->aOT); ++i)
    89         {
    90             void *pvCmd = SvgaCmdBuf3dCmdReserve(pSvga, SVGA_3D_CMD_SET_OTABLE_BASE64, sizeof(SVGA3dCmdSetOTableBase64), SVGA3D_INVALID_ID);
    91             AssertBreakStmt(pvCmd, Status = STATUS_INSUFFICIENT_RESOURCES);
    92 
     62
     63struct VMSVGAOTFREE
     64{
     65    VMSVGAGBO  gbo;
     66    RTR0MEMOBJ hMemObj;
     67};
     68
     69
     70static DECLCALLBACK(void) svgaOTFreeCb(VBOXWDDM_EXT_VMSVGA *pSvga, void *pvData, uint32_t cbData)
     71{
     72    RT_NOREF(pSvga);
     73    AssertReturnVoid(cbData == sizeof(struct VMSVGAOTFREE));
     74    struct VMSVGAOTFREE *p = (struct VMSVGAOTFREE *)pvData;
     75    SvgaGboFree(&p->gbo);
     76    RTR0MemObjFree(p->hMemObj, true);
     77}
     78
     79
     80typedef struct VMSVGAOTINFO
     81{
     82    uint32_t cbEntry;
     83    uint32_t cMaxEntries;
     84} VMSVGAOTINFO, *PVMSVGAOTINFO;
     85
     86
     87static VMSVGAOTINFO const s_aOTInfo[SVGA_OTABLE_DX_MAX] =
     88{
     89    { sizeof(SVGAOTableMobEntry),          SVGA3D_MAX_MOBS },               /* SVGA_OTABLE_MOB */
     90    { sizeof(SVGAOTableSurfaceEntry),      SVGA3D_MAX_SURFACE_IDS },        /* SVGA_OTABLE_SURFACE */
     91    { sizeof(SVGAOTableContextEntry),      0 /* not used */ },              /* SVGA_OTABLE_CONTEXT */
     92    { sizeof(SVGAOTableShaderEntry),       0 /* not used */ },              /* SVGA_OTABLE_SHADER */
     93    { sizeof(SVGAOTableScreenTargetEntry), 64 /*VBOX_VIDEO_MAX_SCREENS*/ }, /* SVGA_OTABLE_SCREENTARGET */
     94    { sizeof(SVGAOTableDXContextEntry),    SVGA3D_MAX_CONTEXT_IDS },        /* SVGA_OTABLE_DXCONTEXT */
     95};
     96
     97
     98static NTSTATUS svgaObjectTablesNotify(VBOXWDDM_EXT_VMSVGA *pSvga, SVGAOTableType enmType, uint32_t id)
     99{
     100    AssertCompile(RT_ELEMENTS(pSvga->aOT) == RT_ELEMENTS(s_aOTInfo));
     101    AssertReturn(enmType < RT_ELEMENTS(pSvga->aOT), STATUS_INVALID_PARAMETER);
     102
     103    if (!RT_BOOL(pSvga->u32Caps & SVGA_CAP_GBOBJECTS))
     104        return STATUS_SUCCESS; /* No otables for such host device. */
     105
     106    PVMSVGAOT pOT = &pSvga->aOT[enmType];
     107    if (id < pOT->cEntries)
     108        return STATUS_SUCCESS; /* Still large enough. */
     109
     110    VMSVGAOTINFO const *pOTInfo = &s_aOTInfo[enmType];
     111    AssertReturn(id < pOTInfo->cMaxEntries, STATUS_INVALID_PARAMETER);
     112
     113    /*
     114     * Allocate a new larger mob and inform the host.
     115     */
     116    uint32_t cbRequired = (id + 1) * pOTInfo->cbEntry;
     117    cbRequired = RT_ALIGN_32(cbRequired, PAGE_SIZE);
     118
     119    /* Try to double the current size. */
     120    uint32_t cbOT = pOT->cEntries ? pOT->cEntries * pOTInfo->cbEntry : PAGE_SIZE;
     121    while (cbRequired > cbOT)
     122        cbOT *= 2;
     123
     124    /* Allocate pages for the new COTable. */
     125    RTR0MEMOBJ hMemObjOT;
     126    int rc = RTR0MemObjAllocPageTag(&hMemObjOT, cbOT, false /* executable R0 mapping */, "VMSVGAOT");
     127    AssertRCReturn(rc, STATUS_INSUFFICIENT_RESOURCES);
     128
     129    memset(RTR0MemObjAddress(hMemObjOT), 0, cbOT);
     130
     131    /* Allocate a new gbo. */
     132    VMSVGAGBO gbo;
     133    NTSTATUS Status = SvgaGboInit(&gbo, cbOT >> PAGE_SHIFT);
     134    AssertReturnStmt(NT_SUCCESS(Status),
     135                     RTR0MemObjFree(hMemObjOT, true),
     136                     Status);
     137
     138    Status = SvgaGboFillPageTableForMemObj(&gbo, hMemObjOT);
     139    AssertReturnStmt(NT_SUCCESS(Status),
     140                     SvgaGboFree(&gbo); RTR0MemObjFree(hMemObjOT, true),
     141                     Status);
     142
     143    if (pOT->cEntries == 0)
     144    {
     145        /* Set the pages for OTable. */
     146        void *pvCmd = SvgaCmdBuf3dCmdReserve(pSvga, SVGA_3D_CMD_SET_OTABLE_BASE64, sizeof(SVGA3dCmdSetOTableBase64), SVGA3D_INVALID_ID);
     147        if (pvCmd)
     148        {
    93149            SVGA3dCmdSetOTableBase64 *pCmd = (SVGA3dCmdSetOTableBase64 *)pvCmd;
    94             pCmd->type             = (SVGAOTableType)i;
    95             pCmd->baseAddress      = pSvga->aOT[i].pMob->base;
    96             pCmd->sizeInBytes      = pSvga->aOT[i].pMob->cbMob;
     150            pCmd->type             = enmType;
     151            pCmd->baseAddress      = gbo.base;
     152            pCmd->sizeInBytes      = gbo.cbGbo;
    97153            pCmd->validSizeInBytes = 0;
    98             pCmd->ptDepth          = pSvga->aOT[i].pMob->enmMobFormat;
    99 
    100             SvgaCmdBufCommit(pSvga, sizeof(SVGA3dCmdSetOTableBase64));
     154            pCmd->ptDepth          = gbo.enmMobFormat;
     155
     156            SvgaCmdBufCommit(pSvga, sizeof(*pCmd));
    101157        }
    102 
    103         SvgaCmdBufFlush(pSvga);
    104     }
    105 
    106     if (!NT_SUCCESS(Status))
    107         SvgaObjectTablesDestroy(pSvga);
     158        else
     159            AssertFailedReturnStmt(SvgaGboFree(&gbo); RTR0MemObjFree(hMemObjOT, true),
     160                                   STATUS_INSUFFICIENT_RESOURCES);
     161    }
     162    else
     163    {
     164        /* Grow OTable and delete the old mob. */
     165        void *pvCmd = SvgaCmdBuf3dCmdReserve(pSvga, SVGA_3D_CMD_GROW_OTABLE, sizeof(SVGA3dCmdGrowOTable), SVGA3D_INVALID_ID);
     166        if (pvCmd)
     167        {
     168            SVGA3dCmdGrowOTable *pCmd = (SVGA3dCmdGrowOTable *)pvCmd;
     169            pCmd->type             = enmType;
     170            pCmd->baseAddress      = gbo.base;
     171            pCmd->sizeInBytes      = gbo.cbGbo;
     172            pCmd->validSizeInBytes = pOT->cEntries * pOTInfo->cbEntry;
     173            pCmd->ptDepth          = gbo.enmMobFormat;
     174
     175            SvgaCmdBufCommit(pSvga, sizeof(*pCmd));
     176        }
     177        else
     178            AssertFailedReturnStmt(SvgaGboFree(&gbo); RTR0MemObjFree(hMemObjOT, true),
     179                                   STATUS_INSUFFICIENT_RESOURCES);
     180
     181        /* Command buffer completion callback to free the COT. */
     182        struct VMSVGAOTFREE callbackData;
     183        callbackData.gbo = pOT->gbo;
     184        callbackData.hMemObj = pOT->hMemObj;
     185        SvgaCmdBufSetCompletionCallback(pSvga, svgaOTFreeCb, &callbackData, sizeof(callbackData));
     186
     187        memset(&pOT->gbo, 0, sizeof(pOT->gbo));
     188        pOT->hMemObj = NIL_RTR0MEMOBJ;
     189    }
     190
     191    SvgaCmdBufFlush(pSvga);
     192
     193    pOT->gbo = gbo;
     194    pOT->hMemObj = hMemObjOT;
     195    pOT->cEntries = cbOT / pOTInfo->cbEntry;
    108196
    109197    return STATUS_SUCCESS;
     
    203291    }
    204292
    205     if (pSvga->u32Caps & SVGA_CAP_GBOBJECTS)
    206     {
    207         /** @todo DX contexts are available if SVGA_CAP_GBOBJECTS, SVGA_CAP_DX and SVGA3D_DEVCAP_DXCONTEXT are all enabled. */
    208         Status = SvgaObjectTablesInit(pSvga);
    209         AssertReturn(NT_SUCCESS(Status), Status);
    210     }
    211 
    212293    uint32_t u32IRQMask = SVGA_IRQFLAG_ANY_FENCE;
    213294    if (pSvga->pCBState)
     
    271352    KeInitializeSpinLock(&pSvga->HwSpinLock);
    272353    KeInitializeSpinLock(&pSvga->HostObjectsSpinLock);
     354    KeInitializeSpinLock(&pSvga->IdSpinLock);
    273355    ExInitializeFastMutex(&pSvga->SvgaMutex);
     356    KeInitializeSpinLock(&pSvga->MobSpinLock);
     357    // pSvga->GMRTree = NULL;
    274358    // pSvga->SurfaceTree = NULL;
     359    // pSvga->MobTree = NULL;
    275360    RTListInit(&pSvga->DeletedHostObjectsList);
    276361
     
    301386                if (pSvga->u32GmrMaxIds > 0)
    302387                {
    303                     pSvga->GMRTree = NULL;
    304388                    pSvga->cbGMRBits = ((pSvga->u32GmrMaxIds + 31) / 32) * 4; /* 32bit align and 4 bytes per 32 bit. */
    305389                    pSvga->pu32GMRBits = (uint32_t *)GaMemAllocZero(pSvga->cbGMRBits);
     
    410494
    411495
    412 NTSTATUS SvgaIdAlloc(PVBOXWDDM_EXT_VMSVGA pSvga,
    413                      uint32_t *pu32Bits,
    414                      uint32_t cbBits,
    415                      uint32_t u32Limit,
    416                      uint32_t *pu32Id)
    417 {
    418     NTSTATUS Status;
    419     ExAcquireFastMutex(&pSvga->SvgaMutex);
    420 
    421     Status = GaIdAlloc(pu32Bits, cbBits, u32Limit, pu32Id);
    422 
    423     ExReleaseFastMutex(&pSvga->SvgaMutex);
    424     return Status;
    425 }
    426 
    427 NTSTATUS SvgaIdFree(PVBOXWDDM_EXT_VMSVGA pSvga,
    428                     uint32_t *pu32Bits,
    429                     uint32_t cbBits,
    430                     uint32_t u32Limit,
    431                     uint32_t u32Id)
    432 {
    433     NTSTATUS Status;
    434     ExAcquireFastMutex(&pSvga->SvgaMutex);
    435 
    436     Status = GaIdFree(pu32Bits, cbBits, u32Limit, u32Id);
    437 
    438     ExReleaseFastMutex(&pSvga->SvgaMutex);
    439     return Status;
     496DECLINLINE(NTSTATUS) svgaIdAlloc(PVBOXWDDM_EXT_VMSVGA pSvga,
     497                                 uint32_t *pu32Bits,
     498                                 uint32_t cbBits,
     499                                 uint32_t u32Limit,
     500                                 uint32_t *pu32Id)
     501{
     502    KIRQL OldIrql;
     503    KeAcquireSpinLock(&pSvga->IdSpinLock, &OldIrql);
     504    NTSTATUS Status = GaIdAlloc(pu32Bits, cbBits, u32Limit, pu32Id);
     505    KeReleaseSpinLock(&pSvga->IdSpinLock, OldIrql);
     506    return Status;
     507}
     508
     509
     510DECLINLINE(NTSTATUS) svgaIdFree(PVBOXWDDM_EXT_VMSVGA pSvga,
     511                                uint32_t *pu32Bits,
     512                                uint32_t cbBits,
     513                                uint32_t u32Limit,
     514                                uint32_t u32Id)
     515{
     516    KIRQL OldIrql;
     517    KeAcquireSpinLock(&pSvga->IdSpinLock, &OldIrql);
     518    NTSTATUS Status = GaIdFree(pu32Bits, cbBits, u32Limit, u32Id);
     519    KeReleaseSpinLock(&pSvga->IdSpinLock, OldIrql);
     520    return Status;
     521}
     522
     523
     524static NTSTATUS svgaOTableIdAlloc(PVBOXWDDM_EXT_VMSVGA pSvga,
     525                                  uint32_t *pu32Bits,
     526                                  uint32_t cbBits,
     527                                  SVGAOTableType enmType,
     528                                  uint32_t *pu32Id)
     529{
     530    AssertReturn(enmType < RT_ELEMENTS(s_aOTInfo), STATUS_INVALID_PARAMETER);
     531    VMSVGAOTINFO const *pOTInfo = &s_aOTInfo[enmType];
     532    Assert(pOTInfo->cMaxEntries <= cbBits * 8);
     533
     534    NTSTATUS Status = svgaIdAlloc(pSvga, pu32Bits, cbBits, pOTInfo->cMaxEntries, pu32Id);
     535    if (NT_SUCCESS(Status))
     536    {
     537        ExAcquireFastMutex(&pSvga->SvgaMutex);
     538        Status = svgaObjectTablesNotify(pSvga, enmType, *pu32Id);
     539        ExReleaseFastMutex(&pSvga->SvgaMutex);
     540
     541        if (!NT_SUCCESS(Status))
     542            svgaIdFree(pSvga, pu32Bits, cbBits, pOTInfo->cMaxEntries, *pu32Id);
     543    }
     544
     545    return Status;
     546}
     547
     548static NTSTATUS svgaOTableIdFree(PVBOXWDDM_EXT_VMSVGA pSvga,
     549                                 uint32_t *pu32Bits,
     550                                 uint32_t cbBits,
     551                                 SVGAOTableType enmType,
     552                                 uint32_t u32Id)
     553{
     554    AssertReturn(enmType < RT_ELEMENTS(s_aOTInfo), STATUS_INVALID_PARAMETER);
     555    VMSVGAOTINFO const *pOTInfo = &s_aOTInfo[enmType];
     556    return svgaIdFree(pSvga, pu32Bits, cbBits, pOTInfo->cMaxEntries, u32Id);
    440557}
    441558
     
    443560                              uint32_t *pu32Cid)
    444561{
    445     return SvgaIdAlloc(pSvga, pSvga->au32DXContextBits, sizeof(pSvga->au32DXContextBits),
    446                        SVGA3D_MAX_CONTEXT_IDS, pu32Cid);
     562    return svgaOTableIdAlloc(pSvga, pSvga->au32DXContextBits, sizeof(pSvga->au32DXContextBits),
     563                             SVGA_OTABLE_DXCONTEXT, pu32Cid);
    447564}
    448565
     
    450567                             uint32_t u32Cid)
    451568{
    452     return SvgaIdFree(pSvga, pSvga->au32DXContextBits, sizeof(pSvga->au32DXContextBits),
    453                       SVGA3D_MAX_CONTEXT_IDS, u32Cid);
     569    return svgaOTableIdFree(pSvga, pSvga->au32DXContextBits, sizeof(pSvga->au32DXContextBits),
     570                            SVGA_OTABLE_DXCONTEXT, u32Cid);
    454571}
    455572
     
    457574                        uint32_t *pu32MobId)
    458575{
    459     return SvgaIdAlloc(pSvga, pSvga->au32MobBits, sizeof(pSvga->au32MobBits),
    460                        SVGA3D_MAX_MOBS, pu32MobId);
     576    return svgaOTableIdAlloc(pSvga, pSvga->au32MobBits, sizeof(pSvga->au32MobBits),
     577                             SVGA_OTABLE_MOB, pu32MobId);
    461578}
    462579
     
    464581                       uint32_t u32MobId)
    465582{
    466     return SvgaIdFree(pSvga, pSvga->au32MobBits, sizeof(pSvga->au32MobBits),
    467                       SVGA3D_MAX_MOBS, u32MobId);
     583    return svgaOTableIdFree(pSvga, pSvga->au32MobBits, sizeof(pSvga->au32MobBits),
     584                            SVGA_OTABLE_MOB, u32MobId);
    468585}
    469586
     
    471588                            uint32_t *pu32Cid)
    472589{
    473     return SvgaIdAlloc(pSvga, pSvga->au32ContextBits, sizeof(pSvga->au32ContextBits),
    474                        SVGA3D_MAX_CONTEXT_IDS, pu32Cid);
     590    return svgaOTableIdAlloc(pSvga, pSvga->au32ContextBits, sizeof(pSvga->au32ContextBits),
     591                             SVGA_OTABLE_CONTEXT, pu32Cid);
    475592}
    476593
     
    478595                           uint32_t u32Cid)
    479596{
    480     return SvgaIdFree(pSvga, pSvga->au32ContextBits, sizeof(pSvga->au32ContextBits),
    481                        SVGA3D_MAX_CONTEXT_IDS, u32Cid);
     597    return svgaOTableIdFree(pSvga, pSvga->au32ContextBits, sizeof(pSvga->au32ContextBits),
     598                            SVGA_OTABLE_CONTEXT, u32Cid);
    482599}
    483600
     
    485602                            uint32_t *pu32Sid)
    486603{
    487     return SvgaIdAlloc(pSvga, pSvga->au32SurfaceBits, sizeof(pSvga->au32SurfaceBits),
    488                        SVGA3D_MAX_SURFACE_IDS, pu32Sid);
     604    return svgaOTableIdAlloc(pSvga, pSvga->au32SurfaceBits, sizeof(pSvga->au32SurfaceBits),
     605                             SVGA_OTABLE_SURFACE, pu32Sid);
    489606}
    490607
     
    492609                           uint32_t u32Sid)
    493610{
    494     return SvgaIdFree(pSvga, pSvga->au32SurfaceBits, sizeof(pSvga->au32SurfaceBits),
    495                       SVGA3D_MAX_SURFACE_IDS, u32Sid);
     611    return svgaOTableIdFree(pSvga, pSvga->au32SurfaceBits, sizeof(pSvga->au32SurfaceBits),
     612                            SVGA_OTABLE_SURFACE, u32Sid);
    496613}
    497614
     
    499616                        uint32_t *pu32GMRId)
    500617{
    501     return SvgaIdAlloc(pSvga, pSvga->pu32GMRBits, pSvga->cbGMRBits,
     618    return svgaIdAlloc(pSvga, pSvga->pu32GMRBits, pSvga->cbGMRBits,
    502619                       pSvga->u32GmrMaxIds, pu32GMRId);
    503620}
     
    506623                       uint32_t u32GMRId)
    507624{
    508     return SvgaIdFree(pSvga, pSvga->pu32GMRBits, pSvga->cbGMRBits,
     625    return svgaIdFree(pSvga, pSvga->pu32GMRBits, pSvga->cbGMRBits,
    509626                      pSvga->u32GmrMaxIds, u32GMRId);
    510627}
     
    19592076}
    19602077
    1961 NTSTATUS SvgaMobAlloc(VBOXWDDM_EXT_VMSVGA *pSvga,
    1962                       PVMSVGAMOB *ppMob)
     2078/*
     2079 *
     2080 * Guest Backed Objects.
     2081 *
     2082 */
     2083
     2084void SvgaGboFree(VMSVGAGBO *pGbo)
     2085{
     2086    if (pGbo->hMemObjPT != NIL_RTR0MEMOBJ)
     2087    {
     2088        int rc = RTR0MemObjFree(pGbo->hMemObjPT, true);
     2089        AssertRC(rc);
     2090        pGbo->hMemObjPT = NIL_RTR0MEMOBJ;
     2091    }
     2092    memset(pGbo, 0, sizeof(*pGbo));
     2093}
     2094
     2095NTSTATUS SvgaGboInit(VMSVGAGBO *pGbo, uint32_t cPages)
     2096{
     2097    /*
     2098     * Calculate how many pages are needed to describe the gbo.
     2099     * Use 64 bit mob format for 32 bit driver too in order to simplify the code for now.
     2100     */
     2101    uint32_t const cPageEntriesPerPage = PAGE_SIZE / sizeof(PPN64);
     2102    if (cPages == 1)
     2103    {
     2104        pGbo->cPTPages = 0;
     2105        pGbo->enmMobFormat = SVGA3D_MOBFMT_PTDEPTH64_0;
     2106    }
     2107    else if (cPages <= cPageEntriesPerPage)
     2108    {
     2109        pGbo->cPTPages = 1;
     2110        pGbo->enmMobFormat = SVGA3D_MOBFMT_PTDEPTH64_1;
     2111    }
     2112    else if (cPages <= cPageEntriesPerPage * cPageEntriesPerPage)
     2113    {
     2114        uint32_t const cLevel1Pages =
     2115            (cPages + cPageEntriesPerPage - 1) / cPageEntriesPerPage;
     2116        pGbo->cPTPages = 1 + cLevel1Pages; /* One level 2 page and level 1 pages. */
     2117        pGbo->enmMobFormat = SVGA3D_MOBFMT_PTDEPTH64_2;
     2118    }
     2119    else
     2120        AssertFailedReturn(STATUS_INVALID_PARAMETER);
     2121
     2122    if (pGbo->cPTPages)
     2123    {
     2124        int rc = RTR0MemObjAllocPageTag(&pGbo->hMemObjPT, pGbo->cPTPages * PAGE_SIZE,
     2125                                        false /* executable R0 mapping */, "VMSVGAGBO");
     2126        AssertRCReturn(rc, STATUS_INSUFFICIENT_RESOURCES);
     2127
     2128        if (pGbo->enmMobFormat == SVGA3D_MOBFMT_PTDEPTH64_2)
     2129        {
     2130            /* Store the page numbers of level 1 pages into the level 2 page.
     2131             * Skip the level 2 page at index 0.
     2132             */
     2133            PPN64 *paPpn = (PPN64 *)RTR0MemObjAddress(pGbo->hMemObjPT);
     2134            for (unsigned i = 1; i < pGbo->cPTPages; ++i)
     2135                paPpn[i - 1] = RTR0MemObjGetPagePhysAddr(pGbo->hMemObjPT, i) >> PAGE_SHIFT;
     2136        }
     2137    }
     2138    else
     2139        pGbo->hMemObjPT = NIL_RTR0MEMOBJ;
     2140
     2141    pGbo->base = UINT64_C(~0); /* base will be assigned by SvgaGboFillPageTable* */
     2142    pGbo->cbGbo = cPages << PAGE_SHIFT;
     2143    return STATUS_SUCCESS;
     2144}
     2145
     2146
     2147NTSTATUS SvgaGboFillPageTableForMDL(PVMSVGAGBO pGbo,
     2148                                    PMDL pMdl,
     2149                                    uint32_t MdlOffset)
     2150{
     2151    PPFN_NUMBER paMdlPfn = &MmGetMdlPfnArray(pMdl)[MdlOffset];
     2152    if (pGbo->enmMobFormat == SVGA3D_MOBFMT_PTDEPTH64_0)
     2153        pGbo->base = paMdlPfn[0];
     2154    else
     2155    {
     2156        /* The first of pages is alway the base. It is either the level 2 page or the single level 1 page */
     2157        pGbo->base = RTR0MemObjGetPagePhysAddr(pGbo->hMemObjPT, 0) >> PAGE_SHIFT;
     2158
     2159        PPN64 *paPpn = (PPN64 *)RTR0MemObjAddress(pGbo->hMemObjPT);
     2160        PPN64 *paPpnMdlPfn;
     2161        if (pGbo->enmMobFormat == SVGA3D_MOBFMT_PTDEPTH64_2)
     2162            paPpnMdlPfn = &paPpn[PAGE_SIZE / sizeof(PPN64)]; /* Level 1 pages follow the level 2 page. */
     2163        else if (pGbo->enmMobFormat == SVGA3D_MOBFMT_PTDEPTH64_1)
     2164            paPpnMdlPfn = paPpn;
     2165        else
     2166            AssertFailedReturn(STATUS_INVALID_PARAMETER);
     2167
     2168        /* Store Mdl page numbers into the level 1 description pages. */
     2169        for (unsigned i = 0; i < pGbo->cbGbo >> PAGE_SHIFT; ++i)
     2170            paPpnMdlPfn[i] = paMdlPfn[i];
     2171    }
     2172    return STATUS_SUCCESS;
     2173}
     2174
     2175
     2176NTSTATUS SvgaGboFillPageTableForMemObj(PVMSVGAGBO pGbo,
     2177                                       RTR0MEMOBJ hMemObj)
     2178{
     2179    if (pGbo->enmMobFormat == SVGA3D_MOBFMT_PTDEPTH64_0)
     2180        pGbo->base = RTR0MemObjGetPagePhysAddr(hMemObj, 0) >> PAGE_SHIFT;
     2181    else
     2182    {
     2183        /* The first of pages is alway the base. It is either the level 2 page or the single level 1 page */
     2184        pGbo->base = RTR0MemObjGetPagePhysAddr(pGbo->hMemObjPT, 0) >> PAGE_SHIFT;
     2185
     2186        PPN64 *paPpn = (PPN64 *)RTR0MemObjAddress(pGbo->hMemObjPT);
     2187        PPN64 *paPpnGbo;
     2188        if (pGbo->enmMobFormat == SVGA3D_MOBFMT_PTDEPTH64_2)
     2189            paPpnGbo = &paPpn[PAGE_SIZE / sizeof(PPN64)]; /* Level 1 pages follow the level 2 page. */
     2190        else if (pGbo->enmMobFormat == SVGA3D_MOBFMT_PTDEPTH64_1)
     2191            paPpnGbo = paPpn;
     2192        else
     2193            AssertFailedReturn(STATUS_INVALID_PARAMETER);
     2194
     2195        /* Store page numbers into the level 1 description pages. */
     2196        for (unsigned i = 0; i < pGbo->cbGbo >> PAGE_SHIFT; ++i)
     2197            paPpnGbo[i] = RTR0MemObjGetPagePhysAddr(hMemObj, i) >> PAGE_SHIFT;
     2198    }
     2199    return STATUS_SUCCESS;
     2200}
     2201
     2202
     2203/*
     2204 *
     2205 * Memory OBjects.
     2206 *
     2207 */
     2208
     2209static NTSTATUS svgaMobAlloc(VBOXWDDM_EXT_VMSVGA *pSvga,
     2210                             PVMSVGAMOB *ppMob)
    19632211{
    19642212    GALOG(("[%p]\n", pSvga));
     
    19732221    AssertReturnStmt(NT_SUCCESS(Status), GaMemFree(*ppMob), STATUS_INSUFFICIENT_RESOURCES);
    19742222
     2223    KIRQL OldIrql;
     2224    KeAcquireSpinLock(&pSvga->MobSpinLock, &OldIrql);
     2225    bool fInserted = RTAvlU32Insert(&pSvga->MobTree, &(*ppMob)->core);
     2226    KeReleaseSpinLock(&pSvga->MobSpinLock, OldIrql);
     2227    Assert(fInserted); RT_NOREF(fInserted);
     2228
     2229    GALOG(("mobid = %u\n", VMSVGAMOB_ID(*ppMob)));
    19752230    return STATUS_SUCCESS;
    19762231}
     
    19832238    if (pMob)
    19842239    {
    1985         ExAcquireFastMutex(&pSvga->SvgaMutex);
     2240        GALOG(("mobid = %u\n", VMSVGAMOB_ID(pMob)));
     2241
     2242        KIRQL OldIrql;
     2243        KeAcquireSpinLock(&pSvga->MobSpinLock, &OldIrql);
    19862244        RTAvlU32Remove(&pSvga->MobTree, pMob->core.Key);
    1987         ExReleaseFastMutex(&pSvga->SvgaMutex);
    1988 
    1989         if (pMob->hMemObjPT != NIL_RTR0MEMOBJ)
    1990         {
    1991             int rc = RTR0MemObjFree(pMob->hMemObjPT, true);
    1992             AssertRC(rc);
    1993             pMob->hMemObjPT = NIL_RTR0MEMOBJ;
    1994         }
     2245        KeReleaseSpinLock(&pSvga->MobSpinLock, OldIrql);
     2246
     2247        SvgaGboFree(&pMob->gbo);
    19952248
    19962249        NTSTATUS Status = SvgaMobIdFree(pSvga, VMSVGAMOB_ID(pMob));
     
    20002253}
    20012254
     2255PVMSVGAMOB SvgaMobQuery(VBOXWDDM_EXT_VMSVGA *pSvga,
     2256                        uint32_t mobid)
     2257{
     2258    KIRQL OldIrql;
     2259    KeAcquireSpinLock(&pSvga->MobSpinLock, &OldIrql);
     2260    PVMSVGAMOB pMob = (PVMSVGAMOB)RTAvlU32Get(&pSvga->MobTree, mobid);
     2261    KeReleaseSpinLock(&pSvga->MobSpinLock, OldIrql);
     2262
     2263    GALOG(("[%p] mobid = %u -> %p\n", pSvga, mobid, pMob));
     2264    return pMob;
     2265}
    20022266
    20032267NTSTATUS SvgaMobCreate(VBOXWDDM_EXT_VMSVGA *pSvga,
     
    20072271{
    20082272    PVMSVGAMOB pMob;
    2009     NTSTATUS Status = SvgaMobAlloc(pSvga, &pMob);
     2273    NTSTATUS Status = svgaMobAlloc(pSvga, &pMob);
    20102274    AssertReturn(NT_SUCCESS(Status), Status);
    20112275
    2012     /*
    2013      * Calculate how many pages are needed to describe the mob.
    2014      * Use 64 bit mob format for 32 bit driver too in order to simplify the code.
    2015      */
    2016     uint32_t const cPageEntriesPerPage = PAGE_SIZE / sizeof(PPN64);
    2017     if (cMobPages == 1)
    2018     {
    2019         pMob->cDescriptionPages = 0;
    2020         pMob->enmMobFormat = SVGA3D_MOBFMT_PTDEPTH64_0;
    2021     }
    2022     else if (cMobPages <= cPageEntriesPerPage)
    2023     {
    2024         pMob->cDescriptionPages = 1;
    2025         pMob->enmMobFormat = SVGA3D_MOBFMT_PTDEPTH64_1;
    2026     }
    2027     else if (cMobPages <= cPageEntriesPerPage * cPageEntriesPerPage)
    2028     {
    2029         uint32_t const cLevel1Pages =
    2030             (cMobPages + cPageEntriesPerPage - 1) / cPageEntriesPerPage;
    2031         pMob->cDescriptionPages = 1 + cLevel1Pages; /* One level 2 page and level 1 pages. */
    2032         pMob->enmMobFormat = SVGA3D_MOBFMT_PTDEPTH64_2;
    2033     }
    2034     else
    2035         AssertFailedReturnStmt(SvgaMobFree(pSvga, pMob), STATUS_INVALID_PARAMETER);
    2036 
    2037     if (pMob->cDescriptionPages)
    2038     {
    2039         int rc = RTR0MemObjAllocPageTag(&pMob->hMemObjPT, pMob->cDescriptionPages * PAGE_SIZE,
    2040                                         false /* executable R0 mapping */, "VMSVGAMOB");
    2041         AssertRCReturnStmt(rc, SvgaMobFree(pSvga, pMob), STATUS_INSUFFICIENT_RESOURCES);
    2042 
    2043         if (pMob->enmMobFormat == SVGA3D_MOBFMT_PTDEPTH64_2)
    2044         {
    2045             /* Store the page numbers of level 1 pages into the level 2 page.
    2046              * Skip the level 2 page at index 0.
    2047              */
    2048             PPN64 *paPpn = (PPN64 *)RTR0MemObjAddress(pMob->hMemObjPT);
    2049             for (unsigned i = 1; i < pMob->cDescriptionPages; ++i)
    2050                 paPpn[i - 1] = RTR0MemObjGetPagePhysAddr(pMob->hMemObjPT, i) >> PAGE_SHIFT;
    2051         }
    2052     }
    2053 
    2054     pMob->base = UINT64_C(~0); /* base will be assigned by SvgaMobFillPageTable* */
    2055     pMob->cbMob = cMobPages << PAGE_SHIFT;
     2276    Status = SvgaGboInit(&pMob->gbo, cMobPages);
     2277    AssertReturnStmt(NT_SUCCESS(Status), SvgaMobFree(pSvga, pMob), Status);
     2278
    20562279    pMob->hAllocation = hAllocation;
    2057 
    20582280    *ppMob = pMob;
    20592281    return STATUS_SUCCESS;
     
    20612283
    20622284
    2063 NTSTATUS SvgaMobFillPageTableForMDL(VBOXWDDM_EXT_VMSVGA *pSvga,
    2064                                     PVMSVGAMOB pMob,
    2065                                     PMDL pMdl,
    2066                                     uint32_t MdlOffset)
    2067 {
    2068     RT_NOREF(pSvga);
    2069 
    2070     PPFN_NUMBER paMdlPfn = &MmGetMdlPfnArray(pMdl)[MdlOffset];
    2071     if (pMob->enmMobFormat == SVGA3D_MOBFMT_PTDEPTH64_0)
    2072         pMob->base = paMdlPfn[0];
    2073     else
    2074     {
    2075         /* The first of pages is alway the base. It is either the level 2 page or the single level 1 page */
    2076         pMob->base = RTR0MemObjGetPagePhysAddr(pMob->hMemObjPT, 0) >> PAGE_SHIFT;
    2077 
    2078         PPN64 *paPpn = (PPN64 *)RTR0MemObjAddress(pMob->hMemObjPT);
    2079         PPN64 *paPpnMdlPfn;
    2080         if (pMob->enmMobFormat == SVGA3D_MOBFMT_PTDEPTH64_2)
    2081             paPpnMdlPfn = &paPpn[PAGE_SIZE / sizeof(PPN64)]; /* Level 1 pages follow the level 2 page. */
    2082         else if (pMob->enmMobFormat == SVGA3D_MOBFMT_PTDEPTH64_1)
    2083             paPpnMdlPfn = paPpn;
    2084         else
    2085             AssertFailedReturn(STATUS_INVALID_PARAMETER);
    2086 
    2087         /* Store Mdl page numbers into the level 1 description pages. */
    2088         for (unsigned i = 0; i < pMob->cbMob >> PAGE_SHIFT; ++i)
    2089             paPpnMdlPfn[i] = paMdlPfn[i];
    2090     }
    2091     return STATUS_SUCCESS;
    2092 }
    2093 
    2094 
    2095 NTSTATUS SvgaMobFillPageTableForMemObj(VBOXWDDM_EXT_VMSVGA *pSvga,
    2096                                        PVMSVGAMOB pMob,
    2097                                        RTR0MEMOBJ hMemObj)
    2098 {
    2099     RT_NOREF(pSvga);
    2100 
    2101     if (pMob->enmMobFormat == SVGA3D_MOBFMT_PTDEPTH64_0)
    2102         pMob->base = RTR0MemObjGetPagePhysAddr(hMemObj, 0) >> PAGE_SHIFT;
    2103     else
    2104     {
    2105         /* The first of pages is alway the base. It is either the level 2 page or the single level 1 page */
    2106         pMob->base = RTR0MemObjGetPagePhysAddr(pMob->hMemObjPT, 0) >> PAGE_SHIFT;
    2107 
    2108         PPN64 *paPpn = (PPN64 *)RTR0MemObjAddress(pMob->hMemObjPT);
    2109         PPN64 *paPpnMob;
    2110         if (pMob->enmMobFormat == SVGA3D_MOBFMT_PTDEPTH64_2)
    2111             paPpnMob = &paPpn[PAGE_SIZE / sizeof(PPN64)]; /* Level 1 pages follow the level 2 page. */
    2112         else if (pMob->enmMobFormat == SVGA3D_MOBFMT_PTDEPTH64_1)
    2113             paPpnMob = paPpn;
    2114         else
    2115             AssertFailedReturn(STATUS_INVALID_PARAMETER);
    2116 
    2117         /* Store page numbers into the level 1 description pages. */
    2118         for (unsigned i = 0; i < pMob->cbMob >> PAGE_SHIFT; ++i)
    2119             paPpnMob[i] = RTR0MemObjGetPagePhysAddr(hMemObj, i) >> PAGE_SHIFT;;
    2120     }
    2121     return STATUS_SUCCESS;
     2285struct VMSVGACOTFREE
     2286{
     2287    PVMSVGAMOB pMob;
     2288    RTR0MEMOBJ hMemObj;
     2289};
     2290
     2291
     2292static DECLCALLBACK(void) svgaCOTMobFreeCb(VBOXWDDM_EXT_VMSVGA *pSvga, void *pvData, uint32_t cbData)
     2293{
     2294    AssertReturnVoid(cbData == sizeof(struct VMSVGACOTFREE));
     2295    struct VMSVGACOTFREE *p = (struct VMSVGACOTFREE *)pvData;
     2296    SvgaMobFree(pSvga, p->pMob);
     2297    RTR0MemObjFree(p->hMemObj, true);
    21222298}
    21232299
     
    21522328        sizeof(SVGACOTableDXUAViewEntry),
    21532329    };
    2154 
    2155     /** @todo Grow COTable. Readback and delete old mob. */
    2156     Assert(pCOT->cEntries == 0);
     2330    AssertCompile(RT_ELEMENTS(pSvgaContext->aCOT) == RT_ELEMENTS(s_acbEntry));
    21572331
    21582332    uint32_t cbRequired = (id + 1) * s_acbEntry[enmType];
     
    21612335    /* Try to double the current size. */
    21622336    uint32_t cbCOT = pCOT->cEntries ? pCOT->cEntries * s_acbEntry[enmType] : PAGE_SIZE;
    2163 cbCOT += PAGE_SIZE * 15; /// @todo Large enough. Remove this line and implement COTable reallocation.
    21642337    while (cbRequired > cbCOT)
    21652338        cbCOT *= 2;
     
    21772350                     Status);
    21782351
    2179     Status = SvgaMobFillPageTableForMemObj(pSvga, pMob, hMemObjCOT);
     2352    Status = SvgaGboFillPageTableForMemObj(&pMob->gbo, hMemObjCOT);
    21802353    AssertReturnStmt(NT_SUCCESS(Status),
    21812354                     SvgaMobFree(pSvga, pMob); RTR0MemObjFree(hMemObjCOT, true),
     
    21842357    /* Emit commands. */
    21852358    void *pvCmd = SvgaCmdBuf3dCmdReserve(pSvga, SVGA_3D_CMD_DEFINE_GB_MOB64, sizeof(SVGA3dCmdDefineGBMob64), SVGA3D_INVALID_ID);
    2186     AssertReturnStmt(pvCmd,
    2187                      SvgaMobFree(pSvga, pMob); RTR0MemObjFree(hMemObjCOT, true),
    2188                      STATUS_INSUFFICIENT_RESOURCES);
    2189 
    2190     SVGA3dCmdDefineGBMob64 *pCmd1 = (SVGA3dCmdDefineGBMob64 *)pvCmd;
    2191     pCmd1->mobid       = VMSVGAMOB_ID(pMob);
    2192     pCmd1->ptDepth     = pMob->enmMobFormat;
    2193     pCmd1->base        = pMob->base;
    2194     pCmd1->sizeInBytes = pMob->cbMob;
    2195     SvgaCmdBufCommit(pSvga, sizeof(*pCmd1));
    2196 
    2197     pvCmd = SvgaCmdBuf3dCmdReserve(pSvga, SVGA_3D_CMD_DX_SET_COTABLE, sizeof(SVGA3dCmdDXSetCOTable), SVGA3D_INVALID_ID);
    2198     AssertReturnStmt(pvCmd,
    2199                      SvgaMobFree(pSvga, pMob); RTR0MemObjFree(hMemObjCOT, true),
    2200                      STATUS_INSUFFICIENT_RESOURCES);
    2201 
    2202     SVGA3dCmdDXSetCOTable *pCmd2 = (SVGA3dCmdDXSetCOTable *)pvCmd;
    2203     pCmd2->cid         = pSvgaContext->u32Cid;
    2204     pCmd2->mobid       = VMSVGAMOB_ID(pMob);
    2205     pCmd2->type        = enmType;
    2206     pCmd2->validSizeInBytes = pCOT->cEntries * s_acbEntry[enmType];
    2207     SvgaCmdBufCommit(pSvga, sizeof(*pCmd2));
     2359    if (pvCmd)
     2360    {
     2361        SVGA3dCmdDefineGBMob64 *pCmd = (SVGA3dCmdDefineGBMob64 *)pvCmd;
     2362        pCmd->mobid       = VMSVGAMOB_ID(pMob);
     2363        pCmd->ptDepth     = pMob->gbo.enmMobFormat;
     2364        pCmd->base        = pMob->gbo.base;
     2365        pCmd->sizeInBytes = pMob->gbo.cbGbo;
     2366        SvgaCmdBufCommit(pSvga, sizeof(*pCmd));
     2367    }
     2368    else
     2369        AssertFailedReturnStmt(SvgaMobFree(pSvga, pMob); RTR0MemObjFree(hMemObjCOT, true),
     2370                               STATUS_INSUFFICIENT_RESOURCES);
     2371
     2372    if (pCOT->cEntries == 0)
     2373    {
     2374        /* Set the mob for COTable. */
     2375        pvCmd = SvgaCmdBuf3dCmdReserve(pSvga, SVGA_3D_CMD_DX_SET_COTABLE, sizeof(SVGA3dCmdDXSetCOTable), SVGA3D_INVALID_ID);
     2376        if (pvCmd)
     2377        {
     2378            SVGA3dCmdDXSetCOTable *pCmd = (SVGA3dCmdDXSetCOTable *)pvCmd;
     2379            pCmd->cid              = pSvgaContext->u32Cid;
     2380            pCmd->mobid            = VMSVGAMOB_ID(pMob);
     2381            pCmd->type             = enmType;
     2382            pCmd->validSizeInBytes = pCOT->cEntries * s_acbEntry[enmType];
     2383            SvgaCmdBufCommit(pSvga, sizeof(*pCmd));
     2384        }
     2385        else
     2386            AssertFailedReturnStmt(SvgaMobFree(pSvga, pMob); RTR0MemObjFree(hMemObjCOT, true),
     2387                                   STATUS_INSUFFICIENT_RESOURCES);
     2388    }
     2389    else
     2390    {
     2391        /* Grow COTable and delete old mob. */
     2392        pvCmd = SvgaCmdBuf3dCmdReserve(pSvga, SVGA_3D_CMD_DX_GROW_COTABLE, sizeof(SVGA3dCmdDXGrowCOTable), SVGA3D_INVALID_ID);
     2393        if (pvCmd)
     2394        {
     2395            SVGA3dCmdDXGrowCOTable *pCmd = (SVGA3dCmdDXGrowCOTable *)pvCmd;
     2396            pCmd->cid              = pSvgaContext->u32Cid;
     2397            pCmd->mobid            = VMSVGAMOB_ID(pMob);
     2398            pCmd->type             = enmType;
     2399            pCmd->validSizeInBytes = pCOT->cEntries * s_acbEntry[enmType];
     2400            SvgaCmdBufCommit(pSvga, sizeof(*pCmd));
     2401        }
     2402        else
     2403            AssertFailedReturnStmt(SvgaMobFree(pSvga, pMob); RTR0MemObjFree(hMemObjCOT, true),
     2404                                   STATUS_INSUFFICIENT_RESOURCES);
     2405
     2406        pvCmd = SvgaCmdBuf3dCmdReserve(pSvga, SVGA_3D_CMD_DESTROY_GB_MOB, sizeof(SVGA3dCmdDestroyGBMob), SVGA3D_INVALID_ID);
     2407        if (pvCmd)
     2408        {
     2409            SVGA3dCmdDestroyGBMob *pCmd = (SVGA3dCmdDestroyGBMob *)pvCmd;
     2410            pCmd->mobid = VMSVGAMOB_ID(pCOT->pMob);
     2411            SvgaCmdBufCommit(pSvga, sizeof(*pCmd));
     2412        }
     2413        else
     2414            AssertFailedReturnStmt(SvgaMobFree(pSvga, pMob); RTR0MemObjFree(hMemObjCOT, true),
     2415                                   STATUS_INSUFFICIENT_RESOURCES);
     2416
     2417        /* Command buffer completion callback to free the COT. */
     2418        struct VMSVGACOTFREE callbackData;
     2419        callbackData.pMob = pCOT->pMob;
     2420        callbackData.hMemObj = pCOT->hMemObj;
     2421        SvgaCmdBufSetCompletionCallback(pSvga, svgaCOTMobFreeCb, &callbackData, sizeof(callbackData));
     2422
     2423        pCOT->pMob = NULL;
     2424        pCOT->hMemObj = NIL_RTR0MEMOBJ;
     2425    }
    22082426
    22092427    SvgaCmdBufFlush(pSvga);
  • trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/gallium/Svga.h

    r94927 r95086  
    7373typedef int32_t VMSVGACBHEADERHANDLE;
    7474#define VMSVGACBHEADER_NIL (-1)
     75
     76struct VBOXWDDM_EXT_VMSVGA;
     77typedef DECLCALLBACKTYPE(void, FNCBCOMPLETION, (struct VBOXWDDM_EXT_VMSVGA *pSvga, void *pvData, uint32_t cbData));
     78typedef FNCBCOMPLETION *PFNCBCOMPLETION;
     79
     80typedef struct VMSVGACBCOMPLETION
     81{
     82    RTLISTNODE                  nodeCompletion;             /* VMSVGACB::listCompletion */
     83    PFNCBCOMPLETION             pfn;                        /* Function to call. */
     84    uint32_t                    cb;                         /* Size of data in bytes. */
     85    /* cb bytes follow. */
     86} VMSVGACBCOMPLETION, *PVMSVGACBCOMPLETION;
    7587
    7688typedef enum VMSVGACBTYPE
     
    101113        PHYSICAL_ADDRESS DmaBufferPhysicalAddress; /* VMSVGACB_UMD */
    102114    } commands;
     115    RTLISTANCHOR         listCompletion;           /* VMSVGACBCOMPLETION to be called on completion. */
    103116#ifdef DEBUG
    104117    bool fSubmitted : 1;
     
    137150} VMSVGACBSTATE, *PVMSVGACBSTATE;
    138151
    139 /* Contexts + One shaders mob per context + surfaces. */
    140 #define SVGA3D_MAX_MOBS (SVGA3D_MAX_CONTEXT_IDS + SVGA3D_MAX_CONTEXT_IDS + SVGA3D_MAX_SURFACE_IDS)
    141 
    142 typedef struct VMSVGAMOB
    143 {
    144     AVLU32NODECORE              core;                       /* AVL entry. Key is mobid, allocated by the miniport. */
    145     uint32_t                    cbMob;                      /* Size of mob in bytes. */
    146     uint32_t                    cDescriptionPages;          /* How many pages are required to hold PPN64 page table. */
     152/* Guest Backed Object: a set of locked pages and a page table for the host to access. */
     153typedef struct VMSVGAGBO
     154{
     155    uint32_t                    cbGbo;                      /* Size of gbo in bytes. */
     156    uint32_t                    cPTPages;                   /* How many pages are required to hold PPN64 page table. */
    147157    SVGAMobFormat               enmMobFormat;               /* Page table format. */
    148158    PPN64                       base;                       /* Page which contains the page table. */
    149159    RTR0MEMOBJ                  hMemObjPT;                  /* Page table pages. */
     160} VMSVGAGBO, *PVMSVGAGBO;
     161
     162/* Contexts + One shaders mob per context + surfaces. */
     163#define SVGA3D_MAX_MOBS (SVGA3D_MAX_CONTEXT_IDS + SVGA3D_MAX_CONTEXT_IDS + SVGA3D_MAX_SURFACE_IDS)
     164
     165/* Memory OBject: a gbo with an id, possibly bound to an allocation. */
     166typedef struct VMSVGAMOB
     167{
     168    AVLU32NODECORE              core;                       /* AVL entry. Key is mobid, allocated by the miniport. */
    150169    HANDLE                      hAllocation;                /* Allocation which is bound to the mob. */
     170    VMSVGAGBO                   gbo;                        /* Gbo for this mob. */
    151171} VMSVGAMOB, *PVMSVGAMOB;
    152172
    153173#define VMSVGAMOB_ID(a_pMob) ((a_pMob)->core.Key)
     174
     175typedef struct VMSVGAOT
     176{
     177    VMSVGAGBO                   gbo;
     178    RTR0MEMOBJ                  hMemObj;
     179    uint32_t                    cEntries;                   /* How many objects can be stored in the OTable. */
     180} VMSVGAOT, *PVMSVGAOT;
    154181
    155182/* VMSVGA specific part of Gallium device extension. */
     
    160187    /** Pointer to FIFO MMIO region. */
    161188    volatile uint32_t *pu32FIFO;
    162 
    163     /** Used only with SVGA_CAP_COMMAND_BUFFERS capability. */
    164     RTR0MEMOBJ hMemObj;
    165     RTR0PTR  pvR0Hdr, pvR0Cmd;
    166     RTHCPHYS paHdr, paCmd;
    167     uint32_t u32NumCmdBufs;
    168 
    169     RTR0MEMOBJ hMemObjOTables;
    170189
    171190    /**
     
    190209    /** Command buffers state. */
    191210    PVMSVGACBSTATE pCBState;
     211    /** Whether the host has generated an IRQ for buffer completion or error. */
    192212    bool volatile fCommandBufferIrq;
    193213
     
    198218    KSPIN_LOCK HostObjectsSpinLock;
    199219
     220    /** For ids allocation. */
     221    KSPIN_LOCK IdSpinLock;
     222
    200223    /** AVL tree for mapping GMR id to the corresponding structure. */
    201224    AVLU32TREE GMRTree;
     
    212235    /** SVGA data access. */
    213236    FAST_MUTEX SvgaMutex;
     237
     238    /** MOB access: MobTree. */
     239    KSPIN_LOCK MobSpinLock;
    214240
    215241    struct
     
    219245    } lastGMRFB;
    220246
    221     struct
    222     {
    223         PVMSVGAMOB pMob;
    224         RTR0MEMOBJ hMemObj;
    225     } aOT[SVGA_OTABLE_DX_MAX];
     247    VMSVGAOT aOT[SVGA_OTABLE_DX_MAX];
    226248
    227249    /** Bitmap of used GMR ids. Bit 0 - GMR id 0, etc. */
     
    248270    RTR0MEMOBJ              hMemObj;                    /* COTable pages. */
    249271    uint32_t                cEntries;                   /* How many objects can be stored in the COTable. */
    250     uint32_t                cNewEntries;                /* New size of the COTable for rebind. */
    251     bool                    fRebind : 1;                /* Mob must be reallocated and host must be informed. */
    252272} VMSVGACOT, *PVMSVGACOT;
    253273
     
    577597#endif
    578598
    579 NTSTATUS SvgaMobAlloc(VBOXWDDM_EXT_VMSVGA *pSvga,
    580                       PVMSVGAMOB *ppMob);
     599NTSTATUS SvgaGboInit(VMSVGAGBO *pGbo, uint32_t cPages);
     600void SvgaGboFree(VMSVGAGBO *pGbo);
     601NTSTATUS SvgaGboFillPageTableForMDL(PVMSVGAGBO pGbo,
     602                                    PMDL pMdl,
     603                                    uint32_t MdlOffset);
     604NTSTATUS SvgaGboFillPageTableForMemObj(PVMSVGAGBO pGbo,
     605                                       RTR0MEMOBJ hMemObj);
     606
    581607void SvgaMobFree(VBOXWDDM_EXT_VMSVGA *pSvga,
    582608                 PVMSVGAMOB pMob);
     609PVMSVGAMOB SvgaMobQuery(VBOXWDDM_EXT_VMSVGA *pSvga,
     610                        uint32_t mobid);
    583611NTSTATUS SvgaMobCreate(VBOXWDDM_EXT_VMSVGA *pSvga,
    584612                       PVMSVGAMOB *ppMob,
    585613                       uint32_t cMobPages,
    586614                       HANDLE hAllocation);
    587 NTSTATUS SvgaMobFillPageTableForMDL(VBOXWDDM_EXT_VMSVGA *pSvga,
    588                                     PVMSVGAMOB pMob,
    589                                     PMDL pMdl,
    590                                     uint32_t MdlOffset);
    591 NTSTATUS SvgaMobFillPageTableForMemObj(VBOXWDDM_EXT_VMSVGA *pSvga,
    592                                        PVMSVGAMOB pMob,
    593                                        RTR0MEMOBJ hMemObj);
    594615
    595616NTSTATUS SvgaCOTNotifyId(VBOXWDDM_EXT_VMSVGA *pSvga,
  • trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/gallium/SvgaFifo.cpp

    r94635 r95086  
    446446    /* Buffer header is not allocated. */
    447447    pCB->hHeader = VMSVGACBHEADER_NIL;
     448    RTListInit(&pCB->listCompletion);
    448449
    449450    *ppCB = pCB;
     
    754755
    755756
     757static void svgaCBCallCompletion(PVBOXWDDM_EXT_VMSVGA pSvga, PVMSVGACB pCB)
     758{
     759    PVMSVGACBCOMPLETION pIter, pNext;
     760    RTListForEachSafe(&pCB->listCompletion, pIter, pNext, VMSVGACBCOMPLETION, nodeCompletion)
     761    {
     762        pIter->pfn(pSvga, &pIter[1], pIter->cb);
     763        RTListNodeRemove(&pIter->nodeCompletion);
     764        RTMemFree(pIter);
     765    }
     766}
     767
     768
    756769/** Process command buffers processed by the host at DPC level.
    757770 *
     
    812825                /* Just delete the buffer. */
    813826                RTListNodeRemove(&pIter->nodeQueue);
     827                svgaCBCallCompletion(pSvga, pIter);
    814828                svgaCBFree(pCBState, pIter);
    815829                break;
     
    841855
    842856
     857void SvgaCmdBufSetCompletionCallback(PVBOXWDDM_EXT_VMSVGA pSvga, PFNCBCOMPLETION pfn, void const *pv, uint32_t cb)
     858{
     859    VMSVGACBCOMPLETION *p = (VMSVGACBCOMPLETION *)RTMemAlloc(sizeof(VMSVGACBCOMPLETION) + cb);
     860    AssertReturnVoid(p);
     861
     862    p->pfn = pfn;
     863    p->cb = cb;
     864    memcpy(&p[1], pv, cb);
     865
     866    PVMSVGACBSTATE pCBState = pSvga->pCBState;
     867    ExAcquireFastMutex(&pCBState->CBCurrentMutex);
     868    RTListAppend(&pCBState->pCBCurrent->listCompletion, &p->nodeCompletion);
     869    ExReleaseFastMutex(&pCBState->CBCurrentMutex);
     870}
     871
     872
    843873NTSTATUS SvgaCmdBufDestroy(PVBOXWDDM_EXT_VMSVGA pSvga)
    844874{
     875    /** PVMSVGACBSTATE pCBState as parameter. */
    845876    PVMSVGACBSTATE pCBState = pSvga->pCBState;
    846877    if (pCBState == NULL)
     
    878909NTSTATUS SvgaCmdBufInit(PVBOXWDDM_EXT_VMSVGA pSvga)
    879910{
     911    /** PVMSVGACBSTATE *ppCBState as parameter. */
    880912    NTSTATUS Status;
    881913
  • trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/gallium/SvgaFifo.h

    r94631 r95086  
    4141void  SvgaCmdBufFlush(PVBOXWDDM_EXT_VMSVGA pSvga);
    4242void  SvgaCmdBufProcess(PVBOXWDDM_EXT_VMSVGA pSvga);
     43void SvgaCmdBufSetCompletionCallback(PVBOXWDDM_EXT_VMSVGA pSvga, PFNCBCOMPLETION pfn, void const *pv, uint32_t cb);
    4344
    4445NTSTATUS SvgaCmdBufAllocUMD(PVBOXWDDM_EXT_VMSVGA pSvga, PHYSICAL_ADDRESS DmaBufferPhysicalAddress,
  • trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/gallium/VBoxMPDX.cpp

    r95010 r95086  
    129129    if (NT_SUCCESS(Status))
    130130    {
    131         Status = SvgaMobFillPageTableForMemObj(pSvga, pAllocation->dx.gb.pMob, pAllocation->dx.gb.hMemObjGB);
     131        Status = SvgaGboFillPageTableForMemObj(&pAllocation->dx.gb.pMob->gbo, pAllocation->dx.gb.hMemObjGB);
    132132        Assert(NT_SUCCESS(Status));
    133133        if (NT_SUCCESS(Status))
     
    140140                SVGA3dCmdDefineGBMob64 *pCmd = (SVGA3dCmdDefineGBMob64 *)pvCmd;
    141141                pCmd->mobid       = VMSVGAMOB_ID(pAllocation->dx.gb.pMob);
    142                 pCmd->ptDepth     = pAllocation->dx.gb.pMob->enmMobFormat;
    143                 pCmd->base        = pAllocation->dx.gb.pMob->base;
    144                 pCmd->sizeInBytes = pAllocation->dx.gb.pMob->cbMob;
     142                pCmd->ptDepth     = pAllocation->dx.gb.pMob->gbo.enmMobFormat;
     143                pCmd->base        = pAllocation->dx.gb.pMob->gbo.base;
     144                pCmd->sizeInBytes = pAllocation->dx.gb.pMob->gbo.cbGbo;
    145145                SvgaCmdBufCommit(pSvga, sizeof(SVGA3dCmdDefineGBMob64));
    146146            }
     
    721721    AssertReturn(NT_SUCCESS(Status), Status);
    722722
    723     Status = SvgaMobFillPageTableForMDL(pSvga, pMob, pBuildPagingBuffer->MapApertureSegment.pMdl,
     723    Status = SvgaGboFillPageTableForMDL(&pMob->gbo, pBuildPagingBuffer->MapApertureSegment.pMdl,
    724724                                        pBuildPagingBuffer->MapApertureSegment.MdlOffset);
    725725    AssertReturnStmt(NT_SUCCESS(Status), SvgaMobFree(pSvga, pMob), Status);
     
    737737        return STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
    738738    }
    739 
    740     /* Add to the container. */
    741     ExAcquireFastMutex(&pSvga->SvgaMutex);
    742     RTAvlU32Insert(&pSvga->MobTree, &pMob->core);
    743     ExReleaseFastMutex(&pSvga->SvgaMutex);
    744739
    745740    pAllocation->dx.mobid = VMSVGAMOB_ID(pMob);
     
    755750    SVGA3dCmdDefineGBMob64 *pCmd = (SVGA3dCmdDefineGBMob64 *)pu8Cmd;
    756751    pCmd->mobid       = VMSVGAMOB_ID(pMob);
    757     pCmd->ptDepth     = pMob->enmMobFormat;
    758     pCmd->base        = pMob->base;
    759     pCmd->sizeInBytes = pMob->cbMob;
     752    pCmd->ptDepth     = pMob->gbo.enmMobFormat;
     753    pCmd->base        = pMob->gbo.base;
     754    pCmd->sizeInBytes = pMob->gbo.cbGbo;
    760755    pu8Cmd += sizeof(*pCmd);
    761756    }
     
    811806
    812807    /* Find the mob. */
    813     ExAcquireFastMutex(&pSvga->SvgaMutex);
    814     PVMSVGAMOB pMob = (PVMSVGAMOB)RTAvlU32Get(&pSvga->MobTree, pAllocation->dx.mobid);
    815     ExReleaseFastMutex(&pSvga->SvgaMutex);
     808    PVMSVGAMOB pMob = SvgaMobQuery(pSvga, pAllocation->dx.mobid);
    816809    AssertReturn(pMob, STATUS_INVALID_PARAMETER);
    817810
     
    903896    }
    904897
    905     /* Fill RenderData description in any case, it will be ignored if the above code failed. */
    906     GARENDERDATA *pRenderData = (GARENDERDATA *)pBuildPagingBuffer->pDmaBufferPrivateData;
    907     pRenderData->u32DataType   = GARENDERDATA_TYPE_PAGING;
    908     pRenderData->cbData        = cbCommands;
    909     pRenderData->pFenceObject  = NULL;
    910     pRenderData->pvDmaBuffer   = pBuildPagingBuffer->pDmaBuffer;
    911     pRenderData->pHwRenderData = NULL;
    912 
    913     switch (Status)
    914     {
    915         case STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER:
    916             DEBUG_BREAKPOINT_TEST();
    917             RT_FALL_THRU();
    918         case STATUS_SUCCESS:
    919         {
     898    if (   Status == STATUS_SUCCESS
     899        || Status == STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER)
     900    {
     901        if (cbCommands)
     902        {
     903            GARENDERDATA *pRenderData = (GARENDERDATA *)pBuildPagingBuffer->pDmaBufferPrivateData;
     904            pRenderData->u32DataType   = GARENDERDATA_TYPE_PAGING;
     905            pRenderData->cbData        = cbCommands;
     906            pRenderData->pFenceObject  = NULL;
     907            pRenderData->pvDmaBuffer   = pBuildPagingBuffer->pDmaBuffer;
     908            pRenderData->pHwRenderData = NULL;
     909
    920910            pBuildPagingBuffer->pDmaBuffer = (uint8_t *)pBuildPagingBuffer->pDmaBuffer + cbCommands;
    921911            pBuildPagingBuffer->pDmaBufferPrivateData = (uint8_t *)pBuildPagingBuffer->pDmaBufferPrivateData + sizeof(GARENDERDATA);
    922         } break;
    923         default: break;
     912        }
    924913    }
    925914
  • trunk/src/VBox/Additions/WINNT/Graphics/Video/mp/wddm/gallium/VBoxMPGaWddm.cpp

    r94975 r95086  
    162162                         PVBOXWDDM_CONTEXT pContext)
    163163{
     164    VBOXWDDM_EXT_VMSVGA *pSvga = pGaDevExt->hw.pSvga;
     165    NTSTATUS Status;
     166
    164167    AssertReturn(pContext->NodeOrdinal == 0, STATUS_NOT_SUPPORTED);
    165168
    166     pContext->pSvgaContext = (PVMSVGACONTEXT)GaMemAllocZero(sizeof(VMSVGACONTEXT));
    167     AssertReturn(pContext->pSvgaContext, STATUS_INSUFFICIENT_RESOURCES);
    168 
    169     pContext->pSvgaContext->fDXContext = RT_BOOL(pInfo->u.vmsvga.u32Flags & VBOXWDDM_F_GA_CONTEXT_VGPU10);
    170 
    171     VBOXWDDM_EXT_VMSVGA *pSvga = pGaDevExt->hw.pSvga;
     169    /*
     170     * Allocate SVGA context and initialize it.
     171     */
     172    PVMSVGACONTEXT pSvgaContext = (PVMSVGACONTEXT)GaMemAllocZero(sizeof(VMSVGACONTEXT));
     173    AssertReturn(pSvgaContext, STATUS_INSUFFICIENT_RESOURCES);
     174
     175    pSvgaContext->fDXContext = RT_BOOL(pInfo->u.vmsvga.u32Flags & VBOXWDDM_F_GA_CONTEXT_VGPU10);
     176
    172177    uint32_t u32Cid;
    173     NTSTATUS Status;
    174     if (pContext->pSvgaContext->fDXContext)
     178    if (pSvgaContext->fDXContext)
    175179        Status = SvgaDXContextIdAlloc(pSvga, &u32Cid);
    176180    else
     
    178182    if (NT_SUCCESS(Status))
    179183    {
    180         if (pContext->pSvgaContext->fDXContext)
     184        if (pSvgaContext->fDXContext)
    181185            Status = SvgaDXContextCreate(pSvga, u32Cid);
    182186        else
     
    184188        if (Status == STATUS_SUCCESS)
    185189        {
    186             /** @todo Save other pInfo fields. */
    187             RT_NOREF(pInfo);
    188 
    189             /* Init pContext fields, which are relevant to the VMSVGA context. */
    190             pContext->pSvgaContext->u32Cid = u32Cid;
    191 
    192             GALOG(("pGaDevExt = %p, cid = %d (%d)\n", pGaDevExt, u32Cid, pContext->pSvgaContext->fDXContext ? "DX" : "VGPU9"));
     190            pSvgaContext->u32Cid = u32Cid;
     191            GALOG(("pGaDevExt = %p, cid = %d (%s)\n", pGaDevExt, u32Cid, pSvgaContext->fDXContext ? "DX" : "VGPU9"));
    193192        }
    194193        else
    195194        {
    196195            AssertFailed();
    197             if (pContext->pSvgaContext->fDXContext)
     196            if (pSvgaContext->fDXContext)
    198197                SvgaDXContextIdFree(pSvga, u32Cid);
    199198            else
     
    202201    }
    203202
    204     if (!NT_SUCCESS(Status))
    205     {
    206         GaMemFree(pContext->pSvgaContext);
    207         pContext->pSvgaContext = 0;
    208     }
     203    if (NT_SUCCESS(Status))
     204        pContext->pSvgaContext = pSvgaContext;
     205    else
     206        GaMemFree(pSvgaContext);
    209207    return Status;
    210208}
     
    213211                          PVBOXWDDM_CONTEXT pContext)
    214212{
     213    VBOXWDDM_EXT_VMSVGA *pSvga = pGaDevExt->hw.pSvga;
     214
    215215    PVMSVGACONTEXT pSvgaContext = pContext->pSvgaContext;
    216216    if (!pSvgaContext)
    217217        return STATUS_SUCCESS;
    218     pContext->pSvgaContext = 0;
     218    pContext->pSvgaContext = NULL;
    219219
    220220    GALOG(("u32Cid = %d\n", pSvgaContext->u32Cid));
    221 
    222     VBOXWDDM_EXT_VMSVGA *pSvga = pGaDevExt->hw.pSvga;
    223221
    224222    NTSTATUS Status;
    225223    if (pSvgaContext->fDXContext)
    226224    {
     225        for (unsigned i = 0; i < RT_ELEMENTS(pSvgaContext->aCOT); ++i)
     226        {
     227            PVMSVGACOT pCOT = &pSvgaContext->aCOT[i];
     228            if (pCOT->pMob)
     229            {
     230                void *pvCmd = SvgaCmdBuf3dCmdReserve(pSvga, SVGA_3D_CMD_DX_SET_COTABLE, sizeof(SVGA3dCmdDXSetCOTable), SVGA3D_INVALID_ID);
     231                if (pvCmd)
     232                {
     233                    SVGA3dCmdDXSetCOTable *pCmd = (SVGA3dCmdDXSetCOTable *)pvCmd;
     234                    pCmd->cid              = pSvgaContext->u32Cid;
     235                    pCmd->mobid            = SVGA3D_INVALID_ID;
     236                    pCmd->type             = (SVGACOTableType)i;
     237                    pCmd->validSizeInBytes = 0;
     238                    SvgaCmdBufCommit(pSvga, sizeof(*pCmd));
     239                }
     240
     241                pvCmd = SvgaCmdBuf3dCmdReserve(pSvga, SVGA_3D_CMD_DESTROY_GB_MOB, sizeof(SVGA3dCmdDestroyGBMob), SVGA3D_INVALID_ID);
     242                if (pvCmd)
     243                {
     244                    SVGA3dCmdDestroyGBMob *pCmd = (SVGA3dCmdDestroyGBMob *)pvCmd;
     245                    pCmd->mobid = VMSVGAMOB_ID(pCOT->pMob);
     246                    SvgaCmdBufCommit(pSvga, sizeof(*pCmd));
     247                }
     248
     249                SvgaMobFree(pSvga, pCOT->pMob);
     250                pCOT->pMob = NULL;
     251            }
     252
     253            if (pCOT->hMemObj != NIL_RTR0MEMOBJ)
     254            {
     255                RTR0MemObjFree(pCOT->hMemObj, true);
     256                pCOT->hMemObj = NIL_RTR0MEMOBJ;
     257            }
     258        }
     259
    227260        SvgaDXContextDestroy(pSvga, pSvgaContext->u32Cid);
    228261        Status = SvgaDXContextIdFree(pSvga, pSvgaContext->u32Cid);
     
    233266        Status = SvgaContextIdFree(pSvga, pSvgaContext->u32Cid);
    234267    }
     268
     269    SvgaFlush(pSvga);
    235270
    236271    GaMemFree(pSvgaContext);
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