state_snapshot.c revision 061bebe04c5bfa05ed733d2a1204389c2a0c96a8
/* $Id$ */
/** @file
*/
/*
* Copyright (C) 2008 Sun Microsystems, Inc.
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
* Clara, CA 95054 USA or visit http://www.sun.com if you need
* additional information or have any questions.
*/
#include "state.h"
#include "state/cr_statetypes.h"
#include "state/cr_texture.h"
#include "cr_mem.h"
#include "cr_string.h"
#include <stdio.h>
/* @todo
*
* The drawback is we have to deal with all the pointers around those structures,
* we'd have to update this code if we'd change state tracking.
* On the bright side it's fast, though it's not really needed as it's not that often operation.
* It could also worth to split those functions into appropriate parts,
* similar to the way context creation is being done.
*
* Second way would be to implement full dispatch api table and substitute diff_api during saving/loading.
* via provided pSSM handle instead of pack buffer,
* saving state could be done by simple diffing against empty "dummy" context.
* Restoring state in such case would look like unpacking commands from pSSM instead of network buffer.
* This would be slower (who cares) but most likely will not require any code changes to support in future.
* We will reduce amount of saved data as we'd save only changed state parts, but I doubt it'd be that much.
* It could be done for the first way as well, but requires tons of bit checks.
*/
/*@todo move with the one from state_texture.c to some header*/
#define MAX_MIPMAP_LEVELS 20
{
if (!*pBuffer)
return VERR_NO_MEMORY;
}
{
/*@todo, check if safe to go till MAX_MIPMAP_LEVELS intead of TextureState->maxLevel*/
for (i = 0; i < MAX_MIPMAP_LEVELS; i++) {
{
}
/* Note, this is not a bug.
* Even with CR_STATE_NO_TEXTURE_IMAGE_STORE defined, it's possible that ptl->img!=NULL.
* For ex. we're saving snapshot right after it was loaded
* and some context hasn't been used by the guest application yet
* (pContext->texture.bResyncNeeded==GL_TRUE).
*/
{
char *pImg;
if (!pImg) return VERR_NO_MEMORY;
}
#endif
}
}
return VINF_SUCCESS;
}
{
for (i = 0; i < MAX_MIPMAP_LEVELS; i++) {
{
}
/* Same story as in crStateSaveTextureObjData */
{
}
#endif
//FILLDIRTY(ptl->dirty);
}
}
return VINF_SUCCESS;
}
{
}
{
}
{
/* fixup stack top pointer */
return rc;
}
{
/* Current texture pointer can't be NULL for real texture unit states,
* but it could be NULL for unused attribute stack depths.
*/
if (pTexture)
else
return VINF_SUCCESS;
}
static int32_t crStateLoadTextureObjPtr(CRTextureObj **pTexture, CRContext *pContext, GLenum target, PSSMHANDLE pSSM)
{
/* We're loading attrib stack with unused state */
if (!*pTexture)
return VINF_SUCCESS;
if (texName)
{
}
else
{
switch (target)
{
case GL_TEXTURE_1D:
break;
case GL_TEXTURE_2D:
break;
#ifdef CR_OPENGL_VERSION_1_2
case GL_TEXTURE_3D:
break;
#endif
#ifdef CR_ARB_texture_cube_map
case GL_TEXTURE_CUBE_MAP_ARB:
break;
#endif
#ifdef CR_NV_texture_rectangle
case GL_TEXTURE_RECTANGLE_NV:
break;
#endif
default:
}
}
return rc;
}
{
#ifdef CR_ARB_texture_cube_map
#endif
#ifdef CR_NV_texture_rectangle
#endif
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);
#endif
#ifdef CR_NV_texture_rectangle
rc = crStateLoadTextureObjPtr(&pTexUnit->currentTextureRect, pContext, GL_TEXTURE_RECTANGLE_NV, pSSM);
#endif
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_VERTEX_3-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_VERTEX_3-GL_MAP1_COLOR_4].coeff;
pDst[GL_MAP1_VERTEX_4-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_VERTEX_4-GL_MAP1_COLOR_4].coeff;
pDst[GL_MAP1_INDEX-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_INDEX-GL_MAP1_COLOR_4].coeff;
pDst[GL_MAP1_COLOR_4-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_COLOR_4-GL_MAP1_COLOR_4].coeff;
pDst[GL_MAP1_NORMAL-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_NORMAL-GL_MAP1_COLOR_4].coeff;
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_VERTEX_3-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_VERTEX_3-GL_MAP2_COLOR_4].coeff;
pDst[GL_MAP2_VERTEX_4-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_VERTEX_4-GL_MAP2_COLOR_4].coeff;
pDst[GL_MAP2_INDEX-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_INDEX-GL_MAP2_COLOR_4].coeff;
pDst[GL_MAP2_COLOR_4-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_COLOR_4-GL_MAP2_COLOR_4].coeff;
pDst[GL_MAP2_NORMAL-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_NORMAL-GL_MAP2_COLOR_4].coeff;
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;
*/
}
{
if (pBufferObj->data)
{
/*We could get here even though retainBufferData is false on host side, in case when we're taking snapshot
after state load and before this context was ever made current*/
}
{
if (pBufferObj->pointer)
{
}
}
}
{
{
}
{
{
}
}
}
{
}
{
}
{
unsigned long key;
/* we're loading default vertex or pixel program*/
if (*ppProgram)
{
if (key!=0) return VERR_SSM_UNEXPECTED_DATA;
}
else
{
if (!ppProgram) return VERR_NO_MEMORY;
if (key==0) return VERR_SSM_UNEXPECTED_DATA;
}
{
}
{
if (!ppSymbol) return VERR_NO_MEMORY;
{
}
}
return VINF_SUCCESS;
}
{
if (pStr)
{
}
else
{
}
}
{
if (len!=0)
{
}
return pStr;
}
{
{
}
else
{
if (sLen>0)
{
}
}
}
{
unsigned long key;
return pShader;
}
{
}
{
GLuint i;
{
}
}
{
{
}
if (activeUniforms>0)
{
if (!name)
{
crWarning("crStateSaveGLSLProgramCB: out of memory");
return;
}
}
for (i=0; i<activeUniforms; ++i)
{
uniformsCount += size;
}
if (activeUniforms>0)
{
for (i=0; i<activeUniforms; ++i)
{
if (size>1)
{
if (!pIndexStr)
{
}
}
for (j=0; j<size; ++j)
{
if (size>1)
{
}
else
{
location = i;
}
if (crStateIsIntUniform(type))
{
}
else
{
}
}
}
}
}
{
crWarning("Saving state with %d display lists, unsupported", crHashtableNumElements(pContext->shared->dlistTable));
/* Save transform state */
for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
{
}
for (i = 0 ; i < CR_MAX_PROGRAM_MATRICES ; i++)
{
}
/* Save textures */
#ifdef CR_ARB_texture_cube_map
#endif
#ifdef CR_NV_texture_rectangle
#endif
/* Save shared textures */
/* Restore previous texture bindings via diff_api */
if (ui32)
{
#ifdef CR_ARB_texture_cube_map
#endif
#ifdef CR_NV_texture_rectangle
#endif
}
#endif
/* Save current texture pointers */
for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i)
{
}
/* Save lights */
rc = SSMR3PutMem(pSSM, pContext->lighting.light, CR_MAX_LIGHTS * sizeof(*pContext->lighting.light));
/* Save attrib stack*/
/*@todo could go up to used stack depth here?*/
for ( i = 0 ; i < CR_MAX_ATTRIB_STACK_DEPTH ; i++)
{
{
}
{
}
{
}
{
}
{
}
{
}
}
/* Save evaluator coeffs */
#ifdef CR_ARB_vertex_buffer_object
/* Save buffer objects */
/* Save default one*/
/* Save all the rest */
/* Restore binding */
/* Save pointers */
/* Save bound array buffers*/ /*@todo vertexArrayStack*/
for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++)
{
}
# ifdef CR_NV_vertex_program
for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++)
{
}
# endif
#endif /*CR_ARB_vertex_buffer_object*/
/* Save defauls programs */
/* Save all the rest */
/* Save Pointers */
/* This one is unused it seems*/
#ifdef CR_EXT_framebuffer_object
/* Save FBOs */
rc = SSMR3PutU32(pSSM, pContext->framebufferobject.drawFB?pContext->framebufferobject.drawFB->id:0);
rc = SSMR3PutU32(pSSM, pContext->framebufferobject.readFB?pContext->framebufferobject.readFB->id:0);
rc = SSMR3PutU32(pSSM, pContext->framebufferobject.renderbuffer?pContext->framebufferobject.renderbuffer->id:0);
#endif
#ifdef CR_OPENGL_VERSION_2_0
/* Save GLSL related info */
#endif
return VINF_SUCCESS;
}
{
unsigned long key;
/* This one is rather big for stack allocation and causes macs to crash */
if (!pTmpContext)
return VERR_NO_MEMORY;
/* We're supposed to be loading into an empty context, so those pointers should be NULL */
for ( i = 0 ; i < CR_MAX_ATTRIB_STACK_DEPTH ; i++)
{
for (j=0; j<GLEVAL_TOT; ++j)
{
}
}
#ifdef CR_ARB_vertex_buffer_object
#endif
/*@todo, that should be removed probably as those should hold the offset values, so loading should be fine
but better check*/
#if 0
#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++)
{
}
# endif
#endif
#endif
#ifdef CR_ARB_vertex_buffer_object
/*That just sets those pointers to NULL*/
for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
{
}
# ifdef CR_NV_vertex_program
for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++)
{
}
# endif
#endif /*CR_ARB_vertex_buffer_object*/
/*@todo CR_NV_vertex_program*/
/*This one could be tricky if we're loading snapshot on host with different GPU*/
#endif
/* Texture pointers */
for (i=0; i<6; ++i)
{
#ifdef CR_ARB_texture_cube_map
#endif
#ifdef CR_NV_texture_rectangle
#endif
}
/* Load transform state */
/* 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++)
{
}
#ifdef CR_EXT_framebuffer_object
#endif
#ifdef CR_OPENGL_VERSION_2_0
#endif
/* Have to preserve original context id */
/* Copy ordinary state to real context */
pTmpContext = NULL;
/* Now deal with pointers */
/* Load transform state */
for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
{
}
for (i = 0 ; i < CR_MAX_PROGRAM_MATRICES ; i++)
{
}
/* Load Textures */
#ifdef CR_ARB_texture_cube_map
#endif
#ifdef CR_NV_texture_rectangle
#endif
/* Load shared textures */
{
if (!pTexture) return VERR_NO_MEMORY;
//DIRTY(pTexture->dirty, pContext->neg_bitid);
//DIRTY(pTexture->imageBit, pContext->neg_bitid);
/*allocate actual memory*/
for (i=0; i<6; ++i) {
}
}
/* Load current texture pointers */
for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i)
{
}
//FILLDIRTY(GetCurrentBits()->texture.dirty);
/* Mark textures for resending to GPU */
/* Load lights */
rc = SSMR3GetMem(pSSM, pContext->lighting.light, CR_MAX_LIGHTS * sizeof(*pContext->lighting.light));
/* Load attrib stack*/
for ( i = 0 ; i < CR_MAX_ATTRIB_STACK_DEPTH ; i++)
{
{
}
{
}
{
}
{
rc = crStateLoadTexUnitCurrentTexturePtrs(&pContext->attrib.textureStack[i].unit[k], pContext, pSSM);
}
{
}
{
}
}
/* Load evaluator coeffs */
/* Load buffer objects */
#ifdef CR_ARB_vertex_buffer_object
{
/* default one should be already allocated */
if (key==0)
{
if (!pBufferObj) return VERR_SSM_UNEXPECTED_DATA;
}
else
{
if (!pBufferObj) return VERR_NO_MEMORY;
}
if (pBufferObj->data)
{
//DIRTY(pBufferObj->dirty, pContext->neg_bitid);
//pBufferObj->dirtyStart = 0;
//pBufferObj->dirtyLength = pBufferObj->size;
}
{
if (pBufferObj->data)
{
}
}
if (key!=0)
}
//FILLDIRTY(GetCurrentBits()->bufferobject.dirty);
/* Load pointers */
#define CRS_GET_BO(name) (((name)==0) ? (pContext->bufferobject.nullBuffer) : crHashtableSearch(pContext->bufferobject.buffers, name))
/* Load bound array buffers*/
for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++)
{
}
# ifdef CR_NV_vertex_program
for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++)
{
}
# endif
#endif
/* Load defauls programs */
//FILLDIRTY(pContext->program.defaultVertexProgram->dirtyProgram);
//FILLDIRTY(pContext->program.defaultFragmentProgram->dirtyProgram);
/* Load all the rest */
{
//DIRTY(pProgram->dirtyProgram, pContext->neg_bitid);
}
//FILLDIRTY(GetCurrentBits()->program.dirty);
/* Load Pointers */
/* Mark programs for resending to GPU */
#ifdef CR_EXT_framebuffer_object
/* Load FBOs */
{
if (!pFBO) return VERR_NO_MEMORY;
}
{
if (!pRBO) return VERR_NO_MEMORY;
}
#endif
#ifdef CR_OPENGL_VERSION_2_0
/* Load GLSL related info */
{
if (!pShader) return VERR_SSM_UNEXPECTED_DATA;
}
{
if (!pProgram) return VERR_NO_MEMORY;
for (k=0; k<numShaders; ++k)
{
crHashtableAdd(pProgram->currentState.attachedShaders, key, crHashtableSearch(pContext->glsl.shaders, key));
}
{
for (k=0; k<numShaders; ++k)
{
if (!pShader) return VERR_SSM_UNEXPECTED_DATA;
}
}
pProgram->currentState.pAttribs = (CRGLSLAttrib*) crAlloc(pProgram->currentState.cAttribs*sizeof(CRGLSLAttrib));
{
rc = SSMR3GetMem(pSSM, &pProgram->currentState.pAttribs[k].index, sizeof(pProgram->currentState.pAttribs[k].index));
}
pProgram->activeState.pAttribs = (CRGLSLAttrib*) crAlloc(pProgram->activeState.cAttribs*sizeof(CRGLSLAttrib));
{
rc = SSMR3GetMem(pSSM, &pProgram->activeState.pAttribs[k].index, sizeof(pProgram->activeState.pAttribs[k].index));
}
{
if (!pProgram) return VERR_NO_MEMORY;
{
{
}
}
}
/*Mark for resending to GPU*/
#endif
return VINF_SUCCESS;
}