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; }
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; }