static void crVBoxServerSaveContextStateCB(unsigned long key, void *data1, void *data2) { CRContext *pContext = (CRContext *) data1; PSSMHANDLE pSSM = (PSSMHANDLE) data2; int32_t rc; CRASSERT(pContext && pSSM); /* We could have skipped saving the key and use similar callback to load context states back, * but there's no guarantee we'd traverse hashtable in same order after loading. */ rc = SSMR3PutMem(pSSM, &key, sizeof(key)); CRASSERT(rc == VINF_SUCCESS); #ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE if (cr_server.curClient) { unsigned long id; if (!crHashtableGetDataKey(cr_server.contextTable, pContext, &id)) { crWarning("No client id for server ctx %d", pContext->id); } else { crServerDispatchMakeCurrent(cr_server.curClient->currentWindow, 0, id); } } #endif rc = crStateSaveContext(pContext, pSSM); CRASSERT(rc == VINF_SUCCESS); }
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; }
/* @todo add hashtable walker with result info and intermediate abort */ static void crVBoxServerSaveCreateInfoCB(unsigned long key, void *data1, void *data2) { CRCreateInfo_t *pCreateInfo = (CRCreateInfo_t *) data1; PSSMHANDLE pSSM = (PSSMHANDLE) data2; int32_t rc; CRASSERT(pCreateInfo && pSSM); rc = SSMR3PutMem(pSSM, &key, sizeof(key)); CRASSERT(rc == VINF_SUCCESS); rc = SSMR3PutMem(pSSM, pCreateInfo, sizeof(*pCreateInfo)); CRASSERT(rc == VINF_SUCCESS); if (pCreateInfo->pszDpyName) { rc = SSMR3PutStrZ(pSSM, pCreateInfo->pszDpyName); CRASSERT(rc == VINF_SUCCESS); } }
static void crVBoxServerSaveMuralCB(unsigned long key, void *data1, void *data2) { CRMuralInfo *pMI = (CRMuralInfo*) data1; PSSMHANDLE pSSM = (PSSMHANDLE) data2; int32_t rc; CRASSERT(pMI && pSSM); /* Don't store default mural */ if (!key) return; rc = SSMR3PutMem(pSSM, &key, sizeof(key)); CRASSERT(rc == VINF_SUCCESS); rc = SSMR3PutMem(pSSM, pMI, sizeof(*pMI)); CRASSERT(rc == VINF_SUCCESS); if (pMI->pVisibleRects) { rc = SSMR3PutMem(pSSM, pMI->pVisibleRects, 4*sizeof(GLint)*pMI->cVisibleRects); } }
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; }
/** * Save PHY state. * * @remarks Since PHY is aggregated into E1K it does not currently supports * versioning of its own. * * @returns VBox status code. * @param pSSMHandle The handle to save the state to. * @param pPhy The pointer to this instance. */ int Phy::saveState(PSSMHANDLE pSSMHandle, PPHY pPhy) { SSMR3PutMem(pSSMHandle, pPhy->au16Regs, sizeof(pPhy->au16Regs)); 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; }
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; }