state_snapshot.c revision bf144aab354eaec8ee22b16b1c138f47f38b7244
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync * VBox Context state saving/loading used by VM snapshot
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync * Copyright (C) 2008 Sun Microsystems, Inc.
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync * available from http://www.virtualbox.org. This file is free software;
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync * you can redistribute it and/or modify it under the terms of the GNU
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync * General Public License (GPL) as published by the Free Software
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
2b2d2111baf3a01b7144b5b3ed0b19007bf08a50vboxsync * additional information or have any questions.
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync * We have two ways of saving/loading states.
db4e05173041f696b1362c454bbf7e3a41fbe955vboxsync * First which is being used atm, just pure saving/loading of structures.
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync * The drawback is we have to deal with all the pointers around those structures,
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync * we'd have to update this code if we'd change state tracking.
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync * On the bright side it's fast, though it's not really needed as it's not that often operation.
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync * It could also worth to split those functions into appropriate parts,
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync * similar to the way context creation is being done.
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync * Second way would be to implement full dispatch api table and substitute diff_api during saving/loading.
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync * Then if we implement that api in a similar way to packer/unpacker with a change to store/load
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync * via provided pSSM handle instead of pack buffer,
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync * saving state could be done by simple diffing against empty "dummy" context.
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync * Restoring state in such case would look like unpacking commands from pSSM instead of network buffer.
2b2d2111baf3a01b7144b5b3ed0b19007bf08a50vboxsync * This would be slower (who cares) but most likely will not require any code changes to support in future.
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync * We will reduce amount of saved data as we'd save only changed state parts, but I doubt it'd be that much.
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync * It could be done for the first way as well, but requires tons of bit checks.
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync/*@todo move with the one from state_texture.c to some header*/
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsyncstatic int32_t crStateAllocAndSSMR3GetMem(PSSMHANDLE pSSM, void **pBuffer, size_t cbBuffer)
99ed66b1a390b4f20a1a921c6f8b4d3d2d251adbvboxsyncstatic int32_t crStateSaveTextureObjData(CRTextureObj *pTexture, PSSMHANDLE pSSM)
2b2d2111baf3a01b7144b5b3ed0b19007bf08a50vboxsync /*@todo, check if safe to go till MAX_MIPMAP_LEVELS intead of TextureState->maxLevel*/
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync for (i = 0; i < MAX_MIPMAP_LEVELS; i++) {
2b2d2111baf3a01b7144b5b3ed0b19007bf08a50vboxsync /* Note, this is not a bug.
2b2d2111baf3a01b7144b5b3ed0b19007bf08a50vboxsync * Even with CR_STATE_NO_TEXTURE_IMAGE_STORE defined, it's possible that ptl->img!=NULL.
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync * For ex. we're saving snapshot right after it was loaded
2b2d2111baf3a01b7144b5b3ed0b19007bf08a50vboxsync * and some context hasn't been used by the guest application yet
68e0b366071a6dd88182866e8852ec5ec90a8b66vboxsync * (pContext->texture.bResyncNeeded==GL_TRUE).
return VINF_SUCCESS;
for (i = 0; i < MAX_MIPMAP_LEVELS; i++) {
return VINF_SUCCESS;
return rc;
if (pTexture)
return VINF_SUCCESS;
static int32_t crStateLoadTextureObjPtr(CRTextureObj **pTexture, CRContext *pContext, GLenum target, PSSMHANDLE pSSM)
if (!*pTexture)
return VINF_SUCCESS;
if (texName)
switch (target)
case GL_TEXTURE_1D:
case GL_TEXTURE_2D:
#ifdef CR_OPENGL_VERSION_1_2
case GL_TEXTURE_3D:
#ifdef CR_ARB_texture_cube_map
case GL_TEXTURE_CUBE_MAP_ARB:
#ifdef CR_NV_texture_rectangle
case GL_TEXTURE_RECTANGLE_NV:
return rc;
#ifdef CR_ARB_texture_cube_map
#ifdef CR_NV_texture_rectangle
return rc;
static int32_t crStateLoadTexUnitCurrentTexturePtrs(CRTextureUnit *pTexUnit, CRContext *pContext, PSSMHANDLE pSSM)
#ifdef CR_ARB_texture_cube_map
rc = crStateLoadTextureObjPtr(&pTexUnit->currentTextureCubeMap, pContext, GL_TEXTURE_CUBE_MAP_ARB, pSSM);
#ifdef CR_NV_texture_rectangle
rc = crStateLoadTextureObjPtr(&pTexUnit->currentTextureRect, pContext, GL_TEXTURE_RECTANGLE_NV, pSSM);
return rc;
for (i=0; i<GLEVAL_TOT; ++i)
return VINF_SUCCESS;
for (i=0; i<GLEVAL_TOT; ++i)
rc = SSMR3PutMem(pSSM, pEval[i].coeff, pEval[i].uorder * pEval[i].vorder * gleval_sizes[i] * sizeof(GLfloat));
return VINF_SUCCESS;
for (i=0; i<GLEVAL_TOT; ++i)
if (bReallocMem)
return VINF_SUCCESS;
for (i=0; i<GLEVAL_TOT; ++i)
if (bReallocMem)
return VINF_SUCCESS;
int32_t i;
for (i=0; i<GLEVAL_TOT; ++i)
pDst[GL_MAP1_TEXTURE_COORD_1-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_TEXTURE_COORD_1-GL_MAP1_COLOR_4].coeff;
pDst[GL_MAP1_TEXTURE_COORD_2-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_TEXTURE_COORD_2-GL_MAP1_COLOR_4].coeff;
pDst[GL_MAP1_TEXTURE_COORD_3-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_TEXTURE_COORD_3-GL_MAP1_COLOR_4].coeff;
pDst[GL_MAP1_TEXTURE_COORD_4-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_TEXTURE_COORD_4-GL_MAP1_COLOR_4].coeff;
int32_t i;
for (i=0; i<GLEVAL_TOT; ++i)
pDst[GL_MAP2_TEXTURE_COORD_1-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_TEXTURE_COORD_1-GL_MAP2_COLOR_4].coeff;
pDst[GL_MAP2_TEXTURE_COORD_2-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_TEXTURE_COORD_2-GL_MAP2_COLOR_4].coeff;
pDst[GL_MAP2_TEXTURE_COORD_3-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_TEXTURE_COORD_3-GL_MAP2_COLOR_4].coeff;
pDst[GL_MAP2_TEXTURE_COORD_4-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_TEXTURE_COORD_4-GL_MAP2_COLOR_4].coeff;
/*We could get here even though retainBufferData is false on host side, in case when we're taking snapshot
unsigned long key;
if (*ppProgram)
return VINF_SUCCESS;
crWarning("Saving state with %d display lists, unsupported", crHashtableNumElements(pContext->shared->dlistTable));
for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
for (i = 0 ; i < CR_MAX_PROGRAM_MATRICES ; i++)
#ifdef CR_ARB_texture_cube_map
#ifdef CR_NV_texture_rectangle
if (ui32)
#ifdef CR_ARB_texture_cube_map
#ifdef CR_NV_texture_rectangle
for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i)
rc = SSMR3PutMem(pSSM, pContext->lighting.light, CR_MAX_LIGHTS * sizeof(*pContext->lighting.light));
for ( i = 0 ; i < CR_MAX_ATTRIB_STACK_DEPTH ; i++)
#ifdef CR_ARB_vertex_buffer_object
for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++)
# ifdef CR_NV_vertex_program
for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++)
#ifdef CR_EXT_framebuffer_object
rc = SSMR3PutU32(pSSM, pContext->framebufferobject.framebuffer?pContext->framebufferobject.framebuffer->id:0);
rc = SSMR3PutU32(pSSM, pContext->framebufferobject.renderbuffer?pContext->framebufferobject.renderbuffer->id:0);
return VINF_SUCCESS;
unsigned long key;
if (!pTmpContext)
return VERR_NO_MEMORY;
for ( i = 0 ; i < CR_MAX_ATTRIB_STACK_DEPTH ; i++)
for (j=0; j<GLEVAL_TOT; ++j)
#ifdef CR_ARB_vertex_buffer_object
/*@todo, that should be removed probably as those should hold the offset values, so loading should be fine
#ifdef CR_EXT_compiled_vertex_array
for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
# ifdef CR_NV_vertex_program
for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++)
#ifdef CR_ARB_vertex_buffer_object
for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
# ifdef CR_NV_vertex_program
for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++)
#ifdef CR_ARB_texture_cube_map
#ifdef CR_NV_texture_rectangle
/* Don't have to worry about pContext->transform.current as it'd be set in crStateSetCurrent call */
/*SLC_COPYPTR(transform.currentStack);*/
for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
for (i = 0 ; i < CR_MAX_PROGRAM_MATRICES ; i++)
for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
for (i = 0 ; i < CR_MAX_PROGRAM_MATRICES ; i++)
#ifdef CR_ARB_texture_cube_map
#ifdef CR_NV_texture_rectangle
for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i)
rc = SSMR3GetMem(pSSM, pContext->lighting.light, CR_MAX_LIGHTS * sizeof(*pContext->lighting.light));
for ( i = 0 ; i < CR_MAX_ATTRIB_STACK_DEPTH ; i++)
rc = crStateLoadTexUnitCurrentTexturePtrs(&pContext->attrib.textureStack[i].unit[k], pContext, pSSM);
#ifdef CR_ARB_vertex_buffer_object
if (key==0)
if (key!=0)
#define CRS_GET_BO(name) (((name)==0) ? (pContext->bufferobject.nullBuffer) : crHashtableSearch(pContext->bufferobject.buffers, name))
for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++)
# ifdef CR_NV_vertex_program
for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++)
#ifdef CR_EXT_framebuffer_object
return VINF_SUCCESS;