VirtualBox

Ignore:
Timestamp:
May 5, 2022 12:50:37 PM (3 years ago)
Author:
vboxsync
Message:

WDDM: Map/UnmapAperture paging ops, Render and Present. bugref:9845

File:
1 edited

Legend:

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

    r94835 r94847  
    283283}
    284284
     285
     286static NTSTATUS svgaRenderPatches(PVBOXWDDM_CONTEXT pContext, DXGKARG_RENDER *pRender, void *pvDmaBuffer, uint32_t cbDmaBuffer)
     287{
     288    /** @todo Verify that patch is within the DMA buffer. */
     289    RT_NOREF(pContext, cbDmaBuffer);
     290    NTSTATUS Status = STATUS_SUCCESS;
     291    uint32_t cOut = 0;
     292    for (unsigned i = 0; i < pRender->PatchLocationListInSize; ++i)
     293    {
     294        D3DDDI_PATCHLOCATIONLIST const *pIn = &pRender->pPatchLocationListIn[i];
     295        void * const pPatchAddress = (uint8_t *)pvDmaBuffer + pIn->PatchOffset;
     296        VBOXDXALLOCATIONTYPE const enmAllocationType = (VBOXDXALLOCATIONTYPE)pIn->DriverId;
     297
     298        DXGK_ALLOCATIONLIST *pAllocationListEntry = &pRender->pAllocationList[pIn->AllocationIndex];
     299        PVBOXWDDM_OPENALLOCATION pOA = (PVBOXWDDM_OPENALLOCATION)pAllocationListEntry->hDeviceSpecificAllocation;
     300        if (pOA)
     301        {
     302            PVBOXWDDM_ALLOCATION pAllocation = pOA->pAllocation;
     303            /* Allocation type determines what the patch is about. */
     304            Assert(pAllocation->dx.desc.enmAllocationType == enmAllocationType);
     305            if (enmAllocationType == VBOXDXALLOCATIONTYPE_SURFACE)
     306            {
     307                /* Surfaces might also need a mobid. */
     308                if (pAllocationListEntry->SegmentId == 3)
     309                {
     310                    /* DEFAULT resources only require the sid, because they exist outside the guest. */
     311                    if (pAllocation->dx.sid != SVGA3D_INVALID_ID)
     312                    {
     313                        *(uint32_t *)pPatchAddress = pAllocation->dx.sid;
     314                        continue;
     315                    }
     316                }
     317                else
     318                {
     319                    /* For Aperture segment, the surface need a mob too. */
     320                    if (   pAllocation->dx.sid != SVGA3D_INVALID_ID
     321                        && pAllocation->dx.mobid != SVGA3D_INVALID_ID)
     322                    {
     323                        *(uint32_t *)pPatchAddress = pAllocation->dx.sid;
     324                        continue;
     325                    }
     326                }
     327            }
     328            else if (enmAllocationType == VBOXDXALLOCATIONTYPE_SHADERS)
     329            {
     330                if (pAllocation->dx.mobid != SVGA3D_INVALID_ID)
     331                {
     332                    *(uint32_t *)pPatchAddress = pAllocation->dx.mobid;
     333                    continue;
     334                }
     335            }
     336        }
     337        else
     338        {
     339            if (   enmAllocationType == VBOXDXALLOCATIONTYPE_SURFACE
     340                || enmAllocationType == VBOXDXALLOCATIONTYPE_SHADERS)
     341            {
     342                *(uint32_t *)pPatchAddress = SVGA3D_INVALID_ID;
     343                continue;
     344            }
     345        }
     346
     347        pRender->pPatchLocationListOut[cOut++] = *pIn;
     348    }
     349
     350    GALOG(("pvDmaBuffer = %p, cbDmaBuffer = %u, cOut = %u\n", pvDmaBuffer, cbDmaBuffer, cOut));
     351
     352    pRender->pPatchLocationListOut = &pRender->pPatchLocationListOut[cOut];
     353    return Status;
     354}
     355
     356
     357NTSTATUS APIENTRY DxgkDdiDXRender(PVBOXWDDM_CONTEXT pContext, DXGKARG_RENDER *pRender)
     358{
     359    PVBOXWDDM_DEVICE pDevice = pContext->pDevice;
     360    PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
     361    VBOXWDDM_EXT_GA *pGaDevExt = pDevExt->pGa;
     362
     363    GALOG(("[%p] Command %p/%d, Dma %p/%d, Private %p/%d, MO %d, S %d, Phys 0x%RX64, AL %p/%d, PLLIn %p/%d, PLLOut %p/%d\n",
     364           pContext,
     365           pRender->pCommand, pRender->CommandLength,
     366           pRender->pDmaBuffer, pRender->DmaSize,
     367           pRender->pDmaBufferPrivateData, pRender->DmaBufferPrivateDataSize,
     368           pRender->MultipassOffset, pRender->DmaBufferSegmentId, pRender->DmaBufferPhysicalAddress.QuadPart,
     369           pRender->pAllocationList, pRender->AllocationListSize,
     370           pRender->pPatchLocationListIn, pRender->PatchLocationListInSize,
     371           pRender->pPatchLocationListOut, pRender->PatchLocationListOutSize
     372         ));
     373
     374    AssertReturn(pRender->DmaBufferPrivateDataSize >= sizeof(GARENDERDATA), STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER);
     375
     376    GARENDERDATA *pRenderData = NULL;  /* Pointer to the DMA buffer description. */
     377    uint32_t cbPrivateData = 0;        /* Bytes to place into the private data buffer. */
     378    uint32_t u32TargetLength = 0;      /* Bytes to place into the DMA buffer. */
     379    uint32_t u32ProcessedLength = 0;   /* Bytes consumed from command buffer. */
     380
     381    /* Calculate where the commands start. */
     382    void const *pvSource = (uint8_t *)pRender->pCommand + pRender->MultipassOffset;
     383    uint32_t cbSource = pRender->CommandLength - pRender->MultipassOffset;
     384
     385    NTSTATUS Status = STATUS_SUCCESS;
     386    __try
     387    {
     388        /* Generate DMA buffer from the supplied command buffer.
     389         * Store the command buffer descriptor to pDmaBufferPrivateData.
     390         *
     391         * The display miniport driver must validate the command buffer.
     392         *
     393         * Copy commands to the pDmaBuffer.
     394         */
     395        Status = SvgaRenderCommandsD3D(pGaDevExt->hw.pSvga, pContext->pSvgaContext,
     396                                       pRender->pDmaBuffer, pRender->DmaSize, pvSource, cbSource,
     397                                       &u32TargetLength, &u32ProcessedLength);
     398        if (NT_SUCCESS(Status))
     399        {
     400            Status = svgaRenderPatches(pContext, pRender, pRender->pDmaBuffer, u32ProcessedLength);
     401        }
     402
     403        /* Fill RenderData description in any case, it will be ignored if the above code failed. */
     404        pRenderData = (GARENDERDATA *)pRender->pDmaBufferPrivateData;
     405        pRenderData->u32DataType  = GARENDERDATA_TYPE_RENDER;
     406        pRenderData->cbData       = u32TargetLength;
     407        pRenderData->pFenceObject = NULL;
     408        pRenderData->pvDmaBuffer  = pRender->pDmaBuffer; /** @todo Should not be needed for D3D context. */
     409        pRenderData->pHwRenderData = NULL;
     410        cbPrivateData = sizeof(GARENDERDATA);
     411        GALOG(("Status = 0x%x\n", Status));
     412    }
     413    __except (EXCEPTION_EXECUTE_HANDLER)
     414    {
     415        Status = STATUS_INVALID_PARAMETER;
     416    }
     417
     418    switch (Status)
     419    {
     420        case STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER:
     421            pRender->MultipassOffset += u32ProcessedLength;
     422            RT_FALL_THRU();
     423        case STATUS_SUCCESS:
     424        {
     425            Assert(pRenderData);
     426            if (u32TargetLength == 0)
     427            {
     428                DEBUG_BREAKPOINT_TEST();
     429                /* Trigger command submission anyway by increasing pDmaBufferPrivateData */
     430                /* Update the DMA buffer description. */
     431                pRenderData->u32DataType  = GARENDERDATA_TYPE_FENCE;
     432                pRenderData->cbData       = u32TargetLength;
     433                /* pRenderData->pFenceObject stays */
     434                pRenderData->pvDmaBuffer  = NULL; /* Not used */
     435            }
     436            pRender->pDmaBuffer = (uint8_t *)pRender->pDmaBuffer + u32TargetLength;
     437            pRender->pDmaBufferPrivateData = (uint8_t *)pRender->pDmaBufferPrivateData + cbPrivateData;
     438        } break;
     439        default: break;
     440    }
     441
     442    return Status;
     443}
     444
     445
     446NTSTATUS APIENTRY DxgkDdiDXPresent(const HANDLE hContext, DXGKARG_PRESENT *pPresent)
     447{
     448    NTSTATUS Status = STATUS_SUCCESS;
     449    PVBOXWDDM_CONTEXT pContext = (PVBOXWDDM_CONTEXT)hContext;
     450    PVBOXWDDM_DEVICE pDevice = pContext->pDevice;
     451    PVBOXMP_DEVEXT pDevExt = pDevice->pAdapter;
     452
     453    DXGK_ALLOCATIONLIST *pSrc = &pPresent->pAllocationList[DXGK_PRESENT_SOURCE_INDEX];
     454    //DXGK_ALLOCATIONLIST *pDst = &pPresent->pAllocationList[DXGK_PRESENT_DESTINATION_INDEX];
     455
     456    if (pPresent->Flags.Blt)
     457    {
     458        //PVBOXWDDM_ALLOCATION pSrcAlloc = vboxWddmGetAllocationFromAllocList(pSrc);
     459        //PVBOXWDDM_ALLOCATION pDstAlloc = vboxWddmGetAllocationFromAllocList(pDst);
     460
     461        //GALOGG(GALOG_GROUP_PRESENT, ("Blt: sid=%x -> sid=%x\n", pSrcAlloc->AllocData.hostID, pDstAlloc->AllocData.hostID));
     462
     463        DEBUG_BREAKPOINT_TEST();
     464
     465        /* Generate empty DMA buffer.
     466         * Store the command buffer descriptor to pDmaBufferPrivateData.
     467         */
     468        GARENDERDATA *pRenderData = NULL;
     469        uint32_t u32TargetLength = 0;
     470        uint32_t cbPrivateData = 0;
     471
     472        if (pPresent->DmaBufferPrivateDataSize >= sizeof(GARENDERDATA))
     473        {
     474            /* Fill RenderData description in any case, it will be ignored if the above code failed. */
     475            pRenderData = (GARENDERDATA *)pPresent->pDmaBufferPrivateData;
     476            pRenderData->u32DataType  = GARENDERDATA_TYPE_PRESENT;
     477            pRenderData->cbData       = u32TargetLength;
     478            pRenderData->pFenceObject = NULL; /* Not a user request, so no user accessible fence object. */
     479            pRenderData->pvDmaBuffer  = pPresent->pDmaBuffer;
     480            pRenderData->pHwRenderData = NULL;
     481            cbPrivateData = sizeof(GARENDERDATA);
     482        }
     483        else
     484        {
     485            Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
     486        }
     487
     488        switch (Status)
     489        {
     490            case STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER:
     491                if (pRenderData == NULL)
     492                {
     493                    /* Not enough space in pDmaBufferPrivateData. */
     494                    break;
     495                }
     496                RT_FALL_THRU();
     497            case STATUS_SUCCESS:
     498            {
     499                pPresent->pDmaBuffer = (uint8_t *)pPresent->pDmaBuffer + u32TargetLength;
     500                pPresent->pDmaBufferPrivateData = (uint8_t *)pPresent->pDmaBufferPrivateData + cbPrivateData;
     501            } break;
     502            default: break;
     503        }
     504    }
     505    else if (pPresent->Flags.Flip)
     506    {
     507        PVBOXWDDM_OPENALLOCATION pOa = (PVBOXWDDM_OPENALLOCATION)pSrc->hDeviceSpecificAllocation;
     508        PVBOXWDDM_ALLOCATION pSrcAllocation = pOa->pAllocation;
     509        Assert(pSrcAllocation->dx.desc.fPrimary);
     510
     511        GALOGG(GALOG_GROUP_PRESENT, ("Flip: sid=%u %dx%d\n",
     512            pSrcAllocation->dx.sid, pSrcAllocation->dx.desc.surfaceInfo.size.width, pSrcAllocation->dx.desc.surfaceInfo.size.height));
     513
     514        /* Generate DMA buffer containing the present commands.
     515         * Store the command buffer descriptor to pDmaBufferPrivateData.
     516         */
     517        GARENDERDATA *pRenderData = NULL;
     518        uint32_t u32TargetLength = 0;
     519        uint32_t cbPrivateData = 0;
     520
     521        if (pPresent->DmaBufferPrivateDataSize >= sizeof(GARENDERDATA))
     522        {
     523            void *pvTarget          = pPresent->pDmaBuffer;
     524            const uint32_t cbTarget = pPresent->DmaSize;
     525            /* SVGA_3D_CMD_BLIT_SURFACE_TO_SCREEN */
     526            RECT rect;
     527            rect.left   = 0;
     528            rect.top    = 0;
     529            rect.right  = pSrcAllocation->dx.desc.surfaceInfo.size.width;
     530            rect.bottom = pSrcAllocation->dx.desc.surfaceInfo.size.height;
     531            uint32_t const cInClipRects = pPresent->SubRectCnt - pPresent->MultipassOffset;
     532            uint32_t cOutClipRects = 0;
     533            Status = SvgaGenBlitSurfaceToScreen(pDevExt->pGa->hw.pSvga,
     534                                                pSrcAllocation->dx.sid,
     535                                                &rect,
     536                                                pSrcAllocation->dx.desc.PrimaryDesc.VidPnSourceId,
     537                                                &rect,
     538                                                cInClipRects,
     539                                                pPresent->pDstSubRects + pPresent->MultipassOffset,
     540                                                pvTarget, cbTarget, &u32TargetLength, &cOutClipRects);
     541            if (Status == STATUS_BUFFER_OVERFLOW)
     542                Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
     543
     544            if (Status == STATUS_SUCCESS)
     545            {
     546                if (cOutClipRects < cInClipRects)
     547                {
     548                    /* Not all rectangles were copied. */
     549                    Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
     550                }
     551
     552                /* Advance the current rectangle index. */
     553                pPresent->MultipassOffset += cOutClipRects;
     554            }
     555
     556            /* Fill RenderData description in any case, it will be ignored if the above code failed. */
     557            pRenderData = (GARENDERDATA *)pPresent->pDmaBufferPrivateData;
     558            pRenderData->u32DataType  = GARENDERDATA_TYPE_PRESENT;
     559            pRenderData->cbData       = u32TargetLength;
     560            pRenderData->pFenceObject = NULL; /* Not a user request, so no user accessible fence object. */
     561            pRenderData->pvDmaBuffer = pPresent->pDmaBuffer;
     562            pRenderData->pHwRenderData = NULL;
     563            cbPrivateData = sizeof(GARENDERDATA);
     564        }
     565        else
     566        {
     567            Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
     568        }
     569
     570        switch (Status)
     571        {
     572            case STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER:
     573                if (pRenderData == NULL)
     574                {
     575                    /* Not enough space in pDmaBufferPrivateData. */
     576                    break;
     577                }
     578                RT_FALL_THRU();
     579            case STATUS_SUCCESS:
     580            {
     581                pPresent->pDmaBuffer = (uint8_t *)pPresent->pDmaBuffer + u32TargetLength;
     582                pPresent->pDmaBufferPrivateData = (uint8_t *)pPresent->pDmaBufferPrivateData + cbPrivateData;
     583            } break;
     584            default: break;
     585        }
     586    }
     587    else if (pPresent->Flags.ColorFill)
     588    {
     589        LogRelMax(16, ("ColorFill is not implemented\n"));
     590        AssertFailed();
     591
     592        /* Generate empty DMA buffer.
     593         * Store the command buffer descriptor to pDmaBufferPrivateData.
     594         */
     595        GARENDERDATA *pRenderData = NULL;
     596        uint32_t u32TargetLength = 0;
     597        uint32_t cbPrivateData = 0;
     598
     599        if (pPresent->DmaBufferPrivateDataSize >= sizeof(GARENDERDATA))
     600        {
     601            /* Fill RenderData description in any case, it will be ignored if the above code failed. */
     602            pRenderData = (GARENDERDATA *)pPresent->pDmaBufferPrivateData;
     603            pRenderData->u32DataType  = GARENDERDATA_TYPE_PRESENT;
     604            pRenderData->cbData       = u32TargetLength;
     605            pRenderData->pFenceObject = NULL; /* Not a user request, so no user accessible fence object. */
     606            pRenderData->pvDmaBuffer  = pPresent->pDmaBuffer;
     607            pRenderData->pHwRenderData = NULL;
     608            cbPrivateData = sizeof(GARENDERDATA);
     609        }
     610        else
     611        {
     612            Status = STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
     613        }
     614
     615        switch (Status)
     616        {
     617            case STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER:
     618                if (pRenderData == NULL)
     619                {
     620                    /* Not enough space in pDmaBufferPrivateData. */
     621                    break;
     622                }
     623                RT_FALL_THRU();
     624            case STATUS_SUCCESS:
     625            {
     626                pPresent->pDmaBuffer = (uint8_t *)pPresent->pDmaBuffer + u32TargetLength;
     627                pPresent->pDmaBufferPrivateData = (uint8_t *)pPresent->pDmaBufferPrivateData + cbPrivateData;
     628            } break;
     629            default: break;
     630        }
     631    }
     632    else
     633    {
     634        WARN(("cmd NOT IMPLEMENTED!! Flags(0x%x)", pPresent->Flags.Value));
     635        Status = STATUS_NOT_SUPPORTED;
     636    }
     637
     638    return Status;
     639}
     640
     641
     642static NTSTATUS svgaPagingMapApertureSegment(PVBOXMP_DEVEXT pDevExt, DXGKARG_BUILDPAGINGBUFFER *pBuildPagingBuffer, uint32_t *pcbCommands)
     643{
     644    VBOXWDDM_EXT_VMSVGA *pSvga = pDevExt->pGa->hw.pSvga;
     645
     646    /* Define a MOB for the supplied MDL and bind the allocation to the MOB. */
     647
     648    PVBOXWDDM_ALLOCATION pAllocation = (PVBOXWDDM_ALLOCATION)pBuildPagingBuffer->MapApertureSegment.hAllocation;
     649    AssertReturn(pAllocation, STATUS_INVALID_PARAMETER);
     650    AssertReturn(pBuildPagingBuffer->MapApertureSegment.SegmentId == 2, STATUS_INVALID_PARAMETER);
     651
     652    /** @todo Mobs require locked pages. Could DX provide a Mdl without locked pages? */
     653    Assert(pBuildPagingBuffer->MapApertureSegment.pMdl->MdlFlags & MDL_PAGES_LOCKED);
     654
     655    if (pAllocation->dx.mobid != SVGA3D_INVALID_ID)
     656    {
     657        AssertFailed();
     658        return STATUS_SUCCESS;
     659    }
     660
     661    PVMSVGAMOB pMob;
     662    NTSTATUS Status = SvgaMobCreate(pSvga, &pMob,
     663                                    pBuildPagingBuffer->MapApertureSegment.NumberOfPages,
     664                                    pBuildPagingBuffer->MapApertureSegment.hAllocation);
     665    AssertReturn(NT_SUCCESS(Status), Status);
     666
     667    Status = SvgaMobFillPageTableForMDL(pSvga, pMob, pBuildPagingBuffer->MapApertureSegment.pMdl,
     668                                        pBuildPagingBuffer->MapApertureSegment.MdlOffset);
     669    AssertReturnStmt(NT_SUCCESS(Status), SvgaMobFree(pSvga, pMob), Status);
     670
     671    pAllocation->dx.mobid = VMSVGAMOB_ID(pMob);
     672
     673    uint32_t cbRequired = sizeof(SVGA3dCmdHeader) + sizeof(SVGA3dCmdDefineGBMob64);
     674    if (pAllocation->dx.desc.enmAllocationType == VBOXDXALLOCATIONTYPE_SURFACE)
     675    {
     676        cbRequired += sizeof(SVGA3dCmdHeader) + sizeof(SVGA3dCmdBindGBSurface);
     677        cbRequired += sizeof(SVGA3dCmdHeader) + sizeof(SVGA3dCmdUpdateGBSurface);
     678    }
     679
     680    if (pBuildPagingBuffer->DmaSize < cbRequired)
     681    {
     682        SvgaMobFree(pSvga, pMob);
     683        return STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
     684    }
     685
     686    /* Add to the container. */
     687    ExAcquireFastMutex(&pSvga->SvgaMutex);
     688    RTAvlU32Insert(&pSvga->MobTree, &pMob->core);
     689    ExReleaseFastMutex(&pSvga->SvgaMutex);
     690
     691    uint8_t *pu8Cmd = (uint8_t *)pBuildPagingBuffer->pDmaBuffer;
     692
     693    SVGA3dCmdHeader *pHdr = (SVGA3dCmdHeader *)pu8Cmd;
     694    pHdr->id   = SVGA_3D_CMD_DEFINE_GB_MOB64;
     695    pHdr->size = sizeof(SVGA3dCmdDefineGBMob64);
     696    pu8Cmd += sizeof(*pHdr);
     697
     698    {
     699    SVGA3dCmdDefineGBMob64 *pCmd = (SVGA3dCmdDefineGBMob64 *)pu8Cmd;
     700    pCmd->mobid       = VMSVGAMOB_ID(pMob);
     701    pCmd->ptDepth     = pMob->enmMobFormat;
     702    pCmd->base        = pMob->base;
     703    pCmd->sizeInBytes = pMob->cbMob;
     704    pu8Cmd += sizeof(*pCmd);
     705    }
     706
     707    if (pAllocation->dx.desc.enmAllocationType == VBOXDXALLOCATIONTYPE_SURFACE)
     708    {
     709        /* Bind. */
     710        pHdr = (SVGA3dCmdHeader *)pu8Cmd;
     711        pHdr->id   = SVGA_3D_CMD_BIND_GB_SURFACE;
     712        pHdr->size = sizeof(SVGA3dCmdBindGBSurface);
     713        pu8Cmd += sizeof(*pHdr);
     714
     715        {
     716        SVGA3dCmdBindGBSurface *pCmd = (SVGA3dCmdBindGBSurface *)pu8Cmd;
     717        pCmd->sid         = pAllocation->dx.sid;
     718        pCmd->mobid       = VMSVGAMOB_ID(pMob);
     719        pu8Cmd += sizeof(*pCmd);
     720        }
     721
     722        /* Update */
     723        pHdr = (SVGA3dCmdHeader *)pu8Cmd;
     724        pHdr->id   = SVGA_3D_CMD_UPDATE_GB_SURFACE;
     725        pHdr->size = sizeof(SVGA3dCmdUpdateGBSurface);
     726        pu8Cmd += sizeof(*pHdr);
     727
     728        {
     729        SVGA3dCmdUpdateGBSurface *pCmd = (SVGA3dCmdUpdateGBSurface *)pu8Cmd;
     730        pCmd->sid         = pAllocation->dx.sid;
     731        pu8Cmd += sizeof(*pCmd);
     732        }
     733    }
     734
     735    *pcbCommands = (uintptr_t)pu8Cmd - (uintptr_t)pBuildPagingBuffer->pDmaBuffer;
     736
     737    return STATUS_SUCCESS;
     738}
     739
     740static NTSTATUS svgaPagingUnmapApertureSegment(PVBOXMP_DEVEXT pDevExt, DXGKARG_BUILDPAGINGBUFFER *pBuildPagingBuffer, uint32_t *pcbCommands)
     741{
     742    VBOXWDDM_EXT_VMSVGA *pSvga = pDevExt->pGa->hw.pSvga;
     743
     744    /* Unbind the allocation from the MOB and destroy the MOB which is bound to the allocation. */
     745
     746    PVBOXWDDM_ALLOCATION pAllocation = (PVBOXWDDM_ALLOCATION)pBuildPagingBuffer->UnmapApertureSegment.hAllocation;
     747    AssertReturn(pAllocation, STATUS_INVALID_PARAMETER);
     748    AssertReturn(pBuildPagingBuffer->UnmapApertureSegment.SegmentId == 2, STATUS_INVALID_PARAMETER);
     749
     750    if (pAllocation->dx.mobid == SVGA3D_INVALID_ID)
     751    {
     752        DEBUG_BREAKPOINT_TEST();
     753        return STATUS_SUCCESS;
     754    }
     755
     756    /* Find the mob. */
     757    ExAcquireFastMutex(&pSvga->SvgaMutex);
     758    PVMSVGAMOB pMob = (PVMSVGAMOB)RTAvlU32Get(&pSvga->MobTree, pAllocation->dx.mobid);
     759    ExReleaseFastMutex(&pSvga->SvgaMutex);
     760    AssertReturn(pMob, STATUS_INVALID_PARAMETER);
     761
     762    uint32_t cbRequired = sizeof(SVGA3dCmdHeader) + sizeof(SVGA3dCmdDestroyGBMob);
     763    if (pAllocation->dx.desc.enmAllocationType == VBOXDXALLOCATIONTYPE_SURFACE)
     764    {
     765        cbRequired += sizeof(SVGA3dCmdHeader) + sizeof(SVGA3dCmdBindGBSurface);
     766    }
     767
     768    if (pBuildPagingBuffer->DmaSize < cbRequired)
     769    {
     770        SvgaMobFree(pSvga, pMob);
     771        return STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER;
     772    }
     773
     774    uint8_t *pu8Cmd = (uint8_t *)pBuildPagingBuffer->pDmaBuffer;
     775
     776    SVGA3dCmdHeader *pHdr;
     777    if (pAllocation->dx.desc.enmAllocationType == VBOXDXALLOCATIONTYPE_SURFACE)
     778    {
     779        /* Unbind. */
     780        pHdr = (SVGA3dCmdHeader *)pu8Cmd;
     781        pHdr->id   = SVGA_3D_CMD_BIND_GB_SURFACE;
     782        pHdr->size = sizeof(SVGA3dCmdBindGBSurface);
     783        pu8Cmd += sizeof(*pHdr);
     784
     785        {
     786        SVGA3dCmdBindGBSurface *pCmd = (SVGA3dCmdBindGBSurface *)pu8Cmd;
     787        pCmd->sid   = pAllocation->dx.sid;
     788        pCmd->mobid = SVGA3D_INVALID_ID;
     789        pu8Cmd += sizeof(*pCmd);
     790        }
     791    }
     792
     793    pHdr = (SVGA3dCmdHeader *)pu8Cmd;
     794    pHdr->id   = SVGA_3D_CMD_DESTROY_GB_MOB;
     795    pHdr->size = sizeof(SVGA3dCmdDestroyGBMob);
     796    pu8Cmd += sizeof(*pHdr);
     797
     798    {
     799    SVGA3dCmdDestroyGBMob *pCmd = (SVGA3dCmdDestroyGBMob *)pu8Cmd;
     800    pCmd->mobid = VMSVGAMOB_ID(pMob);
     801    pu8Cmd += sizeof(*pCmd);
     802    }
     803
     804    *pcbCommands = (uintptr_t)pu8Cmd - (uintptr_t)pBuildPagingBuffer->pDmaBuffer;
     805
     806    SvgaMobFree(pSvga, pMob);
     807    pAllocation->dx.mobid = SVGA3D_INVALID_ID;
     808
     809    return STATUS_SUCCESS;
     810}
     811
     812
     813NTSTATUS DxgkDdiDXBuildPagingBuffer(PVBOXMP_DEVEXT pDevExt, DXGKARG_BUILDPAGINGBUFFER *pBuildPagingBuffer)
     814{
     815    AssertReturn(pBuildPagingBuffer->DmaBufferPrivateDataSize >= sizeof(GARENDERDATA), STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER);
     816
     817    NTSTATUS Status = STATUS_SUCCESS;
     818    uint32_t cbCommands = 0;
     819    switch (pBuildPagingBuffer->Operation)
     820    {
     821        case DXGK_OPERATION_TRANSFER:
     822        {
     823            DEBUG_BREAKPOINT_TEST();
     824            break;
     825        }
     826        case DXGK_OPERATION_FILL:
     827        {
     828            PVBOXWDDM_ALLOCATION pAllocation = (PVBOXWDDM_ALLOCATION)pBuildPagingBuffer->Fill.hAllocation;
     829            RT_NOREF(pAllocation);
     830            DEBUG_BREAKPOINT_TEST();
     831            break;
     832        }
     833        case DXGK_OPERATION_DISCARD_CONTENT:
     834        {
     835            DEBUG_BREAKPOINT_TEST();
     836            break;
     837        }
     838        case DXGK_OPERATION_MAP_APERTURE_SEGMENT:
     839        {
     840            Status = svgaPagingMapApertureSegment(pDevExt, pBuildPagingBuffer, &cbCommands);
     841            break;
     842        }
     843        case DXGK_OPERATION_UNMAP_APERTURE_SEGMENT:
     844        {
     845            Status = svgaPagingUnmapApertureSegment(pDevExt, pBuildPagingBuffer, &cbCommands);
     846            break;
     847        }
     848        default:
     849            AssertFailedStmt(Status = STATUS_NOT_IMPLEMENTED);
     850    }
     851
     852    /* Fill RenderData description in any case, it will be ignored if the above code failed. */
     853    GARENDERDATA *pRenderData = (GARENDERDATA *)pBuildPagingBuffer->pDmaBufferPrivateData;
     854    pRenderData->u32DataType   = GARENDERDATA_TYPE_PAGING;
     855    pRenderData->cbData        = cbCommands;
     856    pRenderData->pFenceObject  = NULL;
     857    pRenderData->pvDmaBuffer   = pBuildPagingBuffer->pDmaBuffer;
     858    pRenderData->pHwRenderData = NULL;
     859
     860    switch (Status)
     861    {
     862        case STATUS_GRAPHICS_INSUFFICIENT_DMA_BUFFER:
     863            AssertFailed(); /** @todo test */
     864            RT_FALL_THRU();
     865        case STATUS_SUCCESS:
     866        {
     867            pBuildPagingBuffer->pDmaBuffer = (uint8_t *)pBuildPagingBuffer->pDmaBuffer + cbCommands;
     868            pBuildPagingBuffer->pDmaBufferPrivateData = (uint8_t *)pBuildPagingBuffer->pDmaBufferPrivateData + sizeof(GARENDERDATA);
     869        } break;
     870        default: break;
     871    }
     872
     873    return Status;
     874}
     875
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