/**
 * Hyper-V state-save operation.
 *
 * @returns VBox status code.
 * @param   pVM     Pointer to the VM.
 * @param   pSSM    Pointer to the SSM handle.
 */
VMMR3_INT_DECL(int) gimR3HvSave(PVM pVM, PSSMHANDLE pSSM)
{
    PCGIMHV pcHv = &pVM->gim.s.u.Hv;

    /*
     * Save the Hyper-V SSM version.
     */
    SSMR3PutU32(pSSM, GIM_HV_SAVED_STATE_VERSION);

    /*
     * Save per-VM MSRs.
     */
    SSMR3PutU64(pSSM, pcHv->u64GuestOsIdMsr);
    SSMR3PutU64(pSSM, pcHv->u64HypercallMsr);
    SSMR3PutU64(pSSM, pcHv->u64TscPageMsr);

    /*
     * Save Hyper-V features / capabilities.
     */
    SSMR3PutU32(pSSM, pcHv->uBaseFeat);
    SSMR3PutU32(pSSM, pcHv->uPartFlags);
    SSMR3PutU32(pSSM, pcHv->uPowMgmtFeat);
    SSMR3PutU32(pSSM, pcHv->uMiscFeat);
    SSMR3PutU32(pSSM, pcHv->uHyperHints);
    SSMR3PutU32(pSSM, pcHv->uHyperCaps);

    /*
     * Save the Hypercall region.
     */
    PCGIMMMIO2REGION pcRegion = &pcHv->aMmio2Regions[GIM_HV_HYPERCALL_PAGE_REGION_IDX];
    SSMR3PutU8(pSSM,     pcRegion->iRegion);
    SSMR3PutBool(pSSM,   pcRegion->fRCMapping);
    SSMR3PutU32(pSSM,    pcRegion->cbRegion);
    SSMR3PutGCPhys(pSSM, pcRegion->GCPhysPage);
    SSMR3PutStrZ(pSSM,   pcRegion->szDescription);

    /*
     * Save the reference TSC region.
     */
    pcRegion = &pcHv->aMmio2Regions[GIM_HV_REF_TSC_PAGE_REGION_IDX];
    SSMR3PutU8(pSSM,     pcRegion->iRegion);
    SSMR3PutBool(pSSM,   pcRegion->fRCMapping);
    SSMR3PutU32(pSSM,    pcRegion->cbRegion);
    SSMR3PutGCPhys(pSSM, pcRegion->GCPhysPage);
    SSMR3PutStrZ(pSSM,   pcRegion->szDescription);
    /* Save the TSC sequence so we can bump it on restore (as the CPU frequency/offset may change). */
    uint32_t uTscSequence = 0;
    if (   pcRegion->fMapped
        && MSR_GIM_HV_REF_TSC_IS_ENABLED(pcHv->u64TscPageMsr))
    {
        PCGIMHVREFTSC pcRefTsc = (PCGIMHVREFTSC)pcRegion->pvPageR3;
        uTscSequence = pcRefTsc->u32TscSequence;
    }

    return SSMR3PutU32(pSSM, uTscSequence);
}
Exemple #2
0
static void crDLMSaveListsCb(unsigned long key, void *pData1, void *pData2)
{
    DLMListInfo         *pListInfo      = (DLMListInfo*)pData1;
    CRDLMSaveListsCbArg *pArg           = (CRDLMSaveListsCbArg *)pData2;
    PSSMHANDLE           pSSM           = pArg->pSSM;
    DLMInstanceList     *pInstance      = pListInfo->first;
    uint32_t             cInstanceCheck = 0;
    int32_t              rc;

    crDebug("Saving Display Lists: found ID=%u, numInstances=%d.", key, pListInfo->numInstances);

    /* Store Display List length. */
    rc = SSMR3PutU32(pSSM, pListInfo->numInstances);
    if (RT_SUCCESS(rc))
    {
        /* Store Display List (guest) ID. */
        rc = SSMR3PutU32(pSSM, (uint32_t)key);
        if (RT_SUCCESS(rc))
        {
            /* Store each Display List item one by one. */
            while (pInstance)
            {
                /* Let's count each list item and compare total number with pListInfo->numInstances.
                 * This is simple consistency check. */
                cInstanceCheck++;

                /* Store instance data size. */
                rc = SSMR3PutU32(pSSM, (uint32_t)pInstance->cbInstance);
                if (RT_SUCCESS(rc))
                {
                    rc = SSMR3PutMem(pSSM, pInstance, pInstance->cbInstance);
                    if (RT_SUCCESS(rc))
                    {
                        /* We just stored all we need. Let's move on to the next list element. */
                        pInstance = pInstance->next;
                        continue;
                    }
                }

                crError("Saving Display Lists: can't store data.");

                pArg->err = 1;
                return;
            }

            if (cInstanceCheck == pListInfo->numInstances)
                return;

            crError("Saving Display Lists: list currupted.");
        }
    }

    pArg->err = 1;
}
Exemple #3
0
static DECLCALLBACK(int) svcSaveState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
{
#ifndef UNIT_TEST
    /* If there are any pending requests, they must be completed here. Since
     * the service is single threaded, there could be only requests
     * which the service itself has postponed.
     *
     * HGCM knows that the state is being saved and that the pfnComplete
     * calls are just clean ups. These requests are saved by the VMMDev.
     *
     * When the state will be restored, these requests will be reissued
     * by VMMDev. The service therefore must save state as if there were no
     * pending request.
     */
    LogRel2 (("svcSaveState: u32ClientID = %d\n", u32ClientID));

    VBOXCLIPBOARDCLIENTDATA *pClient = (VBOXCLIPBOARDCLIENTDATA *)pvClient;

    /* This field used to be the length. We're using it as a version field
       with the high bit set. */
    SSMR3PutU32 (pSSM, UINT32_C (0x80000002));
    int rc = SSMR3PutStructEx (pSSM, pClient, sizeof(*pClient), 0 /*fFlags*/, &g_aClipboardClientDataFields[0], NULL);
    AssertRCReturn (rc, rc);

    if (pClient->fAsync)
    {
        g_pHelpers->pfnCallComplete (pClient->async.callHandle, VINF_SUCCESS /* error code is not important here. */);
        pClient->fAsync = false;
    }

    vboxSvcClipboardCompleteReadData (pClient, VINF_SUCCESS, 0);

#endif /* !UNIT_TEST */
    return VINF_SUCCESS;
}
Exemple #4
0
/**
 * KVM state-save operation.
 *
 * @returns VBox status code.
 * @param   pVM     Pointer to the VM.
 * @param   pSSM    Pointer to the SSM handle.
 */
VMMR3_INT_DECL(int) gimR3KvmSave(PVM pVM, PSSMHANDLE pSSM)
{
    PCGIMKVM pcKvm = &pVM->gim.s.u.Kvm;

    /*
     * Save the KVM SSM version.
     */
    SSMR3PutU32(pSSM, GIM_KVM_SAVED_STATE_VERSION);

    /*
     * Save per-VCPU data.
     */
    for (uint32_t i = 0; i < pVM->cCpus; i++)
    {
        PCGIMKVMCPU pcKvmCpu = &pVM->aCpus[i].gim.s.u.KvmCpu;

        /* Guest may alter flags (namely GIM_KVM_SYSTEM_TIME_FLAGS_GUEST_PAUSED bit). So re-read them from guest-memory. */
        GIMKVMSYSTEMTIME SystemTime;
        RT_ZERO(SystemTime);
        if (MSR_GIM_KVM_SYSTEM_TIME_IS_ENABLED(pcKvmCpu->u64SystemTimeMsr))
        {
            int rc = PGMPhysSimpleReadGCPhys(pVM, &SystemTime, pcKvmCpu->GCPhysSystemTime, sizeof(GIMKVMSYSTEMTIME));
            AssertRCReturn(rc, rc);
        }

        SSMR3PutU64(pSSM, pcKvmCpu->u64SystemTimeMsr);
        SSMR3PutU64(pSSM, pcKvmCpu->uTsc);
        SSMR3PutU64(pSSM, pcKvmCpu->uVirtNanoTS);
        SSMR3PutGCPhys(pSSM, pcKvmCpu->GCPhysSystemTime);
        SSMR3PutU32(pSSM, pcKvmCpu->u32SystemTimeVersion);
        SSMR3PutU8(pSSM, SystemTime.fFlags);
    }

    /*
     * Save per-VM data.
     */
    SSMR3PutU64(pSSM, pcKvm->u64WallClockMsr);
    return SSMR3PutU32(pSSM, pcKvm->uBaseFeat);
}
Exemple #5
0
/**
 * Save a queue state.
 *
 * @param   pSSM                SSM handle to write the state to.
 * @param   pQ                  Pointer to the queue.
 */
static void ps2kSaveQueue(PSSMHANDLE pSSM, GeneriQ *pQ)
{
    uint32_t    cItems = pQ->cUsed;
    int         i;

    /* Only save the number of items. Note that the read/write
     * positions aren't saved as they will be rebuilt on load.
     */
    SSMR3PutU32(pSSM, cItems);

    LogFlow(("Storing %d items from queue %p\n", cItems, pQ));

    /* Save queue data - only the bytes actually used (typically zero). */
    for (i = pQ->rpos; cItems-- > 0; i = (i + 1) % pQ->cSize)
        SSMR3PutU8(pSSM, pQ->abQueue[i]);
}
Exemple #6
0
int32_t DLM_APIENTRY crDLMSaveState(CRDLM *dlm, PSSMHANDLE pSSM)
{
    uint32_t ui32;
    int32_t  rc;

    CRDLMSaveListsCbArg arg;

    arg.pSSM = pSSM;
    arg.err = 0;

    /* Save number of Display Lists assigned to current DLM context. */
    ui32 = (uint32_t)crHashtableNumElements(dlm->displayLists);
    rc = SSMR3PutU32(pSSM, ui32); AssertRCReturn(rc, rc);

    crHashtableWalk(dlm->displayLists, crDLMSaveListsCb, (void *)&arg);

    return arg.err == 0;
}
static DECLCALLBACK(int) svcSaveState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
{
#ifndef UNIT_TEST
    /*
     * When the state will be restored, pending requests will be reissued
     * by VMMDev. The service therefore must save state as if there were no
     * pending request.
     * Pending requests, if any, will be completed in svcDisconnect.
     */
    LogRel2 (("svcSaveState: u32ClientID = %d\n", u32ClientID));

    VBOXCLIPBOARDCLIENTDATA *pClient = (VBOXCLIPBOARDCLIENTDATA *)pvClient;

    /* This field used to be the length. We're using it as a version field
       with the high bit set. */
    SSMR3PutU32 (pSSM, UINT32_C (0x80000002));
    int rc = SSMR3PutStructEx (pSSM, pClient, sizeof(*pClient), 0 /*fFlags*/, &g_aClipboardClientDataFields[0], NULL);
    AssertRCReturn (rc, rc);
#endif /* !UNIT_TEST */
    return VINF_SUCCESS;
}
int vmsvga3dSaveExec(PVGASTATE pThis, PSSMHANDLE pSSM)
{
    PVMSVGA3DSTATE pState = pThis->svga.p3dState;
    AssertReturn(pState, VERR_NO_MEMORY);
    int            rc;

    /* Save a copy of the generic 3d state first. */
    rc = SSMR3PutStructEx(pSSM, pState, sizeof(*pState), 0, g_aVMSVGA3DSTATEFields, NULL);
    AssertRCReturn(rc, rc);

#ifdef VMSVGA3D_OPENGL
    /* Save the shared context. */
    if (pState->SharedCtx.id == VMSVGA3D_SHARED_CTX_ID)
    {
        rc = vmsvga3dSaveContext(pThis, pSSM, &pState->SharedCtx);
        AssertRCReturn(rc, rc);
    }
#endif

    /* Save all active contexts. */
    for (uint32_t i = 0; i < pState->cContexts; i++)
    {
        rc = vmsvga3dSaveContext(pThis, pSSM, pState->papContexts[i]);
        AssertRCReturn(rc, rc);
    }

    /* Save all active surfaces. */
    for (uint32_t sid = 0; sid < pState->cSurfaces; sid++)
    {
        PVMSVGA3DSURFACE pSurface = pState->papSurfaces[sid];

        /* Save the id first. */
        rc = SSMR3PutU32(pSSM, pSurface->id);
        AssertRCReturn(rc, rc);

        if (pSurface->id != SVGA3D_INVALID_ID)
        {
            /* Save a copy of the surface structure first. */
            rc = SSMR3PutStructEx(pSSM, pSurface, sizeof(*pSurface), 0, g_aVMSVGA3DSURFACEFields, NULL);
            AssertRCReturn(rc, rc);

            /* Save the mip map level info. */
            for (uint32_t face=0; face < pSurface->cFaces; face++)
            {
                for (uint32_t i = 0; i < pSurface->faces[0].numMipLevels; i++)
                {
                    uint32_t idx = i + face * pSurface->faces[0].numMipLevels;
                    PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->pMipmapLevels[idx];

                    /* Save a copy of the mip map level struct. */
                    rc = SSMR3PutStructEx(pSSM, pMipmapLevel, sizeof(*pMipmapLevel), 0, g_aVMSVGA3DMIPMAPLEVELFields, NULL);
                    AssertRCReturn(rc, rc);
                }
            }

            /* Save the mip map level data. */
            for (uint32_t face=0; face < pSurface->cFaces; face++)
            {
                for (uint32_t i = 0; i < pSurface->faces[0].numMipLevels; i++)
                {
                    uint32_t idx = i + face * pSurface->faces[0].numMipLevels;
                    PVMSVGA3DMIPMAPLEVEL pMipmapLevel = &pSurface->pMipmapLevels[idx];

                    Log(("Surface sid=%d: save mipmap level %d with %x bytes data.\n", sid, i, pMipmapLevel->cbSurface));

                    if (!VMSVGA3DSURFACE_HAS_HW_SURFACE(pSurface))
                    {
                        if (pMipmapLevel->fDirty)
                        {
                            /* Data follows */
                            rc = SSMR3PutBool(pSSM, true);
                            AssertRCReturn(rc, rc);

                            Assert(pMipmapLevel->cbSurface);
                            rc = SSMR3PutMem(pSSM, pMipmapLevel->pSurfaceData, pMipmapLevel->cbSurface);
                            AssertRCReturn(rc, rc);
                        }
                        else
                        {
                            /* No data follows */
                            rc = SSMR3PutBool(pSSM, false);
                            AssertRCReturn(rc, rc);
                        }
                    }
                    else
                    {
#ifdef VMSVGA3D_DIRECT3D
                        void            *pData;
                        bool             fRenderTargetTexture = false;
                        bool             fTexture = false;
                        bool             fSkipSave = false;
                        HRESULT          hr;

                        Assert(pMipmapLevel->cbSurface);
                        pData = RTMemAllocZ(pMipmapLevel->cbSurface);
                        AssertReturn(pData, VERR_NO_MEMORY);

                        switch (pSurface->enmD3DResType)
                        {
                        case VMSVGA3D_D3DRESTYPE_CUBE_TEXTURE:
                        case VMSVGA3D_D3DRESTYPE_VOLUME_TEXTURE:
                            AssertFailed(); /// @todo
                            fSkipSave = true;
                            break;
                        case VMSVGA3D_D3DRESTYPE_SURFACE:
                        case VMSVGA3D_D3DRESTYPE_TEXTURE:
                        {
                            if (pSurface->surfaceFlags & SVGA3D_SURFACE_HINT_DEPTHSTENCIL)
                            {
                               /** @todo unable to easily fetch depth surface data in d3d 9 */
                               fSkipSave = true;
                               break;
                            }

                            fTexture = (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_TEXTURE);
                            fRenderTargetTexture = fTexture && (pSurface->surfaceFlags & SVGA3D_SURFACE_HINT_RENDERTARGET);

                            D3DLOCKED_RECT LockedRect;

                            if (fTexture)
                            {
                                if (pSurface->bounce.pTexture)
                                {
                                    if (    !pSurface->fDirty
                                        &&  fRenderTargetTexture
                                        &&  i == 0 /* only the first time */)
                                    {
                                        IDirect3DSurface9 *pSrc, *pDest;

                                        /** @todo stricter checks for associated context */
                                        uint32_t cid = pSurface->idAssociatedContext;
                                        if (    cid >= pState->cContexts
                                            ||  pState->papContexts[cid]->id != cid)
                                        {
                                            Log(("vmsvga3dSaveExec invalid context id (%x - %x)!\n", cid, (cid >= pState->cContexts) ? -1 : pState->papContexts[cid]->id));
                                            AssertFailedReturn(VERR_INVALID_PARAMETER);
                                        }
                                        PVMSVGA3DCONTEXT pContext = pState->papContexts[cid];

                                        hr = pSurface->bounce.pTexture->GetSurfaceLevel(i, &pDest);
                                        AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);

                                        hr = pSurface->u.pTexture->GetSurfaceLevel(i, &pSrc);
                                        AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetSurfaceLevel failed with %x\n", hr), VERR_INTERNAL_ERROR);

                                        hr = pContext->pDevice->GetRenderTargetData(pSrc, pDest);
                                        AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: GetRenderTargetData failed with %x\n", hr), VERR_INTERNAL_ERROR);

                                        pSrc->Release();
                                        pDest->Release();
                                    }

                                    hr = pSurface->bounce.pTexture->LockRect(i, /* texture level */
                                                                             &LockedRect,
                                                                             NULL,
                                                                             D3DLOCK_READONLY);
                                }
                                else
                                    hr = pSurface->u.pTexture->LockRect(i, /* texture level */
                                                                        &LockedRect,
                                                                        NULL,
                                                                        D3DLOCK_READONLY);
                            }
                            else
                                hr = pSurface->u.pSurface->LockRect(&LockedRect,
                                                                    NULL,
                                                                    D3DLOCK_READONLY);
                            AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: LockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);

                            /* Copy the data one line at a time in case the internal pitch is different. */
                            for (uint32_t j = 0; j < pMipmapLevel->cBlocksY; ++j)
                            {
                                uint8_t *pu8Dst = (uint8_t *)pData + j * pMipmapLevel->cbSurfacePitch;
                                const uint8_t *pu8Src = (uint8_t *)LockedRect.pBits + j * LockedRect.Pitch;
                                memcpy(pu8Dst, pu8Src, pMipmapLevel->cbSurfacePitch);
                            }

                            if (fTexture)
                            {
                                if (pSurface->bounce.pTexture)
                                {
                                    hr = pSurface->bounce.pTexture->UnlockRect(i);
                                    AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
                                }
                                else
                                    hr = pSurface->u.pTexture->UnlockRect(i);
                            }
                            else
                                hr = pSurface->u.pSurface->UnlockRect();
                            AssertMsgReturn(hr == D3D_OK, ("vmsvga3dSaveExec: UnlockRect failed with %x\n", hr), VERR_INTERNAL_ERROR);
                            break;
                        }

                        case VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER:
                        case VMSVGA3D_D3DRESTYPE_INDEX_BUFFER:
                        {
                            /* Current type of the buffer. */
                            const bool fVertex = (pSurface->enmD3DResType == VMSVGA3D_D3DRESTYPE_VERTEX_BUFFER);

                            uint8_t *pD3DData;

                            if (fVertex)
                                hr = pSurface->u.pVertexBuffer->Lock(0, 0, (void **)&pD3DData, D3DLOCK_READONLY);
                            else
                                hr = pSurface->u.pIndexBuffer->Lock(0, 0, (void **)&pD3DData, D3DLOCK_READONLY);
                            AssertMsg(hr == D3D_OK, ("vmsvga3dSaveExec: Lock %s failed with %x\n", (fVertex) ? "vertex" : "index", hr));

                            memcpy(pData, pD3DData, pMipmapLevel->cbSurface);

                            if (fVertex)
                                hr = pSurface->u.pVertexBuffer->Unlock();
                            else
                                hr = pSurface->u.pIndexBuffer->Unlock();
                            AssertMsg(hr == D3D_OK, ("vmsvga3dSaveExec: Unlock %s failed with %x\n", (fVertex) ? "vertex" : "index", hr));
                            break;
                        }

                        default:
                            AssertFailed();
                            break;
                        }

                        if (!fSkipSave)
                        {
                            /* Data follows */
                            rc = SSMR3PutBool(pSSM, true);
                            AssertRCReturn(rc, rc);

                            /* And write the surface data. */
                            rc = SSMR3PutMem(pSSM, pData, pMipmapLevel->cbSurface);
                            AssertRCReturn(rc, rc);
                        }
                        else
                        {
                            /* No data follows */
                            rc = SSMR3PutBool(pSSM, false);
                            AssertRCReturn(rc, rc);
                        }

                        RTMemFree(pData);
#elif defined(VMSVGA3D_OPENGL)
                        void *pData = NULL;

                        PVMSVGA3DCONTEXT pContext = &pState->SharedCtx;
                        VMSVGA3D_SET_CURRENT_CONTEXT(pState, pContext);

                        Assert(pMipmapLevel->cbSurface);

                        switch (pSurface->enmOGLResType)
                        {
                        default:
                            AssertFailed();
                            RT_FALL_THRU();
                        case VMSVGA3D_OGLRESTYPE_RENDERBUFFER:
                            /** @todo fetch data from the renderbuffer. Not used currently. */
                            /* No data follows */
                            rc = SSMR3PutBool(pSSM, false);
                            AssertRCReturn(rc, rc);
                            break;

                        case VMSVGA3D_OGLRESTYPE_TEXTURE:
                        {
                            GLint activeTexture;

                            pData = RTMemAllocZ(pMipmapLevel->cbSurface);
                            AssertReturn(pData, VERR_NO_MEMORY);

                            glGetIntegerv(GL_TEXTURE_BINDING_2D, &activeTexture);
                            VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);

                            glBindTexture(GL_TEXTURE_2D, pSurface->oglId.texture);
                            VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);

                            /* Set row length and alignment of the output data. */
                            VMSVGAPACKPARAMS SavedParams;
                            vmsvga3dOglSetPackParams(pState, pContext, pSurface, &SavedParams);

                            glGetTexImage(GL_TEXTURE_2D,
                                          i,
                                          pSurface->formatGL,
                                          pSurface->typeGL,
                                          pData);
                            VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);

                            vmsvga3dOglRestorePackParams(pState, pContext, pSurface, &SavedParams);

                            /* Data follows */
                            rc = SSMR3PutBool(pSSM, true);
                            AssertRCReturn(rc, rc);

                            /* And write the surface data. */
                            rc = SSMR3PutMem(pSSM, pData, pMipmapLevel->cbSurface);
                            AssertRCReturn(rc, rc);

                            /* Restore the old active texture. */
                            glBindTexture(GL_TEXTURE_2D, activeTexture);
                            VMSVGA3D_CHECK_LAST_ERROR_WARN(pState, pContext);
                            break;
                        }

                        case VMSVGA3D_OGLRESTYPE_BUFFER:
                        {
                            uint8_t *pBufferData;

                            pState->ext.glBindBuffer(GL_ARRAY_BUFFER, pSurface->oglId.buffer);
                            VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);

                            pBufferData = (uint8_t *)pState->ext.glMapBuffer(GL_ARRAY_BUFFER, GL_READ_ONLY);
                            VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);
                            Assert(pBufferData);

                            /* Data follows */
                            rc = SSMR3PutBool(pSSM, true);
                            AssertRCReturn(rc, rc);

                            /* And write the surface data. */
                            rc = SSMR3PutMem(pSSM, pBufferData, pMipmapLevel->cbSurface);
                            AssertRCReturn(rc, rc);

                            pState->ext.glUnmapBuffer(GL_ARRAY_BUFFER);
                            VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);

                            pState->ext.glBindBuffer(GL_ARRAY_BUFFER, 0);
                            VMSVGA3D_CHECK_LAST_ERROR(pState, pContext);

                        }
                        }
                        if (pData)
                            RTMemFree(pData);
#else
#error "Unexpected 3d backend"
#endif
                    }
                }
            }
        }
    }
    return VINF_SUCCESS;
}
static int vmsvga3dSaveContext(PVGASTATE pThis, PSSMHANDLE pSSM, PVMSVGA3DCONTEXT pContext)
{
    PVMSVGA3DSTATE pState = pThis->svga.p3dState;
    uint32_t cid = pContext->id;

    /* Save the id first. */
    int rc = SSMR3PutU32(pSSM, cid);
    AssertRCReturn(rc, rc);

    if (cid != SVGA3D_INVALID_ID)
    {
        /* Save a copy of the context structure first. */
        rc = SSMR3PutStructEx(pSSM, pContext, sizeof(*pContext), 0, g_aVMSVGA3DCONTEXTFields, NULL);
        AssertRCReturn(rc, rc);

        /* Save all pixel shaders. */
        for (uint32_t j = 0; j < pContext->cPixelShaders; j++)
        {
            PVMSVGA3DSHADER pShader = &pContext->paPixelShader[j];

            /* Save the id first. */
            rc = SSMR3PutU32(pSSM, pShader->id);
            AssertRCReturn(rc, rc);

            if (pShader->id != SVGA3D_INVALID_ID)
            {
                uint32_t cbData = pShader->cbData;

                /* Save a copy of the shader struct. */
                rc = SSMR3PutStructEx(pSSM, pShader, sizeof(*pShader), 0, g_aVMSVGA3DSHADERFields, NULL);
                AssertRCReturn(rc, rc);

                Log(("Save pixelshader shid=%d with %x bytes code.\n", pShader->id, cbData));
                rc = SSMR3PutMem(pSSM, pShader->pShaderProgram, cbData);
                AssertRCReturn(rc, rc);
            }
        }

        /* Save all vertex shaders. */
        for (uint32_t j = 0; j < pContext->cVertexShaders; j++)
        {
            PVMSVGA3DSHADER pShader = &pContext->paVertexShader[j];

            /* Save the id first. */
            rc = SSMR3PutU32(pSSM, pShader->id);
            AssertRCReturn(rc, rc);

            if (pShader->id != SVGA3D_INVALID_ID)
            {
                uint32_t cbData = pShader->cbData;

                /* Save a copy of the shader struct. */
                rc = SSMR3PutStructEx(pSSM, pShader, sizeof(*pShader), 0, g_aVMSVGA3DSHADERFields, NULL);
                AssertRCReturn(rc, rc);

                Log(("Save vertex shader shid=%d with %x bytes code.\n", pShader->id, cbData));
                /* Fetch the shader code and save it. */
                rc = SSMR3PutMem(pSSM, pShader->pShaderProgram, cbData);
                AssertRCReturn(rc, rc);
            }
        }

        /* Save pixel shader constants. */
        for (uint32_t j = 0; j < pContext->state.cPixelShaderConst; j++)
        {
            rc = SSMR3PutStructEx(pSSM, &pContext->state.paPixelShaderConst[j], sizeof(pContext->state.paPixelShaderConst[j]), 0, g_aVMSVGASHADERCONSTFields, NULL);
            AssertRCReturn(rc, rc);
        }

        /* Save vertex shader constants. */
        for (uint32_t j = 0; j < pContext->state.cVertexShaderConst; j++)
        {
            rc = SSMR3PutStructEx(pSSM, &pContext->state.paVertexShaderConst[j], sizeof(pContext->state.paVertexShaderConst[j]), 0, g_aVMSVGASHADERCONSTFields, NULL);
            AssertRCReturn(rc, rc);
        }

        /* Save texture stage and samplers state. */

        /* Number of stages/samplers. */
        rc = SSMR3PutU32(pSSM, RT_ELEMENTS(pContext->state.aTextureStates));
        AssertRCReturn(rc, rc);

        /* Number of texture states. */
        rc = SSMR3PutU32(pSSM, RT_ELEMENTS(pContext->state.aTextureStates[0]));
        AssertRCReturn(rc, rc);

        for (uint32_t iStage = 0; iStage < RT_ELEMENTS(pContext->state.aTextureStates); ++iStage)
        {
            for (uint32_t j = 0; j < RT_ELEMENTS(pContext->state.aTextureStates[0]); ++j)
            {
                SVGA3dTextureState *pTextureState = &pContext->state.aTextureStates[iStage][j];

                SSMR3PutU32(pSSM, pTextureState->stage);
                SSMR3PutU32(pSSM, pTextureState->name);
                rc = SSMR3PutU32(pSSM, pTextureState->value);
                AssertRCReturn(rc, rc);
            }
        }

        /* Occlusion query. */
        if (!VMSVGA3DQUERY_EXISTS(&pContext->occlusion))
        {
            pContext->occlusion.enmQueryState = VMSVGA3DQUERYSTATE_NULL;
        }

        switch (pContext->occlusion.enmQueryState)
        {
            case VMSVGA3DQUERYSTATE_BUILDING:
                /* Stop collecting data. Fetch partial result. Save result. */
                vmsvga3dOcclusionQueryEnd(pState, pContext);
                RT_FALL_THRU();
            case VMSVGA3DQUERYSTATE_ISSUED:
                /* Fetch result. Save result. */
                pContext->occlusion.u32QueryResult = 0;
                vmsvga3dOcclusionQueryGetData(pState, pContext, &pContext->occlusion.u32QueryResult);
                RT_FALL_THRU();
            case VMSVGA3DQUERYSTATE_SIGNALED:
                /* Save result. Nothing to do here. */
                break;

            default:
                AssertFailed();
                RT_FALL_THRU();
            case VMSVGA3DQUERYSTATE_NULL:
                pContext->occlusion.enmQueryState = VMSVGA3DQUERYSTATE_NULL;
                pContext->occlusion.u32QueryResult = 0;
                break;
        }

        rc = SSMR3PutStructEx(pSSM, &pContext->occlusion, sizeof(pContext->occlusion), 0, g_aVMSVGA3DQUERYFields, NULL);
        AssertRCReturn(rc, rc);
    }

    return VINF_SUCCESS;
}
static int vmsvga3dSaveContext(PVGASTATE pThis, PSSMHANDLE pSSM, PVMSVGA3DCONTEXT pContext)
{
    uint32_t cid = pContext->id;

    /* Save the id first. */
    int rc = SSMR3PutU32(pSSM, cid);
    AssertRCReturn(rc, rc);

    if (cid != SVGA3D_INVALID_ID)
    {
        /* Save a copy of the context structure first. */
        rc = SSMR3PutStructEx(pSSM, pContext, sizeof(*pContext), 0, g_aVMSVGA3DCONTEXTFields, NULL);
        AssertRCReturn(rc, rc);

        /* Save all pixel shaders. */
        for (uint32_t j = 0; j < pContext->cPixelShaders; j++)
        {
            PVMSVGA3DSHADER pShader = &pContext->paPixelShader[j];

            /* Save the id first. */
            rc = SSMR3PutU32(pSSM, pShader->id);
            AssertRCReturn(rc, rc);

            if (pShader->id != SVGA3D_INVALID_ID)
            {
                uint32_t cbData = pShader->cbData;

                /* Save a copy of the shader struct. */
                rc = SSMR3PutStructEx(pSSM, pShader, sizeof(*pShader), 0, g_aVMSVGA3DSHADERFields, NULL);
                AssertRCReturn(rc, rc);

                Log(("Save pixelshader shid=%d with %x bytes code.\n", pShader->id, cbData));
                rc = SSMR3PutMem(pSSM, pShader->pShaderProgram, cbData);
                AssertRCReturn(rc, rc);
            }
        }

        /* Save all vertex shaders. */
        for (uint32_t j = 0; j < pContext->cVertexShaders; j++)
        {
            PVMSVGA3DSHADER pShader = &pContext->paVertexShader[j];

            /* Save the id first. */
            rc = SSMR3PutU32(pSSM, pShader->id);
            AssertRCReturn(rc, rc);

            if (pShader->id != SVGA3D_INVALID_ID)
            {
                uint32_t cbData = pShader->cbData;

                /* Save a copy of the shader struct. */
                rc = SSMR3PutStructEx(pSSM, pShader, sizeof(*pShader), 0, g_aVMSVGA3DSHADERFields, NULL);
                AssertRCReturn(rc, rc);

                Log(("Save vertex shader shid=%d with %x bytes code.\n", pShader->id, cbData));
                /* Fetch the shader code and save it. */
                rc = SSMR3PutMem(pSSM, pShader->pShaderProgram, cbData);
                AssertRCReturn(rc, rc);
            }
        }

        /* Save pixel shader constants. */
        for (uint32_t j = 0; j < pContext->state.cPixelShaderConst; j++)
        {
            rc = SSMR3PutStructEx(pSSM, &pContext->state.paPixelShaderConst[j], sizeof(pContext->state.paPixelShaderConst[j]), 0, g_aVMSVGASHADERCONSTFields, NULL);
            AssertRCReturn(rc, rc);
        }

        /* Save vertex shader constants. */
        for (uint32_t j = 0; j < pContext->state.cVertexShaderConst; j++)
        {
            rc = SSMR3PutStructEx(pSSM, &pContext->state.paVertexShaderConst[j], sizeof(pContext->state.paVertexShaderConst[j]), 0, g_aVMSVGASHADERCONSTFields, NULL);
            AssertRCReturn(rc, rc);
        }
    }

    return VINF_SUCCESS;
}
Exemple #11
0
DECLEXPORT(int32_t) crVBoxServerSaveState(PSSMHANDLE pSSM)
{
    int32_t  rc, i;
    uint32_t ui32;
    GLboolean b;
    unsigned long key;
#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
    unsigned long ctxID=-1, winID=-1;
#endif

    /* We shouldn't be called if there's no clients at all*/
    CRASSERT(cr_server.numClients>0);

    /* @todo it's hack atm */
    /* We want to be called only once to save server state but atm we're being called from svcSaveState
     * for every connected client (e.g. guest opengl application)
     */
    if (!cr_server.bIsInSavingState) /* It's first call */
    {
        cr_server.bIsInSavingState = GL_TRUE;

        /* Store number of clients */
        rc = SSMR3PutU32(pSSM, (uint32_t) cr_server.numClients);
        AssertRCReturn(rc, rc);

        g_hackVBoxServerSaveLoadCallsLeft = cr_server.numClients;
    }

    g_hackVBoxServerSaveLoadCallsLeft--;

    /* Do nothing until we're being called last time */
    if (g_hackVBoxServerSaveLoadCallsLeft>0)
    {
        return VINF_SUCCESS;
    }

    /* Save rendering contexts creation info */
    ui32 = crHashtableNumElements(cr_server.pContextCreateInfoTable);
    rc = SSMR3PutU32(pSSM, (uint32_t) ui32);
    AssertRCReturn(rc, rc);
    crHashtableWalk(cr_server.pContextCreateInfoTable, crVBoxServerSaveCreateInfoCB, pSSM);

#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
    /* Save current win and ctx IDs, as we'd rebind contexts when saving textures */
    if (cr_server.curClient)
    {
        ctxID = cr_server.curClient->currentContextNumber;
        winID = cr_server.curClient->currentWindow;
    }
#endif

    /* Save contexts state tracker data */
    /* @todo For now just some blind data dumps,
     * but I've a feeling those should be saved/restored in a very strict sequence to
     * allow diff_api to work correctly.
     * Should be tested more with multiply guest opengl apps working when saving VM snapshot.
     */
    crHashtableWalk(cr_server.contextTable, crVBoxServerSaveContextStateCB, pSSM);

#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
    /* Restore original win and ctx IDs*/
    if (cr_server.curClient)
    {
        crServerDispatchMakeCurrent(winID, 0, ctxID);
    }
#endif

    /* Save windows creation info */
    ui32 = crHashtableNumElements(cr_server.pWindowCreateInfoTable);
    rc = SSMR3PutU32(pSSM, (uint32_t) ui32);
    AssertRCReturn(rc, rc);
    crHashtableWalk(cr_server.pWindowCreateInfoTable, crVBoxServerSaveCreateInfoCB, pSSM);

    /* Save cr_server.muralTable
     * @todo we don't need it all, just geometry info actually
     */
    ui32 = crHashtableNumElements(cr_server.muralTable);
    /* There should be default mural always */
    CRASSERT(ui32>=1);
    rc = SSMR3PutU32(pSSM, (uint32_t) ui32-1);
    AssertRCReturn(rc, rc);
    crHashtableWalk(cr_server.muralTable, crVBoxServerSaveMuralCB, pSSM);

    /* Save starting free context and window IDs */
    rc = SSMR3PutMem(pSSM, &cr_server.idsPool, sizeof(cr_server.idsPool));
    AssertRCReturn(rc, rc);

    /* Save clients info */
    for (i = 0; i < cr_server.numClients; i++)
    {
        if (cr_server.clients[i] && cr_server.clients[i]->conn)
        {
            CRClient *pClient = cr_server.clients[i];

            rc = SSMR3PutU32(pSSM, pClient->conn->u32ClientID);
            AssertRCReturn(rc, rc);

            rc = SSMR3PutU32(pSSM, pClient->conn->vMajor);
            AssertRCReturn(rc, rc);

            rc = SSMR3PutU32(pSSM, pClient->conn->vMinor);
            AssertRCReturn(rc, rc);

            rc = SSMR3PutMem(pSSM, pClient, sizeof(*pClient));
            AssertRCReturn(rc, rc);

            if (pClient->currentCtx && pClient->currentContextNumber>=0)
            {
                b = crHashtableGetDataKey(cr_server.contextTable, pClient->currentCtx, &key);
                CRASSERT(b);
                rc = SSMR3PutMem(pSSM, &key, sizeof(key));
                AssertRCReturn(rc, rc);
            }

            if (pClient->currentMural && pClient->currentWindow>=0)
            {
                b = crHashtableGetDataKey(cr_server.muralTable, pClient->currentMural, &key);
                CRASSERT(b);
                rc = SSMR3PutMem(pSSM, &key, sizeof(key));
                AssertRCReturn(rc, rc);
            }
        }
    }

    cr_server.bIsInSavingState = GL_FALSE;

    return VINF_SUCCESS;
}