VirtualBox

source: vbox/trunk/src/VBox/GuestHost/OpenGL/state_tracker/state_snapshot.c@ 76541

Last change on this file since 76541 was 73097, checked in by vboxsync, 6 years ago

*: Made RT_UOFFSETOF, RT_OFFSETOF, RT_UOFFSETOF_ADD and RT_OFFSETOF_ADD work like builtin_offsetof() and require compile time resolvable requests, adding RT_UOFFSETOF_DYN for the dynamic questions that can only be answered at runtime.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id Revision
File size: 93.2 KB
Line 
1/* $Id: state_snapshot.c 73097 2018-07-12 21:06:33Z vboxsync $ */
2/** @file
3 * VBox Context state saving/loading used by VM snapshot
4 */
5
6/*
7 * Copyright (C) 2008-2017 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#include "state.h"
19#include "state_internals.h"
20#include "state/cr_statetypes.h"
21#include "state/cr_texture.h"
22#include "cr_mem.h"
23#include "cr_string.h"
24#include "cr_pixeldata.h"
25#include <stdio.h>
26
27#include <iprt/assert.h>
28#include <iprt/types.h>
29#include <iprt/err.h>
30#include <VBox/err.h>
31#include <VBox/log.h>
32
33/** @todo
34 * We have two ways of saving/loading states.
35 *
36 * First which is being used atm, just pure saving/loading of structures.
37 * The drawback is we have to deal with all the pointers around those structures,
38 * we'd have to update this code if we'd change state tracking.
39 * On the bright side it's fast, though it's not really needed as it's not that often operation.
40 * It could also worth to split those functions into appropriate parts,
41 * similar to the way context creation is being done.
42 *
43 * Second way would be to implement full dispatch api table and substitute diff_api during saving/loading.
44 * Then if we implement that api in a similar way to packer/unpacker with a change to store/load
45 * via provided pSSM handle instead of pack buffer,
46 * saving state could be done by simple diffing against empty "dummy" context.
47 * Restoring state in such case would look like unpacking commands from pSSM instead of network buffer.
48 * This would be slower (who cares) but most likely will not require any code changes to support in future.
49 * We will reduce amount of saved data as we'd save only changed state parts, but I doubt it'd be that much.
50 * It could be done for the first way as well, but requires tons of bit checks.
51 */
52
53static int32_t crStateAllocAndSSMR3GetMem(PSSMHANDLE pSSM, void **pBuffer, size_t cbBuffer)
54{
55 CRASSERT(pSSM && pBuffer && cbBuffer>0);
56
57 *pBuffer = crAlloc((unsigned int /* this case is just so stupid */)cbBuffer);
58 if (!*pBuffer)
59 return VERR_NO_MEMORY;
60
61 return SSMR3GetMem(pSSM, *pBuffer, cbBuffer);
62}
63
64#define SHCROGL_GET_STRUCT_PART(_pPtr, _type, _from, _to) do { \
65 rc = SSMR3GetMem(pSSM, &(_pPtr)->_from, RT_UOFFSETOF(_type, _to) - RT_UOFFSETOF(_type, _from)); \
66 AssertRCReturn(rc, rc); \
67 } while (0)
68
69#define SHCROGL_GET_STRUCT_TAIL(_pPtr, _type, _from) do { \
70 rc = SSMR3GetMem(pSSM, &(_pPtr)->_from, sizeof (_type) - RT_UOFFSETOF(_type, _from)); \
71 AssertRCReturn(rc, rc); \
72 } while (0)
73
74#define SHCROGL_GET_STRUCT_HEAD(_pPtr, _type, _to) do { \
75 rc = SSMR3GetMem(pSSM, (_pPtr), RT_UOFFSETOF(_type, _to)); \
76 AssertRCReturn(rc, rc); \
77 } while (0)
78
79#define SHCROGL_CUT_FIELD_ALIGNMENT_SIZE(_type, _prevField, _field) (RT_UOFFSETOF(_type, _field) - RT_UOFFSETOF(_type, _prevField) - RT_SIZEOFMEMB(_type, _prevField))
80#define SHCROGL_CUT_FIELD_ALIGNMENT(_type, _prevField, _field) do { \
81 const int32_t cbAlignment = SHCROGL_CUT_FIELD_ALIGNMENT_SIZE(_type, _prevField, _field) ; \
82 /*AssertCompile(SHCROGL_CUT_FIELD_ALIGNMENT_SIZE(_type, _prevField, _field) >= 0 && SHCROGL_CUT_FIELD_ALIGNMENT_SIZE(_type, _prevField, _field) < sizeof (void*));*/ \
83 if (cbAlignment) { \
84 rc = SSMR3Skip(pSSM, cbAlignment); \
85 } \
86 } while (0)
87
88#define SHCROGL_ROUNDBOUND(_v, _b) (((_v) + ((_b) - 1)) & ~((_b) - 1))
89#define SHCROGL_ALIGNTAILSIZE(_v, _b) (SHCROGL_ROUNDBOUND((_v),(_b)) - (_v))
90#define SHCROGL_CUT_FOR_OLD_TYPE_TO_ENSURE_ALIGNMENT_SIZE(_type, _field, _oldFieldType, _nextFieldAllignment) (SHCROGL_ALIGNTAILSIZE(((RT_UOFFSETOF(_type, _field) + sizeof (_oldFieldType))), (_nextFieldAllignment)))
91#define SHCROGL_CUT_FOR_OLD_TYPE_TO_ENSURE_ALIGNMENT(_type, _field, _oldFieldType, _nextFieldAllignment) do { \
92 const int32_t cbAlignment = SHCROGL_CUT_FOR_OLD_TYPE_TO_ENSURE_ALIGNMENT_SIZE(_type, _field, _oldFieldType, _nextFieldAllignment); \
93 /*AssertCompile(SHCROGL_CUT_TAIL_ALIGNMENT_SIZE(_type, _lastField) >= 0 && SHCROGL_CUT_TAIL_ALIGNMENT_SIZE(_type, _lastField) < sizeof (void*));*/ \
94 if (cbAlignment) { \
95 rc = SSMR3Skip(pSSM, cbAlignment); \
96 } \
97 } while (0)
98
99
100#define SHCROGL_CUT_TAIL_ALIGNMENT_SIZE(_type, _lastField) (sizeof (_type) - RT_UOFFSETOF(_type, _lastField) - RT_SIZEOFMEMB(_type, _lastField))
101#define SHCROGL_CUT_TAIL_ALIGNMENT(_type, _lastField) do { \
102 const int32_t cbAlignment = SHCROGL_CUT_TAIL_ALIGNMENT_SIZE(_type, _lastField); \
103 /*AssertCompile(SHCROGL_CUT_TAIL_ALIGNMENT_SIZE(_type, _lastField) >= 0 && SHCROGL_CUT_TAIL_ALIGNMENT_SIZE(_type, _lastField) < sizeof (void*));*/ \
104 if (cbAlignment) { \
105 rc = SSMR3Skip(pSSM, cbAlignment); \
106 } \
107 } while (0)
108
109static int32_t crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(CRTextureObj *pTexture, PSSMHANDLE pSSM)
110{
111 int32_t rc;
112 uint32_t cbObj = RT_UOFFSETOF(CRTextureObj, ctxUsage);
113 cbObj = ((cbObj + sizeof (void*) - 1) & ~(sizeof (void*) - 1));
114 rc = SSMR3GetMem(pSSM, pTexture, cbObj);
115 AssertRCReturn(rc, rc);
116 /* just make all bits are used so that we fall back to the pre-ctxUsage behavior,
117 * i.e. all shared resources will be destructed on last shared context termination */
118 FILLDIRTY(pTexture->ctxUsage);
119 return rc;
120}
121
122static int32_t crStateLoadTextureUnit_v_BEFORE_CTXUSAGE_BITS(CRTextureUnit *t, PSSMHANDLE pSSM)
123{
124 int32_t rc;
125 SHCROGL_GET_STRUCT_HEAD(t, CRTextureUnit, Saved1D);
126 rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->Saved1D, pSSM);
127 AssertRCReturn(rc, rc);
128 SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureUnit, Saved1D, Saved2D);
129 rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->Saved2D, pSSM);
130 AssertRCReturn(rc, rc);
131 SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureUnit, Saved2D, Saved3D);
132 rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->Saved3D, pSSM);
133 AssertRCReturn(rc, rc);
134#ifdef CR_ARB_texture_cube_map
135 SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureUnit, Saved3D, SavedCubeMap);
136 rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->SavedCubeMap, pSSM);
137 AssertRCReturn(rc, rc);
138# define SHCROGL_INTERNAL_LAST_FIELD SavedCubeMap
139#else
140# define SHCROGL_INTERNAL_LAST_FIELD Saved3D
141#endif
142#ifdef CR_NV_texture_rectangle
143 SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureUnit, SHCROGL_INTERNAL_LAST_FIELD, SavedRect);
144 rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->SavedRect, pSSM);
145 AssertRCReturn(rc, rc);
146# undef SHCROGL_INTERNAL_LAST_FIELD
147# define SHCROGL_INTERNAL_LAST_FIELD SavedRect
148#endif
149 SHCROGL_CUT_TAIL_ALIGNMENT(CRTextureUnit, SHCROGL_INTERNAL_LAST_FIELD);
150#undef SHCROGL_INTERNAL_LAST_FIELD
151 return rc;
152}
153
154static int crStateLoadStencilPoint_v_37(CRPointState *pPoint, PSSMHANDLE pSSM)
155{
156 int rc = VINF_SUCCESS;
157 SHCROGL_GET_STRUCT_HEAD(pPoint, CRPointState, spriteCoordOrigin);
158 pPoint->spriteCoordOrigin = (GLfloat)GL_UPPER_LEFT;
159 return rc;
160}
161
162static int32_t crStateLoadStencilState_v_33(CRStencilState *s, PSSMHANDLE pSSM)
163{
164 CRStencilState_v_33 stencilV33;
165 int32_t rc = SSMR3GetMem(pSSM, &stencilV33, sizeof (stencilV33));
166 AssertRCReturn(rc, rc);
167 s->stencilTest = stencilV33.stencilTest;
168 s->stencilTwoSideEXT = GL_FALSE;
169 s->activeStencilFace = GL_FRONT;
170 s->clearValue = stencilV33.clearValue;
171 s->writeMask = stencilV33.writeMask;
172 s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func = stencilV33.func;
173 s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask = stencilV33.mask;
174 s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref = stencilV33.ref;
175 s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail = stencilV33.fail;
176 s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail = stencilV33.passDepthFail;
177 s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass = stencilV33.passDepthPass;
178 s->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK] = s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT];
179 crStateStencilBufferInit(&s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK]);
180 return VINF_SUCCESS;
181}
182
183static int32_t crStateLoadTextureState_v_BEFORE_CTXUSAGE_BITS(CRTextureState *t, PSSMHANDLE pSSM)
184{
185 GLint i;
186 int32_t rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->base1D, pSSM);
187 AssertRCReturn(rc, rc);
188 SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, base1D, base2D);
189 rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->base2D, pSSM);
190 AssertRCReturn(rc, rc);
191 rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->base3D, pSSM);
192 SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, base2D, base3D);
193 AssertRCReturn(rc, rc);
194#ifdef CR_ARB_texture_cube_map
195 SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, base3D, baseCubeMap);
196 rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->baseCubeMap, pSSM);
197 AssertRCReturn(rc, rc);
198# define SHCROGL_INTERNAL_LAST_FIELD baseCubeMap
199#else
200# define SHCROGL_INTERNAL_LAST_FIELD base3D
201#endif
202#ifdef CR_NV_texture_rectangle
203 SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, SHCROGL_INTERNAL_LAST_FIELD, baseRect);
204 rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->baseRect, pSSM);
205 AssertRCReturn(rc, rc);
206# undef SHCROGL_INTERNAL_LAST_FIELD
207# define SHCROGL_INTERNAL_LAST_FIELD baseRect
208#endif
209 SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, SHCROGL_INTERNAL_LAST_FIELD, proxy1D);
210 rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->proxy1D, pSSM);
211 AssertRCReturn(rc, rc);
212#undef SHCROGL_INTERNAL_LAST_FIELD
213 SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, proxy1D, proxy2D);
214 rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->proxy2D, pSSM);
215 AssertRCReturn(rc, rc);
216 SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, proxy2D, proxy3D);
217 rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->proxy3D, pSSM);
218 AssertRCReturn(rc, rc);
219#ifdef CR_ARB_texture_cube_map
220 SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, proxy3D, proxyCubeMap);
221 rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->proxyCubeMap, pSSM);
222 AssertRCReturn(rc, rc);
223# define SHCROGL_INTERNAL_LAST_FIELD proxyCubeMap
224#else
225# define SHCROGL_INTERNAL_LAST_FIELD proxy3D
226#endif
227#ifdef CR_NV_texture_rectangle
228 SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, SHCROGL_INTERNAL_LAST_FIELD, proxyRect);
229 rc = crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(&t->proxyRect, pSSM);
230 AssertRCReturn(rc, rc);
231# undef SHCROGL_INTERNAL_LAST_FIELD
232# define SHCROGL_INTERNAL_LAST_FIELD proxyRect
233#endif
234 SHCROGL_CUT_FIELD_ALIGNMENT(CRTextureState, SHCROGL_INTERNAL_LAST_FIELD, curTextureUnit);
235# undef SHCROGL_INTERNAL_LAST_FIELD
236 SHCROGL_GET_STRUCT_PART(t, CRTextureState, curTextureUnit, unit);
237
238 for (i = 0; i < CR_MAX_TEXTURE_UNITS; ++i)
239 {
240 rc = crStateLoadTextureUnit_v_BEFORE_CTXUSAGE_BITS(&t->unit[i], pSSM);
241 AssertRCReturn(rc, rc);
242 }
243
244 SHCROGL_CUT_TAIL_ALIGNMENT(CRTextureState, unit);
245
246 return VINF_SUCCESS;
247}
248
249static int32_t crStateStencilBufferStack_v_33(CRStencilBufferStack *s, PSSMHANDLE pSSM)
250{
251 CRStencilBufferStack_v_33 stackV33;
252 int32_t rc = SSMR3GetMem(pSSM, &stackV33, sizeof(stackV33));
253 AssertLogRelReturn(rc, rc);
254
255 s->stencilTest = stackV33.stencilTest;
256 s->stencilTwoSideEXT = GL_FALSE;
257 s->activeStencilFace = GL_FRONT;
258 s->clearValue = stackV33.clearValue;
259 s->writeMask = stackV33.writeMask;
260 s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].func = stackV33.func;
261 s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].mask = stackV33.mask;
262 s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].ref = stackV33.ref;
263 s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].fail = stackV33.fail;
264 s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthFail = stackV33.passDepthFail;
265 s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT].passDepthPass = stackV33.passDepthPass;
266 s->buffers[CRSTATE_STENCIL_BUFFER_ID_BACK] = s->buffers[CRSTATE_STENCIL_BUFFER_ID_FRONT];
267
268 s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].func = GL_ALWAYS;
269 s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].mask = 0xFFFFFFFF;
270 s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].ref = 0;
271 s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].fail = GL_KEEP;
272 s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthFail = GL_KEEP;
273 s->buffers[CRSTATE_STENCIL_BUFFER_ID_TWO_SIDE_BACK].passDepthPass = GL_KEEP;
274
275 return VINF_SUCCESS;
276}
277
278static int32_t crStateLoadAttribState_v_33(CRAttribState *t, PSSMHANDLE pSSM)
279{
280 int32_t i, rc;
281 SHCROGL_GET_STRUCT_HEAD(t, CRAttribState, stencilBufferStack);
282 for (i = 0; i < CR_MAX_ATTRIB_STACK_DEPTH; ++i)
283 {
284 rc = crStateStencilBufferStack_v_33(&t->stencilBufferStack[i], pSSM);
285 AssertRCReturn(rc, rc);
286 }
287 SHCROGL_GET_STRUCT_TAIL(t, CRAttribState, textureStackDepth);
288 return rc;
289}
290
291static int32_t crStateLoadTextureStack_v_BEFORE_CTXUSAGE_BITS(CRTextureStack *t, PSSMHANDLE pSSM)
292{
293 int32_t i, rc;
294 SHCROGL_GET_STRUCT_HEAD(t, CRTextureStack, unit);
295 for (i = 0; i < CR_MAX_TEXTURE_UNITS; ++i)
296 {
297 rc = crStateLoadTextureUnit_v_BEFORE_CTXUSAGE_BITS(&t->unit[i], pSSM);
298 AssertRCReturn(rc, rc);
299 }
300 SHCROGL_CUT_TAIL_ALIGNMENT(CRTextureStack, unit);
301 return rc;
302}
303
304static int32_t crStateLoadAttribState_v_BEFORE_CTXUSAGE_BITS(CRAttribState *t, PSSMHANDLE pSSM)
305{
306 int32_t i, rc;
307
308 SHCROGL_GET_STRUCT_HEAD(t, CRAttribState, stencilBufferStack);
309 for (i = 0; i < CR_MAX_ATTRIB_STACK_DEPTH; ++i)
310 {
311 rc = crStateStencilBufferStack_v_33(&t->stencilBufferStack[i], pSSM);
312 AssertRCReturn(rc, rc);
313 }
314 SHCROGL_GET_STRUCT_PART(t, CRAttribState, textureStackDepth, textureStack);
315 for (i = 0; i < CR_MAX_ATTRIB_STACK_DEPTH; ++i)
316 {
317 rc = crStateLoadTextureStack_v_BEFORE_CTXUSAGE_BITS(&t->textureStack[i], pSSM);
318 AssertRCReturn(rc, rc);
319 }
320 SHCROGL_GET_STRUCT_TAIL(t, CRAttribState, transformStackDepth);
321 return rc;
322}
323
324
325static int32_t crStateLoadTextureObj(CRTextureObj *pTexture, PSSMHANDLE pSSM, uint32_t u32Version)
326{
327 int32_t rc;
328 if (u32Version == SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS)
329 return crStateLoadTextureObj_v_BEFORE_CTXUSAGE_BITS(pTexture, pSSM);
330 rc = SSMR3GetMem(pSSM, pTexture, sizeof (*pTexture));
331 AssertRCReturn(rc, rc);
332 return rc;
333}
334
335static int32_t crStateLoadBufferObject(CRBufferObject *pBufferObj, PSSMHANDLE pSSM, uint32_t u32Version)
336{
337 int32_t rc;
338 if (u32Version == SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS)
339 {
340 uint32_t cbObj = RT_UOFFSETOF(CRBufferObject, ctxUsage);
341 cbObj = ((cbObj + sizeof (void*) - 1) & ~(sizeof (void*) - 1));
342 rc = SSMR3GetMem(pSSM, pBufferObj, cbObj);
343 AssertRCReturn(rc, rc);
344 /* just make all bits are used so that we fall back to the pre-ctxUsage behavior,
345 * i.e. all shared resources will be destructed on last shared context termination */
346 FILLDIRTY(pBufferObj->ctxUsage);
347 }
348 else
349 {
350 rc = SSMR3GetMem(pSSM, pBufferObj, sizeof(*pBufferObj));
351 AssertRCReturn(rc, rc);
352 }
353 return rc;
354}
355
356static int32_t crStateLoadFramebufferObject(CRFramebufferObject *pFBO, PSSMHANDLE pSSM, uint32_t u32Version)
357{
358 int32_t rc;
359 if (u32Version == SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS)
360 {
361 uint32_t cbObj = RT_UOFFSETOF(CRFramebufferObject, ctxUsage);
362 cbObj = ((cbObj + sizeof (void*) - 1) & ~(sizeof (void*) - 1));
363 rc = SSMR3GetMem(pSSM, pFBO, cbObj);
364 AssertRCReturn(rc, rc);
365 /* just make all bits are used so that we fall back to the pre-ctxUsage behavior,
366 * i.e. all shared resources will be destructed on last shared context termination */
367 FILLDIRTY(pFBO->ctxUsage);
368 }
369 else
370 {
371 rc = SSMR3GetMem(pSSM, pFBO, sizeof(*pFBO));
372 AssertRCReturn(rc, rc);
373 }
374 return rc;
375}
376
377static int32_t crStateLoadRenderbufferObject(CRRenderbufferObject *pRBO, PSSMHANDLE pSSM, uint32_t u32Version)
378{
379 int32_t rc;
380 if (u32Version == SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS)
381 {
382 uint32_t cbObj = RT_UOFFSETOF(CRRenderbufferObject, ctxUsage);
383 cbObj = ((cbObj + sizeof (void*) - 1) & ~(sizeof (void*) - 1));
384 rc = SSMR3GetMem(pSSM, pRBO, cbObj);
385 AssertRCReturn(rc, rc);
386 /* just make all bits are used so that we fall back to the pre-ctxUsage behavior,
387 * i.e. all shared resources will be destructed on last shared context termination */
388 FILLDIRTY(pRBO->ctxUsage);
389 }
390 else
391 {
392 rc = SSMR3GetMem(pSSM, pRBO, sizeof(*pRBO));
393 AssertRCReturn(rc, rc);
394 }
395 return rc;
396}
397
398static int32_t crStateSaveTextureObjData(CRTextureObj *pTexture, PSSMHANDLE pSSM)
399{
400 int32_t rc, face, i;
401 GLint bound = 0;
402
403 CRASSERT(pTexture && pSSM);
404
405 crDebug("crStateSaveTextureObjData %u. START", pTexture->id);
406
407 for (face = 0; face < 6; face++) {
408 CRASSERT(pTexture->level[face]);
409
410 for (i = 0; i < CR_MAX_MIPMAP_LEVELS; i++) {
411 CRTextureLevel *ptl = &(pTexture->level[face][i]);
412 rc = SSMR3PutMem(pSSM, ptl, sizeof(*ptl));
413 AssertRCReturn(rc, rc);
414 if (ptl->img)
415 {
416 CRASSERT(ptl->bytes);
417 rc = SSMR3PutMem(pSSM, ptl->img, ptl->bytes);
418 AssertRCReturn(rc, rc);
419 }
420#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
421 /* Note, this is not a bug.
422 * Even with CR_STATE_NO_TEXTURE_IMAGE_STORE defined, it's possible that ptl->img!=NULL.
423 * For ex. we're saving snapshot right after it was loaded
424 * and some context hasn't been used by the guest application yet
425 * (pContext->shared->bTexResyncNeeded==GL_TRUE).
426 */
427 else if (ptl->bytes)
428 {
429 char *pImg;
430 GLenum target;
431
432 if (!bound)
433 {
434 GLenum getEnum;
435 diff_api.BindTexture(pTexture->target, pTexture->hwid);
436 bound = 1;
437
438 /* osx nvidia drivers seem to have a bug that 1x1 TEXTURE_2D texture becmes inaccessible for some reason
439 * saw that for 1x1 dummy textures generated by wine
440 * to avoid crashes we skip texture data save if that is the case */
441 switch (pTexture->target)
442 {
443 case GL_TEXTURE_1D:
444 getEnum = GL_TEXTURE_BINDING_1D;
445 break;
446 case GL_TEXTURE_2D:
447 getEnum = GL_TEXTURE_BINDING_2D;
448 break;
449 case GL_TEXTURE_3D:
450 getEnum = GL_TEXTURE_BINDING_3D;
451 break;
452 case GL_TEXTURE_RECTANGLE_ARB:
453 getEnum = GL_TEXTURE_BINDING_RECTANGLE_ARB;
454 break;
455 case GL_TEXTURE_CUBE_MAP_ARB:
456 getEnum = GL_TEXTURE_BINDING_CUBE_MAP_ARB;
457 break;
458 default:
459 crWarning("unknown texture target: 0x%x", pTexture->target);
460 getEnum = 0;
461 break;
462 }
463
464 if (getEnum)
465 {
466 GLint curTex;
467 diff_api.GetIntegerv(getEnum, &curTex);
468 if ((GLuint)curTex != pTexture->hwid)
469 {
470 crWarning("texture not bound properly: expected %d, but was %d. Texture state data: target(0x%x), id(%d), w(%d), h(%d)",
471 pTexture->hwid, curTex,
472 pTexture->target,
473 pTexture->id,
474 ptl->width,
475 ptl->height);
476 bound = -1;
477 }
478 }
479
480 }
481
482 if (pTexture->target!=GL_TEXTURE_CUBE_MAP_ARB)
483 {
484 target = pTexture->target;
485 }
486 else
487 {
488 target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
489 }
490
491#ifdef DEBUG
492 pImg = crAlloc(ptl->bytes+4);
493#else
494 pImg = crAlloc(ptl->bytes);
495#endif
496 if (!pImg) return VERR_NO_MEMORY;
497
498#ifdef DEBUG
499 *(int*)((char*)pImg+ptl->bytes) = 0xDEADDEAD;
500#endif
501 if (bound > 0)
502 {
503#ifdef DEBUG
504 {
505 GLint w,h=0;
506 crDebug("get image: compressed %i, face %i, level %i, width %i, height %i, bytes %i",
507 ptl->compressed, face, i, ptl->width, ptl->height, ptl->bytes);
508 diff_api.GetTexLevelParameteriv(target, i, GL_TEXTURE_WIDTH, &w);
509 diff_api.GetTexLevelParameteriv(target, i, GL_TEXTURE_HEIGHT, &h);
510 if (w!=ptl->width || h!=ptl->height)
511 {
512 crWarning("!!!tex size mismatch %i, %i!!!", w, h);
513 }
514 }
515#endif
516
517 /** @todo ugly workaround for crashes inside ati driver,
518 * they overwrite their own allocated memory in cases where texlevel >=4
519 and width or height <=2.
520 */
521 if (i<4 || (ptl->width>2 && ptl->height>2))
522 {
523 if (!ptl->compressed)
524 {
525 diff_api.GetTexImage(target, i, ptl->format, ptl->type, pImg);
526 }
527 else
528 {
529 diff_api.GetCompressedTexImageARB(target, i, pImg);
530 }
531 }
532 }
533 else
534 {
535 crMemset(pImg, 0, ptl->bytes);
536 }
537
538#ifdef DEBUG
539 if (*(int*)((char*)pImg+ptl->bytes) != 0xDEADDEAD)
540 {
541 crWarning("Texture is bigger than expected!!!");
542 }
543#endif
544
545 rc = SSMR3PutMem(pSSM, pImg, ptl->bytes);
546 crFree(pImg);
547 AssertRCReturn(rc, rc);
548 }
549#endif
550 }
551 }
552
553 crDebug("crStateSaveTextureObjData %u. END", pTexture->id);
554
555 return VINF_SUCCESS;
556}
557
558static int32_t crStateLoadTextureObjData(CRTextureObj *pTexture, PSSMHANDLE pSSM)
559{
560 int32_t rc, face, i;
561
562 CRASSERT(pTexture && pSSM);
563
564 for (face = 0; face < 6; face++) {
565 CRASSERT(pTexture->level[face]);
566
567 for (i = 0; i < CR_MAX_MIPMAP_LEVELS; i++) {
568 CRTextureLevel *ptl = &(pTexture->level[face][i]);
569 CRASSERT(!ptl->img);
570
571 rc = SSMR3GetMem(pSSM, ptl, sizeof(*ptl));
572 AssertRCReturn(rc, rc);
573 if (ptl->img)
574 {
575 CRASSERT(ptl->bytes);
576
577 ptl->img = crAlloc(ptl->bytes);
578 if (!ptl->img) return VERR_NO_MEMORY;
579
580 rc = SSMR3GetMem(pSSM, ptl->img, ptl->bytes);
581 AssertRCReturn(rc, rc);
582 }
583#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
584 /* Same story as in crStateSaveTextureObjData */
585 else if (ptl->bytes)
586 {
587 ptl->img = crAlloc(ptl->bytes);
588 if (!ptl->img) return VERR_NO_MEMORY;
589
590 rc = SSMR3GetMem(pSSM, ptl->img, ptl->bytes);
591 AssertRCReturn(rc, rc);
592 }
593#endif
594 crStateTextureInitTextureFormat(ptl, ptl->internalFormat);
595 }
596 }
597
598 return VINF_SUCCESS;
599}
600
601static void crStateSaveSharedTextureCB(unsigned long key, void *data1, void *data2)
602{
603 CRTextureObj *pTexture = (CRTextureObj *) data1;
604 PSSMHANDLE pSSM = (PSSMHANDLE) data2;
605 int32_t rc;
606
607 CRASSERT(pTexture && pSSM);
608
609 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
610 CRASSERT(rc == VINF_SUCCESS);
611 rc = SSMR3PutMem(pSSM, pTexture, sizeof(*pTexture));
612 CRASSERT(rc == VINF_SUCCESS);
613 rc = crStateSaveTextureObjData(pTexture, pSSM);
614 CRASSERT(rc == VINF_SUCCESS);
615}
616
617static int32_t crStateSaveMatrixStack(CRMatrixStack *pStack, PSSMHANDLE pSSM)
618{
619 return SSMR3PutMem(pSSM, pStack->stack, sizeof(CRmatrix) * pStack->maxDepth);
620}
621
622static int32_t crStateLoadMatrixStack(CRMatrixStack *pStack, PSSMHANDLE pSSM)
623{
624 int32_t rc;
625
626 CRASSERT(pStack && pSSM);
627
628 rc = SSMR3GetMem(pSSM, pStack->stack, sizeof(CRmatrix) * pStack->maxDepth);
629 /* fixup stack top pointer */
630 pStack->top = &pStack->stack[pStack->depth];
631 return rc;
632}
633
634static int32_t crStateSaveTextureObjPtr(CRTextureObj *pTexture, PSSMHANDLE pSSM)
635{
636 /* Current texture pointer can't be NULL for real texture unit states,
637 * but it could be NULL for unused attribute stack depths.
638 */
639 if (pTexture)
640 return SSMR3PutU32(pSSM, pTexture->id);
641 else
642 return VINF_SUCCESS;
643}
644
645static int32_t crStateLoadTextureObjPtr(CRTextureObj **pTexture, CRContext *pContext, GLenum target, PSSMHANDLE pSSM)
646{
647 uint32_t texName;
648 int32_t rc;
649
650 /* We're loading attrib stack with unused state */
651 if (!*pTexture)
652 return VINF_SUCCESS;
653
654 rc = SSMR3GetU32(pSSM, &texName);
655 AssertRCReturn(rc, rc);
656
657 if (texName)
658 {
659 *pTexture = (CRTextureObj *) crHashtableSearch(pContext->shared->textureTable, texName);
660 }
661 else
662 {
663 switch (target)
664 {
665 case GL_TEXTURE_1D:
666 *pTexture = &(pContext->texture.base1D);
667 break;
668 case GL_TEXTURE_2D:
669 *pTexture = &(pContext->texture.base2D);
670 break;
671#ifdef CR_OPENGL_VERSION_1_2
672 case GL_TEXTURE_3D:
673 *pTexture = &(pContext->texture.base3D);
674 break;
675#endif
676#ifdef CR_ARB_texture_cube_map
677 case GL_TEXTURE_CUBE_MAP_ARB:
678 *pTexture = &(pContext->texture.baseCubeMap);
679 break;
680#endif
681#ifdef CR_NV_texture_rectangle
682 case GL_TEXTURE_RECTANGLE_NV:
683 *pTexture = &(pContext->texture.baseRect);
684 break;
685#endif
686 default:
687 crError("LoadTextureObjPtr: Unknown texture target %d", target);
688 }
689 }
690
691 return rc;
692}
693
694static int32_t crStateSaveTexUnitCurrentTexturePtrs(CRTextureUnit *pTexUnit, PSSMHANDLE pSSM)
695{
696 int32_t rc;
697
698 rc = crStateSaveTextureObjPtr(pTexUnit->currentTexture1D, pSSM);
699 AssertRCReturn(rc, rc);
700 rc = crStateSaveTextureObjPtr(pTexUnit->currentTexture2D, pSSM);
701 AssertRCReturn(rc, rc);
702 rc = crStateSaveTextureObjPtr(pTexUnit->currentTexture3D, pSSM);
703 AssertRCReturn(rc, rc);
704#ifdef CR_ARB_texture_cube_map
705 rc = crStateSaveTextureObjPtr(pTexUnit->currentTextureCubeMap, pSSM);
706 AssertRCReturn(rc, rc);
707#endif
708#ifdef CR_NV_texture_rectangle
709 rc = crStateSaveTextureObjPtr(pTexUnit->currentTextureRect, pSSM);
710 AssertRCReturn(rc, rc);
711#endif
712
713 return rc;
714}
715
716static int32_t crStateLoadTexUnitCurrentTexturePtrs(CRTextureUnit *pTexUnit, CRContext *pContext, PSSMHANDLE pSSM)
717{
718 int32_t rc;
719
720 rc = crStateLoadTextureObjPtr(&pTexUnit->currentTexture1D, pContext, GL_TEXTURE_1D, pSSM);
721 AssertRCReturn(rc, rc);
722 rc = crStateLoadTextureObjPtr(&pTexUnit->currentTexture2D, pContext, GL_TEXTURE_1D, pSSM);
723 AssertRCReturn(rc, rc);
724 rc = crStateLoadTextureObjPtr(&pTexUnit->currentTexture3D, pContext, GL_TEXTURE_2D, pSSM);
725 AssertRCReturn(rc, rc);
726#ifdef CR_ARB_texture_cube_map
727 rc = crStateLoadTextureObjPtr(&pTexUnit->currentTextureCubeMap, pContext, GL_TEXTURE_CUBE_MAP_ARB, pSSM);
728 AssertRCReturn(rc, rc);
729#endif
730#ifdef CR_NV_texture_rectangle
731 rc = crStateLoadTextureObjPtr(&pTexUnit->currentTextureRect, pContext, GL_TEXTURE_RECTANGLE_NV, pSSM);
732 AssertRCReturn(rc, rc);
733#endif
734
735 return rc;
736}
737
738static int32_t crSateSaveEvalCoeffs1D(CREvaluator1D *pEval, PSSMHANDLE pSSM)
739{
740 int32_t rc, i;
741
742 for (i=0; i<GLEVAL_TOT; ++i)
743 {
744 if (pEval[i].coeff)
745 {
746 rc = SSMR3PutMem(pSSM, pEval[i].coeff, pEval[i].order * gleval_sizes[i] * sizeof(GLfloat));
747 AssertRCReturn(rc, rc);
748 }
749 }
750
751 return VINF_SUCCESS;
752}
753
754static int32_t crSateSaveEvalCoeffs2D(CREvaluator2D *pEval, PSSMHANDLE pSSM)
755{
756 int32_t rc, i;
757
758 for (i=0; i<GLEVAL_TOT; ++i)
759 {
760 if (pEval[i].coeff)
761 {
762 rc = SSMR3PutMem(pSSM, pEval[i].coeff, pEval[i].uorder * pEval[i].vorder * gleval_sizes[i] * sizeof(GLfloat));
763 AssertRCReturn(rc, rc);
764 }
765 }
766
767 return VINF_SUCCESS;
768}
769
770static int32_t crSateLoadEvalCoeffs1D(CREvaluator1D *pEval, GLboolean bReallocMem, PSSMHANDLE pSSM)
771{
772 int32_t rc, i;
773 size_t size;
774
775 for (i=0; i<GLEVAL_TOT; ++i)
776 {
777 if (pEval[i].coeff)
778 {
779 size = pEval[i].order * gleval_sizes[i] * sizeof(GLfloat);
780 if (bReallocMem)
781 {
782 pEval[i].coeff = (GLfloat*) crAlloc((unsigned int /* this case is just so stupid */)size);
783 if (!pEval[i].coeff) return VERR_NO_MEMORY;
784 }
785 rc = SSMR3GetMem(pSSM, pEval[i].coeff, size);
786 AssertRCReturn(rc, rc);
787 }
788 }
789
790 return VINF_SUCCESS;
791}
792
793static int32_t crSateLoadEvalCoeffs2D(CREvaluator2D *pEval, GLboolean bReallocMem, PSSMHANDLE pSSM)
794{
795 int32_t rc, i;
796 size_t size;
797
798 for (i=0; i<GLEVAL_TOT; ++i)
799 {
800 if (pEval[i].coeff)
801 {
802 size = pEval[i].uorder * pEval[i].vorder * gleval_sizes[i] * sizeof(GLfloat);
803 if (bReallocMem)
804 {
805 pEval[i].coeff = (GLfloat*) crAlloc((unsigned int /* this case is just so stupid */)size);
806 if (!pEval[i].coeff) return VERR_NO_MEMORY;
807 }
808 rc = SSMR3GetMem(pSSM, pEval[i].coeff, size);
809 AssertRCReturn(rc, rc);
810 }
811 }
812
813 return VINF_SUCCESS;
814}
815
816static void crStateCopyEvalPtrs1D(CREvaluator1D *pDst, CREvaluator1D *pSrc)
817{
818 int32_t i;
819
820 for (i=0; i<GLEVAL_TOT; ++i)
821 pDst[i].coeff = pSrc[i].coeff;
822
823 /*
824 pDst[GL_MAP1_VERTEX_3-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_VERTEX_3-GL_MAP1_COLOR_4].coeff;
825 pDst[GL_MAP1_VERTEX_4-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_VERTEX_4-GL_MAP1_COLOR_4].coeff;
826 pDst[GL_MAP1_INDEX-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_INDEX-GL_MAP1_COLOR_4].coeff;
827 pDst[GL_MAP1_COLOR_4-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_COLOR_4-GL_MAP1_COLOR_4].coeff;
828 pDst[GL_MAP1_NORMAL-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_NORMAL-GL_MAP1_COLOR_4].coeff;
829 pDst[GL_MAP1_TEXTURE_COORD_1-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_TEXTURE_COORD_1-GL_MAP1_COLOR_4].coeff;
830 pDst[GL_MAP1_TEXTURE_COORD_2-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_TEXTURE_COORD_2-GL_MAP1_COLOR_4].coeff;
831 pDst[GL_MAP1_TEXTURE_COORD_3-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_TEXTURE_COORD_3-GL_MAP1_COLOR_4].coeff;
832 pDst[GL_MAP1_TEXTURE_COORD_4-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_TEXTURE_COORD_4-GL_MAP1_COLOR_4].coeff;
833 */
834}
835
836static void crStateCopyEvalPtrs2D(CREvaluator2D *pDst, CREvaluator2D *pSrc)
837{
838 int32_t i;
839
840 for (i=0; i<GLEVAL_TOT; ++i)
841 pDst[i].coeff = pSrc[i].coeff;
842
843 /*
844 pDst[GL_MAP2_VERTEX_3-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_VERTEX_3-GL_MAP2_COLOR_4].coeff;
845 pDst[GL_MAP2_VERTEX_4-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_VERTEX_4-GL_MAP2_COLOR_4].coeff;
846 pDst[GL_MAP2_INDEX-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_INDEX-GL_MAP2_COLOR_4].coeff;
847 pDst[GL_MAP2_COLOR_4-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_COLOR_4-GL_MAP2_COLOR_4].coeff;
848 pDst[GL_MAP2_NORMAL-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_NORMAL-GL_MAP2_COLOR_4].coeff;
849 pDst[GL_MAP2_TEXTURE_COORD_1-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_TEXTURE_COORD_1-GL_MAP2_COLOR_4].coeff;
850 pDst[GL_MAP2_TEXTURE_COORD_2-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_TEXTURE_COORD_2-GL_MAP2_COLOR_4].coeff;
851 pDst[GL_MAP2_TEXTURE_COORD_3-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_TEXTURE_COORD_3-GL_MAP2_COLOR_4].coeff;
852 pDst[GL_MAP2_TEXTURE_COORD_4-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_TEXTURE_COORD_4-GL_MAP2_COLOR_4].coeff;
853 */
854}
855
856static void crStateSaveBufferObjectCB(unsigned long key, void *data1, void *data2)
857{
858 CRBufferObject *pBufferObj = (CRBufferObject *) data1;
859 PSSMHANDLE pSSM = (PSSMHANDLE) data2;
860 int32_t rc;
861
862 CRASSERT(pBufferObj && pSSM);
863
864 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
865 CRASSERT(rc == VINF_SUCCESS);
866 rc = SSMR3PutMem(pSSM, pBufferObj, sizeof(*pBufferObj));
867 CRASSERT(rc == VINF_SUCCESS);
868
869 if (pBufferObj->data)
870 {
871 /*We could get here even though retainBufferData is false on host side, in case when we're taking snapshot
872 after state load and before this context was ever made current*/
873 CRASSERT(pBufferObj->size>0);
874 rc = SSMR3PutMem(pSSM, pBufferObj->data, pBufferObj->size);
875 CRASSERT(rc == VINF_SUCCESS);
876 }
877 else if (pBufferObj->id!=0 && pBufferObj->size>0)
878 {
879 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, pBufferObj->hwid);
880 pBufferObj->pointer = diff_api.MapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB);
881 rc = SSMR3PutMem(pSSM, &pBufferObj->pointer, sizeof(pBufferObj->pointer));
882 CRASSERT(rc == VINF_SUCCESS);
883 if (pBufferObj->pointer)
884 {
885 rc = SSMR3PutMem(pSSM, pBufferObj->pointer, pBufferObj->size);
886 CRASSERT(rc == VINF_SUCCESS);
887 }
888 diff_api.UnmapBufferARB(GL_ARRAY_BUFFER_ARB);
889 pBufferObj->pointer = NULL;
890 }
891}
892
893static void crStateSaveProgramCB(unsigned long key, void *data1, void *data2)
894{
895 CRProgram *pProgram = (CRProgram *) data1;
896 PSSMHANDLE pSSM = (PSSMHANDLE) data2;
897 CRProgramSymbol *pSymbol;
898 int32_t rc;
899
900 CRASSERT(pProgram && pSSM);
901
902 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
903 CRASSERT(rc == VINF_SUCCESS);
904 rc = SSMR3PutMem(pSSM, pProgram, sizeof(*pProgram));
905 CRASSERT(rc == VINF_SUCCESS);
906 if (pProgram->string)
907 {
908 CRASSERT(pProgram->length);
909 rc = SSMR3PutMem(pSSM, pProgram->string, pProgram->length);
910 CRASSERT(rc == VINF_SUCCESS);
911 }
912
913 for (pSymbol = pProgram->symbolTable; pSymbol; pSymbol=pSymbol->next)
914 {
915 rc = SSMR3PutMem(pSSM, pSymbol, sizeof(*pSymbol));
916 CRASSERT(rc == VINF_SUCCESS);
917 if (pSymbol->name)
918 {
919 CRASSERT(pSymbol->cbName>0);
920 rc = SSMR3PutMem(pSSM, pSymbol->name, pSymbol->cbName);
921 CRASSERT(rc == VINF_SUCCESS);
922 }
923 }
924}
925
926static void crStateSaveFramebuffersCB(unsigned long key, void *data1, void *data2)
927{
928 CRFramebufferObject *pFBO = (CRFramebufferObject*) data1;
929 PSSMHANDLE pSSM = (PSSMHANDLE) data2;
930 int32_t rc;
931
932 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
933 CRASSERT(rc == VINF_SUCCESS);
934
935 rc = SSMR3PutMem(pSSM, pFBO, sizeof(*pFBO));
936 CRASSERT(rc == VINF_SUCCESS);
937}
938
939static void crStateSaveRenderbuffersCB(unsigned long key, void *data1, void *data2)
940{
941 CRRenderbufferObject *pRBO = (CRRenderbufferObject*) data1;
942 PSSMHANDLE pSSM = (PSSMHANDLE) data2;
943 int32_t rc;
944
945 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
946 CRASSERT(rc == VINF_SUCCESS);
947
948 rc = SSMR3PutMem(pSSM, pRBO, sizeof(*pRBO));
949 CRASSERT(rc == VINF_SUCCESS);
950}
951
952static int32_t crStateLoadProgram(CRProgram **ppProgram, PSSMHANDLE pSSM)
953{
954 CRProgramSymbol **ppSymbol;
955 int32_t rc;
956 unsigned long key;
957
958 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
959 AssertRCReturn(rc, rc);
960
961 /* we're loading default vertex or pixel program*/
962 if (*ppProgram)
963 {
964 if (key!=0) return VERR_SSM_UNEXPECTED_DATA;
965 }
966 else
967 {
968 *ppProgram = (CRProgram*) crAlloc(sizeof(CRProgram));
969 if (!ppProgram) return VERR_NO_MEMORY;
970 if (key==0) return VERR_SSM_UNEXPECTED_DATA;
971 }
972
973 rc = SSMR3GetMem(pSSM, *ppProgram, sizeof(**ppProgram));
974 AssertRCReturn(rc, rc);
975
976 if ((*ppProgram)->string)
977 {
978 CRASSERT((*ppProgram)->length);
979 (*ppProgram)->string = crAlloc((*ppProgram)->length);
980 if (!(*ppProgram)->string) return VERR_NO_MEMORY;
981 rc = SSMR3GetMem(pSSM, (void*) (*ppProgram)->string, (*ppProgram)->length);
982 AssertRCReturn(rc, rc);
983 }
984
985 for (ppSymbol = &(*ppProgram)->symbolTable; *ppSymbol; ppSymbol=&(*ppSymbol)->next)
986 {
987 *ppSymbol = crAlloc(sizeof(CRProgramSymbol));
988 if (!ppSymbol) return VERR_NO_MEMORY;
989
990 rc = SSMR3GetMem(pSSM, *ppSymbol, sizeof(**ppSymbol));
991 AssertRCReturn(rc, rc);
992
993 if ((*ppSymbol)->name)
994 {
995 CRASSERT((*ppSymbol)->cbName>0);
996 (*ppSymbol)->name = crAlloc((*ppSymbol)->cbName);
997 if (!(*ppSymbol)->name) return VERR_NO_MEMORY;
998
999 rc = SSMR3GetMem(pSSM, (void*) (*ppSymbol)->name, (*ppSymbol)->cbName);
1000 AssertRCReturn(rc, rc);
1001 }
1002 }
1003
1004 return VINF_SUCCESS;
1005}
1006
1007static void crStateSaveString(const char *pStr, PSSMHANDLE pSSM)
1008{
1009 int32_t len;
1010 int32_t rc;
1011
1012 if (pStr)
1013 {
1014 len = crStrlen(pStr)+1;
1015
1016 rc = SSMR3PutS32(pSSM, len);
1017 CRASSERT(rc == VINF_SUCCESS);
1018
1019 rc = SSMR3PutMem(pSSM, pStr, len*sizeof(*pStr));
1020 CRASSERT(rc == VINF_SUCCESS);
1021 }
1022 else
1023 {
1024 rc = SSMR3PutS32(pSSM, 0);
1025 CRASSERT(rc == VINF_SUCCESS);
1026 }
1027}
1028
1029static char* crStateLoadString(PSSMHANDLE pSSM)
1030{
1031 int32_t len, rc;
1032 char* pStr = NULL;
1033
1034 rc = SSMR3GetS32(pSSM, &len);
1035 CRASSERT(rc == VINF_SUCCESS);
1036
1037 if (len!=0)
1038 {
1039 pStr = crAlloc(len*sizeof(*pStr));
1040
1041 rc = SSMR3GetMem(pSSM, pStr, len*sizeof(*pStr));
1042 CRASSERT(rc == VINF_SUCCESS);
1043 }
1044
1045 return pStr;
1046}
1047
1048static void crStateSaveGLSLShaderCB(unsigned long key, void *data1, void *data2)
1049{
1050 CRGLSLShader *pShader = (CRGLSLShader*) data1;
1051 PSSMHANDLE pSSM = (PSSMHANDLE) data2;
1052 int32_t rc;
1053
1054 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
1055 CRASSERT(rc == VINF_SUCCESS);
1056
1057 rc = SSMR3PutMem(pSSM, pShader, sizeof(*pShader));
1058 CRASSERT(rc == VINF_SUCCESS);
1059
1060 if (pShader->source)
1061 {
1062 crStateSaveString(pShader->source, pSSM);
1063 }
1064 else
1065 {
1066 GLint sLen=0;
1067 GLchar *source=NULL;
1068
1069 diff_api.GetShaderiv(pShader->hwid, GL_SHADER_SOURCE_LENGTH, &sLen);
1070 if (sLen>0)
1071 {
1072 source = (GLchar*) crAlloc(sLen);
1073 diff_api.GetShaderSource(pShader->hwid, sLen, NULL, source);
1074 }
1075
1076 crStateSaveString(source, pSSM);
1077 if (source) crFree(source);
1078 }
1079}
1080
1081static CRGLSLShader* crStateLoadGLSLShader(PSSMHANDLE pSSM)
1082{
1083 CRGLSLShader *pShader;
1084 int32_t rc;
1085 unsigned long key;
1086
1087 pShader = crAlloc(sizeof(*pShader));
1088 if (!pShader) return NULL;
1089
1090 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
1091 CRASSERT(rc == VINF_SUCCESS);
1092
1093 rc = SSMR3GetMem(pSSM, pShader, sizeof(*pShader));
1094 CRASSERT(rc == VINF_SUCCESS);
1095
1096 pShader->source = crStateLoadString(pSSM);
1097
1098 return pShader;
1099}
1100
1101
1102static void crStateSaveGLSLShaderKeyCB(unsigned long key, void *data1, void *data2)
1103{
1104 //CRGLSLShader *pShader = (CRGLSLShader*) data1;
1105 PSSMHANDLE pSSM = (PSSMHANDLE) data2;
1106 int32_t rc;
1107
1108 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
1109 CRASSERT(rc == VINF_SUCCESS);
1110}
1111
1112static void crStateSaveGLSLProgramAttribs(CRGLSLProgramState *pState, PSSMHANDLE pSSM)
1113{
1114 GLuint i;
1115 int32_t rc;
1116
1117 for (i=0; i<pState->cAttribs; ++i)
1118 {
1119 rc = SSMR3PutMem(pSSM, &pState->pAttribs[i].index, sizeof(pState->pAttribs[i].index));
1120 CRASSERT(rc == VINF_SUCCESS);
1121 crStateSaveString(pState->pAttribs[i].name, pSSM);
1122 }
1123}
1124
1125static void crStateSaveGLSLProgramCB(unsigned long key, void *data1, void *data2)
1126{
1127 CRGLSLProgram *pProgram = (CRGLSLProgram*) data1;
1128 PSSMHANDLE pSSM = (PSSMHANDLE) data2;
1129 int32_t rc;
1130 uint32_t ui32;
1131 GLint maxUniformLen, activeUniforms=0, uniformsCount=0, i, j;
1132 GLchar *name = NULL;
1133 GLenum type;
1134 GLint size, location;
1135
1136 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
1137 CRASSERT(rc == VINF_SUCCESS);
1138
1139 rc = SSMR3PutMem(pSSM, pProgram, sizeof(*pProgram));
1140 CRASSERT(rc == VINF_SUCCESS);
1141
1142 ui32 = crHashtableNumElements(pProgram->currentState.attachedShaders);
1143 rc = SSMR3PutU32(pSSM, ui32);
1144 CRASSERT(rc == VINF_SUCCESS);
1145
1146 crHashtableWalk(pProgram->currentState.attachedShaders, crStateSaveGLSLShaderKeyCB, pSSM);
1147
1148 if (pProgram->activeState.attachedShaders)
1149 {
1150 ui32 = crHashtableNumElements(pProgram->activeState.attachedShaders);
1151 rc = SSMR3PutU32(pSSM, ui32);
1152 CRASSERT(rc == VINF_SUCCESS);
1153 crHashtableWalk(pProgram->currentState.attachedShaders, crStateSaveGLSLShaderCB, pSSM);
1154 }
1155
1156 crStateSaveGLSLProgramAttribs(&pProgram->currentState, pSSM);
1157 crStateSaveGLSLProgramAttribs(&pProgram->activeState, pSSM);
1158
1159 diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformLen);
1160 diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_UNIFORMS, &activeUniforms);
1161
1162 if (!maxUniformLen)
1163 {
1164 if (activeUniforms)
1165 {
1166 crWarning("activeUniforms (%d), while maxUniformLen is zero", activeUniforms);
1167 activeUniforms = 0;
1168 }
1169 }
1170
1171 if (activeUniforms>0)
1172 {
1173 name = (GLchar *) crAlloc((maxUniformLen+8)*sizeof(GLchar));
1174
1175 if (!name)
1176 {
1177 crWarning("crStateSaveGLSLProgramCB: out of memory");
1178 return;
1179 }
1180 }
1181
1182 for (i=0; i<activeUniforms; ++i)
1183 {
1184 diff_api.GetActiveUniform(pProgram->hwid, i, maxUniformLen, NULL, &size, &type, name);
1185 uniformsCount += size;
1186 }
1187 CRASSERT(uniformsCount>=activeUniforms);
1188
1189 rc = SSMR3PutS32(pSSM, uniformsCount);
1190 CRASSERT(rc == VINF_SUCCESS);
1191
1192 if (activeUniforms>0)
1193 {
1194 GLfloat fdata[16];
1195 GLint idata[16];
1196 char *pIndexStr=NULL;
1197
1198 for (i=0; i<activeUniforms; ++i)
1199 {
1200 diff_api.GetActiveUniform(pProgram->hwid, i, maxUniformLen, NULL, &size, &type, name);
1201
1202 if (size>1)
1203 {
1204 pIndexStr = crStrchr(name, '[');
1205 if (!pIndexStr)
1206 {
1207 pIndexStr = name+crStrlen(name);
1208 }
1209 }
1210
1211 for (j=0; j<size; ++j)
1212 {
1213 if (size>1)
1214 {
1215 sprintf(pIndexStr, "[%i]", j);
1216 }
1217 location = diff_api.GetUniformLocation(pProgram->hwid, name);
1218
1219 rc = SSMR3PutMem(pSSM, &type, sizeof(type));
1220 CRASSERT(rc == VINF_SUCCESS);
1221
1222 crStateSaveString(name, pSSM);
1223
1224 if (crStateIsIntUniform(type))
1225 {
1226 diff_api.GetUniformiv(pProgram->hwid, location, &idata[0]);
1227 rc = SSMR3PutMem(pSSM, &idata[0], crStateGetUniformSize(type)*sizeof(idata[0]));
1228 CRASSERT(rc == VINF_SUCCESS);
1229 }
1230 else
1231 {
1232 diff_api.GetUniformfv(pProgram->hwid, location, &fdata[0]);
1233 rc = SSMR3PutMem(pSSM, &fdata[0], crStateGetUniformSize(type)*sizeof(fdata[0]));
1234 CRASSERT(rc == VINF_SUCCESS);
1235 }
1236 }
1237 }
1238
1239 crFree(name);
1240 }
1241}
1242
1243static int32_t crStateSaveClientPointer(CRVertexArrays *pArrays, int32_t index, PSSMHANDLE pSSM)
1244{
1245 int32_t rc;
1246 CRClientPointer *cp;
1247
1248 cp = crStateGetClientPointerByIndex(index, pArrays);
1249
1250 if (cp->buffer)
1251 rc = SSMR3PutU32(pSSM, cp->buffer->id);
1252 else
1253 rc = SSMR3PutU32(pSSM, 0);
1254
1255 AssertRCReturn(rc, rc);
1256
1257#ifdef CR_EXT_compiled_vertex_array
1258 if (cp->locked)
1259 {
1260 CRASSERT(cp->p);
1261 rc = SSMR3PutMem(pSSM, cp->p, cp->stride*(pArrays->lockFirst+pArrays->lockCount));
1262 AssertRCReturn(rc, rc);
1263 }
1264#endif
1265
1266 return VINF_SUCCESS;
1267}
1268
1269static int32_t crStateLoadClientPointer(CRVertexArrays *pArrays, int32_t index, CRContext *pContext, PSSMHANDLE pSSM)
1270{
1271 int32_t rc;
1272 uint32_t ui;
1273 CRClientPointer *cp;
1274
1275 cp = crStateGetClientPointerByIndex(index, pArrays);
1276
1277 rc = SSMR3GetU32(pSSM, &ui);
1278 AssertRCReturn(rc, rc);
1279 cp->buffer = ui==0 ? pContext->bufferobject.nullBuffer : crHashtableSearch(pContext->shared->buffersTable, ui);
1280
1281 if (!cp->buffer)
1282 {
1283 crWarning("crStateLoadClientPointer: ui=%d loaded as NULL buffer!", ui);
1284 }
1285
1286#ifdef CR_EXT_compiled_vertex_array
1287 if (cp->locked)
1288 {
1289 rc = crStateAllocAndSSMR3GetMem(pSSM, (void**)&cp->p, cp->stride*(pArrays->lockFirst+pArrays->lockCount));
1290 AssertRCReturn(rc, rc);
1291 }
1292#endif
1293
1294 return VINF_SUCCESS;
1295}
1296
1297static int32_t crStateSaveCurrentBits(CRStateBits *pBits, PSSMHANDLE pSSM)
1298{
1299 int32_t rc, i;
1300
1301 rc = SSMR3PutMem(pSSM, pBits, sizeof(*pBits));
1302 AssertRCReturn(rc, rc);
1303
1304 rc = SSMR3PutMem(pSSM, pBits->client.v, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
1305 AssertRCReturn(rc, rc);
1306 rc = SSMR3PutMem(pSSM, pBits->client.n, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
1307 AssertRCReturn(rc, rc);
1308 rc = SSMR3PutMem(pSSM, pBits->client.c, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
1309 AssertRCReturn(rc, rc);
1310 rc = SSMR3PutMem(pSSM, pBits->client.s, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
1311 AssertRCReturn(rc, rc);
1312 rc = SSMR3PutMem(pSSM, pBits->client.i, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
1313 AssertRCReturn(rc, rc);
1314 for (i=0; i<CR_MAX_TEXTURE_UNITS; i++)
1315 {
1316 rc = SSMR3PutMem(pSSM, pBits->client.t[i], GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
1317 AssertRCReturn(rc, rc);
1318 }
1319 rc = SSMR3PutMem(pSSM, pBits->client.e, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
1320 AssertRCReturn(rc, rc);
1321 rc = SSMR3PutMem(pSSM, pBits->client.f, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
1322 AssertRCReturn(rc, rc);
1323#ifdef CR_NV_vertex_program
1324 for (i=0; i<CR_MAX_VERTEX_ATTRIBS; i++)
1325 {
1326 rc = SSMR3PutMem(pSSM, pBits->client.a[i], GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
1327 AssertRCReturn(rc, rc);
1328 }
1329#endif
1330
1331 rc = SSMR3PutMem(pSSM, pBits->lighting.light, CR_MAX_LIGHTS*sizeof(pBits->lighting.light));
1332 AssertRCReturn(rc, rc);
1333
1334 return VINF_SUCCESS;
1335}
1336
1337static int32_t crStateLoadCurrentBits(CRStateBits *pBits, PSSMHANDLE pSSM)
1338{
1339 int32_t rc, i;
1340 CRClientBits client;
1341 CRLightingBits lighting;
1342
1343 CRASSERT(pBits);
1344
1345 client.v = pBits->client.v;
1346 client.n = pBits->client.n;
1347 client.c = pBits->client.c;
1348 client.s = pBits->client.s;
1349 client.i = pBits->client.i;
1350 client.e = pBits->client.e;
1351 client.f = pBits->client.f;
1352 for (i=0; i<CR_MAX_TEXTURE_UNITS; i++)
1353 {
1354 client.t[i] = pBits->client.t[i];
1355 }
1356#ifdef CR_NV_vertex_program
1357 for (i=0; i<CR_MAX_VERTEX_ATTRIBS; i++)
1358 {
1359 client.a[i] = pBits->client.a[i];
1360 }
1361#endif
1362 lighting.light = pBits->lighting.light;
1363
1364 rc = SSMR3GetMem(pSSM, pBits, sizeof(*pBits));
1365 AssertRCReturn(rc, rc);
1366
1367 pBits->client.v = client.v;
1368 rc = SSMR3GetMem(pSSM, pBits->client.v, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
1369 AssertRCReturn(rc, rc);
1370 pBits->client.n = client.n;
1371 rc = SSMR3GetMem(pSSM, pBits->client.n, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
1372 AssertRCReturn(rc, rc);
1373 pBits->client.c = client.c;
1374 rc = SSMR3GetMem(pSSM, pBits->client.c, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
1375 AssertRCReturn(rc, rc);
1376 pBits->client.s = client.s;
1377 rc = SSMR3GetMem(pSSM, pBits->client.s, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
1378 AssertRCReturn(rc, rc);
1379 pBits->client.i = client.i;
1380 rc = SSMR3GetMem(pSSM, pBits->client.i, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
1381 AssertRCReturn(rc, rc);
1382 pBits->client.e = client.e;
1383 rc = SSMR3GetMem(pSSM, pBits->client.e, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
1384 AssertRCReturn(rc, rc);
1385 pBits->client.f = client.f;
1386 rc = SSMR3GetMem(pSSM, pBits->client.f, GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
1387 AssertRCReturn(rc, rc);
1388 for (i=0; i<CR_MAX_TEXTURE_UNITS; i++)
1389 {
1390 pBits->client.t[i] = client.t[i];
1391 rc = SSMR3GetMem(pSSM, pBits->client.t[i], GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
1392 AssertRCReturn(rc, rc);
1393 }
1394#ifdef CR_NV_vertex_program
1395 for (i=0; i<CR_MAX_VERTEX_ATTRIBS; i++)
1396 {
1397 pBits->client.a[i] = client.a[i];
1398 rc = SSMR3GetMem(pSSM, pBits->client.a[i], GLCLIENT_BIT_ALLOC*sizeof(CRbitvalue));
1399 AssertRCReturn(rc, rc);
1400 }
1401#endif
1402
1403 pBits->lighting.light = lighting.light;
1404 rc = SSMR3GetMem(pSSM, pBits->lighting.light, CR_MAX_LIGHTS*sizeof(pBits->lighting.light));
1405 AssertRCReturn(rc, rc);
1406
1407 return VINF_SUCCESS;
1408}
1409
1410static void crStateSaveKeysCB(unsigned long firstKey, unsigned long count, void *data)
1411{
1412 PSSMHANDLE pSSM = (PSSMHANDLE)data;
1413 int rc;
1414 CRASSERT(firstKey);
1415 CRASSERT(count);
1416 rc = SSMR3PutU32(pSSM, firstKey);
1417 CRASSERT(RT_SUCCESS(rc));
1418 rc = SSMR3PutU32(pSSM, count);
1419 CRASSERT(RT_SUCCESS(rc));
1420}
1421
1422static int32_t crStateSaveKeys(CRHashTable *pHash, PSSMHANDLE pSSM)
1423{
1424 crHashtableWalkKeys(pHash, crStateSaveKeysCB , pSSM);
1425 /* use null terminator */
1426 SSMR3PutU32(pSSM, 0);
1427 return VINF_SUCCESS;
1428}
1429
1430static int32_t crStateLoadKeys(CRHashTable *pHash, PSSMHANDLE pSSM, uint32_t u32Version)
1431{
1432 uint32_t u32Key, u32Count, i;
1433 int rc;
1434 for(;;)
1435 {
1436 rc = SSMR3GetU32(pSSM, &u32Key);
1437 AssertRCReturn(rc, rc);
1438
1439 if (!u32Key)
1440 return rc;
1441
1442 rc = SSMR3GetU32(pSSM, &u32Count);
1443 AssertRCReturn(rc, rc);
1444
1445 CRASSERT(u32Count);
1446
1447 if (u32Version > SHCROGL_SSM_VERSION_WITH_BUGGY_KEYS)
1448 {
1449 for (i = u32Key; i < u32Count + u32Key; ++i)
1450 {
1451 GLboolean fIsNew = crHashtableAllocRegisterKey(pHash, i); NOREF(fIsNew);
1452#if 0 //def DEBUG_misha
1453 CRASSERT(fIsNew);
1454#endif
1455 }
1456 }
1457 }
1458 /* not reached*/
1459}
1460
1461
1462int32_t crStateSaveContext(CRContext *pContext, PSSMHANDLE pSSM)
1463{
1464 int32_t rc, i;
1465 uint32_t ui32, j;
1466 GLboolean bSaveShared = GL_TRUE;
1467
1468 CRASSERT(pContext && pSSM);
1469
1470 CRASSERT(pContext->client.attribStackDepth == 0);
1471
1472 /* this stuff is not used anymore, zero it up for sanity */
1473 pContext->buffer.storedWidth = 0;
1474 pContext->buffer.storedHeight = 0;
1475
1476 CRASSERT(VBoxTlsRefIsFunctional(pContext));
1477
1478 /* make sure the gl error state is captured by our state mechanism to store the correct gl error value */
1479 crStateSyncHWErrorState(pContext);
1480
1481 rc = SSMR3PutMem(pSSM, pContext, sizeof (*pContext));
1482 AssertRCReturn(rc, rc);
1483
1484 if (crHashtableNumElements(pContext->shared->dlistTable)>0)
1485 crWarning("Saving state with %d display lists, unsupported", crHashtableNumElements(pContext->shared->dlistTable));
1486
1487 if (crHashtableNumElements(pContext->program.programHash)>0)
1488 crDebug("Saving state with %d programs", crHashtableNumElements(pContext->program.programHash));
1489
1490 rc = SSMR3PutS32(pSSM, pContext->shared->id);
1491 AssertRCReturn(rc, rc);
1492
1493 rc = SSMR3PutS32(pSSM, crStateContextIsShared(pContext));
1494 AssertRCReturn(rc, rc);
1495
1496 if (pContext->shared->refCount>1)
1497 {
1498 bSaveShared = pContext->shared->saveCount==0;
1499
1500 ++pContext->shared->saveCount;
1501 if (pContext->shared->saveCount == pContext->shared->refCount)
1502 {
1503 pContext->shared->saveCount=0;
1504 }
1505 }
1506
1507 /* Save transform state */
1508 rc = SSMR3PutMem(pSSM, pContext->transform.clipPlane, sizeof(GLvectord)*CR_MAX_CLIP_PLANES);
1509 AssertRCReturn(rc, rc);
1510 rc = SSMR3PutMem(pSSM, pContext->transform.clip, sizeof(GLboolean)*CR_MAX_CLIP_PLANES);
1511 AssertRCReturn(rc, rc);
1512 rc = crStateSaveMatrixStack(&pContext->transform.modelViewStack, pSSM);
1513 AssertRCReturn(rc, rc);
1514 rc = crStateSaveMatrixStack(&pContext->transform.projectionStack, pSSM);
1515 AssertRCReturn(rc, rc);
1516 rc = crStateSaveMatrixStack(&pContext->transform.colorStack, pSSM);
1517 AssertRCReturn(rc, rc);
1518 for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
1519 {
1520 rc = crStateSaveMatrixStack(&pContext->transform.textureStack[i], pSSM);
1521 AssertRCReturn(rc, rc);
1522 }
1523 for (i = 0 ; i < CR_MAX_PROGRAM_MATRICES ; i++)
1524 {
1525 rc = crStateSaveMatrixStack(&pContext->transform.programStack[i], pSSM);
1526 AssertRCReturn(rc, rc);
1527 }
1528
1529 /* Save textures */
1530 rc = crStateSaveTextureObjData(&pContext->texture.base1D, pSSM);
1531 AssertRCReturn(rc, rc);
1532 rc = crStateSaveTextureObjData(&pContext->texture.base2D, pSSM);
1533 AssertRCReturn(rc, rc);
1534 rc = crStateSaveTextureObjData(&pContext->texture.base3D, pSSM);
1535 AssertRCReturn(rc, rc);
1536 rc = crStateSaveTextureObjData(&pContext->texture.proxy1D, pSSM);
1537 AssertRCReturn(rc, rc);
1538 rc = crStateSaveTextureObjData(&pContext->texture.proxy2D, pSSM);
1539 AssertRCReturn(rc, rc);
1540 rc = crStateSaveTextureObjData(&pContext->texture.proxy3D, pSSM);
1541#ifdef CR_ARB_texture_cube_map
1542 rc = crStateSaveTextureObjData(&pContext->texture.baseCubeMap, pSSM);
1543 AssertRCReturn(rc, rc);
1544 rc = crStateSaveTextureObjData(&pContext->texture.proxyCubeMap, pSSM);
1545 AssertRCReturn(rc, rc);
1546#endif
1547#ifdef CR_NV_texture_rectangle
1548 rc = crStateSaveTextureObjData(&pContext->texture.baseRect, pSSM);
1549 AssertRCReturn(rc, rc);
1550 rc = crStateSaveTextureObjData(&pContext->texture.proxyRect, pSSM);
1551 AssertRCReturn(rc, rc);
1552#endif
1553
1554 /* Save shared textures */
1555 if (bSaveShared)
1556 {
1557 CRASSERT(pContext->shared && pContext->shared->textureTable);
1558 rc = crStateSaveKeys(pContext->shared->textureTable, pSSM);
1559 AssertRCReturn(rc, rc);
1560 ui32 = crHashtableNumElements(pContext->shared->textureTable);
1561 rc = SSMR3PutU32(pSSM, ui32);
1562 AssertRCReturn(rc, rc);
1563 crHashtableWalk(pContext->shared->textureTable, crStateSaveSharedTextureCB, pSSM);
1564
1565#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
1566 /* Restore previous texture bindings via diff_api */
1567 if (ui32)
1568 {
1569 CRTextureUnit *pTexUnit;
1570
1571 pTexUnit = &pContext->texture.unit[pContext->texture.curTextureUnit];
1572
1573 diff_api.BindTexture(GL_TEXTURE_1D, pTexUnit->currentTexture1D->hwid);
1574 diff_api.BindTexture(GL_TEXTURE_2D, pTexUnit->currentTexture2D->hwid);
1575 diff_api.BindTexture(GL_TEXTURE_3D, pTexUnit->currentTexture3D->hwid);
1576#ifdef CR_ARB_texture_cube_map
1577 diff_api.BindTexture(GL_TEXTURE_CUBE_MAP_ARB, pTexUnit->currentTextureCubeMap->hwid);
1578#endif
1579#ifdef CR_NV_texture_rectangle
1580 diff_api.BindTexture(GL_TEXTURE_RECTANGLE_NV, pTexUnit->currentTextureRect->hwid);
1581#endif
1582 }
1583#endif
1584 }
1585
1586 /* Save current texture pointers */
1587 for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i)
1588 {
1589 rc = crStateSaveTexUnitCurrentTexturePtrs(&pContext->texture.unit[i], pSSM);
1590 AssertRCReturn(rc, rc);
1591 }
1592
1593 /* Save lights */
1594 CRASSERT(pContext->lighting.light);
1595 rc = SSMR3PutMem(pSSM, pContext->lighting.light, CR_MAX_LIGHTS * sizeof(*pContext->lighting.light));
1596 AssertRCReturn(rc, rc);
1597
1598 /* Save attrib stack*/
1599 /** @todo could go up to used stack depth here?*/
1600 for ( i = 0 ; i < CR_MAX_ATTRIB_STACK_DEPTH ; i++)
1601 {
1602 if (pContext->attrib.enableStack[i].clip)
1603 {
1604 rc = SSMR3PutMem(pSSM, pContext->attrib.enableStack[i].clip,
1605 pContext->limits.maxClipPlanes*sizeof(GLboolean));
1606 AssertRCReturn(rc, rc);
1607 }
1608
1609 if (pContext->attrib.enableStack[i].light)
1610 {
1611 rc = SSMR3PutMem(pSSM, pContext->attrib.enableStack[i].light,
1612 pContext->limits.maxLights*sizeof(GLboolean));
1613 AssertRCReturn(rc, rc);
1614 }
1615
1616 if (pContext->attrib.lightingStack[i].light)
1617 {
1618 rc = SSMR3PutMem(pSSM, pContext->attrib.lightingStack[i].light,
1619 pContext->limits.maxLights*sizeof(CRLight));
1620 AssertRCReturn(rc, rc);
1621 }
1622
1623 for (j=0; j<pContext->limits.maxTextureUnits; ++j)
1624 {
1625 rc = crStateSaveTexUnitCurrentTexturePtrs(&pContext->attrib.textureStack[i].unit[j], pSSM);
1626 AssertRCReturn(rc, rc);
1627 }
1628
1629 if (pContext->attrib.transformStack[i].clip)
1630 {
1631 rc = SSMR3PutMem(pSSM, pContext->attrib.transformStack[i].clip,
1632 pContext->limits.maxClipPlanes*sizeof(GLboolean));
1633 AssertRCReturn(rc, rc);
1634 }
1635
1636 if (pContext->attrib.transformStack[i].clipPlane)
1637 {
1638 rc = SSMR3PutMem(pSSM, pContext->attrib.transformStack[i].clipPlane,
1639 pContext->limits.maxClipPlanes*sizeof(GLvectord));
1640 AssertRCReturn(rc, rc);
1641 }
1642
1643 rc = crSateSaveEvalCoeffs1D(pContext->attrib.evalStack[i].eval1D, pSSM);
1644 AssertRCReturn(rc, rc);
1645 rc = crSateSaveEvalCoeffs2D(pContext->attrib.evalStack[i].eval2D, pSSM);
1646 AssertRCReturn(rc, rc);
1647 }
1648
1649 /* Save evaluator coeffs */
1650 rc = crSateSaveEvalCoeffs1D(pContext->eval.eval1D, pSSM);
1651 AssertRCReturn(rc, rc);
1652 rc = crSateSaveEvalCoeffs2D(pContext->eval.eval2D, pSSM);
1653 AssertRCReturn(rc, rc);
1654
1655#ifdef CR_ARB_vertex_buffer_object
1656 /* Save buffer objects */
1657 if (bSaveShared)
1658 {
1659 rc = crStateSaveKeys(pContext->shared->buffersTable, pSSM);
1660 AssertRCReturn(rc, rc);
1661 }
1662 ui32 = bSaveShared? crHashtableNumElements(pContext->shared->buffersTable):0;
1663 rc = SSMR3PutU32(pSSM, ui32);
1664 AssertRCReturn(rc, rc);
1665
1666 /* Save default one*/
1667 crStateSaveBufferObjectCB(0, pContext->bufferobject.nullBuffer, pSSM);
1668
1669 if (bSaveShared)
1670 {
1671 /* Save all the rest */
1672 crHashtableWalk(pContext->shared->buffersTable, crStateSaveBufferObjectCB, pSSM);
1673 }
1674
1675 /* Restore binding */
1676 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, pContext->bufferobject.arrayBuffer->hwid);
1677
1678 /* Save pointers */
1679 rc = SSMR3PutU32(pSSM, pContext->bufferobject.arrayBuffer->id);
1680 AssertRCReturn(rc, rc);
1681 rc = SSMR3PutU32(pSSM, pContext->bufferobject.elementsBuffer->id);
1682 AssertRCReturn(rc, rc);
1683#ifdef CR_ARB_pixel_buffer_object
1684 rc = SSMR3PutU32(pSSM, pContext->bufferobject.packBuffer->id);
1685 AssertRCReturn(rc, rc);
1686 rc = SSMR3PutU32(pSSM, pContext->bufferobject.unpackBuffer->id);
1687 AssertRCReturn(rc, rc);
1688#endif
1689 /* Save clint pointers and buffer bindings*/
1690 for (i=0; i<CRSTATECLIENT_MAX_VERTEXARRAYS; ++i)
1691 {
1692 rc = crStateSaveClientPointer(&pContext->client.array, i, pSSM);
1693 AssertRCReturn(rc, rc);
1694 }
1695
1696 crDebug("client.vertexArrayStackDepth %i", pContext->client.vertexArrayStackDepth);
1697 for (i=0; i<pContext->client.vertexArrayStackDepth; ++i)
1698 {
1699 CRVertexArrays *pArray = &pContext->client.vertexArrayStack[i];
1700 for (j=0; j<CRSTATECLIENT_MAX_VERTEXARRAYS; ++j)
1701 {
1702 rc = crStateSaveClientPointer(pArray, j, pSSM);
1703 AssertRCReturn(rc, rc);
1704 }
1705 }
1706#endif /*CR_ARB_vertex_buffer_object*/
1707
1708 /* Save pixel/vertex programs */
1709 ui32 = crHashtableNumElements(pContext->program.programHash);
1710 rc = SSMR3PutU32(pSSM, ui32);
1711 AssertRCReturn(rc, rc);
1712 /* Save defaults programs */
1713 crStateSaveProgramCB(0, pContext->program.defaultVertexProgram, pSSM);
1714 crStateSaveProgramCB(0, pContext->program.defaultFragmentProgram, pSSM);
1715 /* Save all the rest */
1716 crHashtableWalk(pContext->program.programHash, crStateSaveProgramCB, pSSM);
1717 /* Save Pointers */
1718 rc = SSMR3PutU32(pSSM, pContext->program.currentVertexProgram->id);
1719 AssertRCReturn(rc, rc);
1720 rc = SSMR3PutU32(pSSM, pContext->program.currentFragmentProgram->id);
1721 AssertRCReturn(rc, rc);
1722 /* This one is unused it seems*/
1723 CRASSERT(!pContext->program.errorString);
1724
1725#ifdef CR_EXT_framebuffer_object
1726 /* Save FBOs */
1727 if (bSaveShared)
1728 {
1729 rc = crStateSaveKeys(pContext->shared->fbTable, pSSM);
1730 AssertRCReturn(rc, rc);
1731 ui32 = crHashtableNumElements(pContext->shared->fbTable);
1732 rc = SSMR3PutU32(pSSM, ui32);
1733 AssertRCReturn(rc, rc);
1734 crHashtableWalk(pContext->shared->fbTable, crStateSaveFramebuffersCB, pSSM);
1735
1736 rc = crStateSaveKeys(pContext->shared->rbTable, pSSM);
1737 AssertRCReturn(rc, rc);
1738 ui32 = crHashtableNumElements(pContext->shared->rbTable);
1739 rc = SSMR3PutU32(pSSM, ui32);
1740 AssertRCReturn(rc, rc);
1741 crHashtableWalk(pContext->shared->rbTable, crStateSaveRenderbuffersCB, pSSM);
1742 }
1743 rc = SSMR3PutU32(pSSM, pContext->framebufferobject.drawFB?pContext->framebufferobject.drawFB->id:0);
1744 AssertRCReturn(rc, rc);
1745 rc = SSMR3PutU32(pSSM, pContext->framebufferobject.readFB?pContext->framebufferobject.readFB->id:0);
1746 AssertRCReturn(rc, rc);
1747 rc = SSMR3PutU32(pSSM, pContext->framebufferobject.renderbuffer?pContext->framebufferobject.renderbuffer->id:0);
1748 AssertRCReturn(rc, rc);
1749#endif
1750
1751#ifdef CR_OPENGL_VERSION_2_0
1752 /* Save GLSL related info */
1753 ui32 = crHashtableNumElements(pContext->glsl.shaders);
1754 rc = SSMR3PutU32(pSSM, ui32);
1755 AssertRCReturn(rc, rc);
1756 crHashtableWalk(pContext->glsl.shaders, crStateSaveGLSLShaderCB, pSSM);
1757 ui32 = crHashtableNumElements(pContext->glsl.programs);
1758 rc = SSMR3PutU32(pSSM, ui32);
1759 AssertRCReturn(rc, rc);
1760 crHashtableWalk(pContext->glsl.programs, crStateSaveGLSLProgramCB, pSSM);
1761 rc = SSMR3PutU32(pSSM, pContext->glsl.activeProgram?pContext->glsl.activeProgram->id:0);
1762 AssertRCReturn(rc, rc);
1763#endif
1764
1765 return VINF_SUCCESS;
1766}
1767
1768typedef struct _crFindSharedCtxParms {
1769 PFNCRSTATE_CONTEXT_GET pfnCtxGet;
1770 CRContext *pSrcCtx, *pDstCtx;
1771} crFindSharedCtxParms_t;
1772
1773static void crStateFindSharedCB(unsigned long key, void *data1, void *data2)
1774{
1775 crFindSharedCtxParms_t *pParms = (crFindSharedCtxParms_t *) data2;
1776 CRContext *pContext = pParms->pfnCtxGet(data1);
1777 (void) key;
1778
1779 if (pContext!=pParms->pSrcCtx && pContext->shared->id==pParms->pSrcCtx->shared->id)
1780 {
1781 pParms->pDstCtx->shared = pContext->shared;
1782 }
1783}
1784
1785int32_t crStateSaveGlobals(PSSMHANDLE pSSM)
1786{
1787 /* don't need that for now */
1788#if 0
1789 CRStateBits *pBits;
1790 int rc;
1791
1792 CRASSERT(g_cContexts >= 1);
1793 if (g_cContexts <= 1)
1794 return VINF_SUCCESS;
1795
1796 pBits = GetCurrentBits();
1797#define CRSTATE_BITS_OP(_var, _size) \
1798 rc = SSMR3PutMem(pSSM, (pBits->_var), _size); \
1799 AssertRCReturn(rc, rc);
1800#include "state_bits_globalop.h"
1801#undef CRSTATE_BITS_OP
1802#endif
1803 return VINF_SUCCESS;
1804}
1805
1806int32_t crStateLoadGlobals(PSSMHANDLE pSSM, uint32_t u32Version)
1807{
1808 CRStateBits *pBits;
1809 int rc;
1810 CRASSERT(g_cContexts >= 1);
1811 if (g_cContexts <= 1)
1812 return VINF_SUCCESS;
1813
1814 pBits = GetCurrentBits();
1815
1816 if (u32Version >= SHCROGL_SSM_VERSION_WITH_STATE_BITS)
1817 {
1818#define CRSTATE_BITS_OP(_var, _size) \
1819 rc = SSMR3GetMem(pSSM, (pBits->_var), _size); \
1820 AssertRCReturn(rc, rc);
1821
1822 if (u32Version < SHCROGL_SSM_VERSION_WITH_FIXED_STENCIL)
1823 {
1824#define CRSTATE_BITS_OP_VERSION (SHCROGL_SSM_VERSION_WITH_FIXED_STENCIL - 1)
1825#define CRSTATE_BITS_OP_STENCIL_FUNC_V_33(_i, _var) do {} while (0)
1826#define CRSTATE_BITS_OP_STENCIL_OP_V_33(_i, _var) do {} while (0)
1827#include "state_bits_globalop.h"
1828#undef CRSTATE_BITS_OP_VERSION
1829#undef CRSTATE_BITS_OP_STENCIL_FUNC_V_33
1830#undef CRSTATE_BITS_OP_STENCIL_OP_V_33
1831 }
1832 else if (u32Version < SHCROGL_SSM_VERSION_WITH_SPRITE_COORD_ORIGIN)
1833 {
1834#define CRSTATE_BITS_OP_VERSION (SHCROGL_SSM_VERSION_WITH_SPRITE_COORD_ORIGIN - 1)
1835#include "state_bits_globalop.h"
1836#undef CRSTATE_BITS_OP_VERSION
1837 }
1838 else
1839 {
1840 /* we do not put dirty bits to state anymore,
1841 * nop */
1842//#include "state_bits_globalop.h"
1843 }
1844#undef CRSTATE_BITS_OP
1845 /* always dirty all bits */
1846 /* return VINF_SUCCESS; */
1847 }
1848
1849#define CRSTATE_BITS_OP(_var, _size) FILLDIRTY(pBits->_var);
1850#include "state_bits_globalop.h"
1851#undef CRSTATE_BITS_OP
1852 return VINF_SUCCESS;
1853}
1854
1855
1856#define SLC_COPYPTR(ptr) pTmpContext->ptr = pContext->ptr
1857#define SLC_ASSSERT_NULL_PTR(ptr) CRASSERT(!pContext->ptr)
1858
1859AssertCompile(VBOXTLSREFDATA_SIZE() <= CR_MAX_BITARRAY);
1860AssertCompile(VBOXTLSREFDATA_STATE_INITIALIZED != 0);
1861AssertCompile(RTASSERT_OFFSET_OF(CRContext, shared) >= VBOXTLSREFDATA_ASSERT_OFFSET(CRContext)
1862 + VBOXTLSREFDATA_SIZE()
1863 + RT_SIZEOFMEMB(CRContext, bitid)
1864 + RT_SIZEOFMEMB(CRContext, neg_bitid));
1865
1866int32_t crStateLoadContext(CRContext *pContext, CRHashTable * pCtxTable, PFNCRSTATE_CONTEXT_GET pfnCtxGet, PSSMHANDLE pSSM, uint32_t u32Version)
1867{
1868 CRContext* pTmpContext;
1869 int32_t rc, i, j;
1870 uint32_t uiNumElems, ui, k;
1871 unsigned long key;
1872 GLboolean bLoadShared = GL_TRUE;
1873 GLenum err;
1874
1875 CRASSERT(pContext && pSSM);
1876
1877 /* This one is rather big for stack allocation and causes macs to crash */
1878 pTmpContext = (CRContext*)crAlloc(sizeof(*pTmpContext));
1879 if (!pTmpContext)
1880 return VERR_NO_MEMORY;
1881
1882 CRASSERT(VBoxTlsRefIsFunctional(pContext));
1883
1884 if (u32Version <= SHCROGL_SSM_VERSION_WITH_INVALID_ERROR_STATE)
1885 {
1886 union {
1887 CRbitvalue bitid[CR_MAX_BITARRAY];
1888 struct {
1889 VBOXTLSREFDATA
1890 } tlsRef;
1891 } bitid;
1892
1893 /* do not increment the saved state version due to VBOXTLSREFDATA addition to CRContext */
1894 rc = SSMR3GetMem(pSSM, pTmpContext, VBOXTLSREFDATA_OFFSET(CRContext));
1895 AssertRCReturn(rc, rc);
1896
1897 /* VBox 4.1.8 had a bug that VBOXTLSREFDATA was also stored in the snapshot,
1898 * thus the saved state data format was changed w/o changing the saved state version.
1899 * here we determine whether the saved state contains VBOXTLSREFDATA, and if so, treat it accordingly */
1900 rc = SSMR3GetMem(pSSM, &bitid, sizeof (bitid));
1901 AssertRCReturn(rc, rc);
1902
1903 /* the bitid array has one bit set only. this is why if bitid.tlsRef has both cTlsRefs
1904 * and enmTlsRefState non-zero - this is definitely NOT a bit id and is a VBOXTLSREFDATA */
1905 if (bitid.tlsRef.enmTlsRefState == VBOXTLSREFDATA_STATE_INITIALIZED
1906 && bitid.tlsRef.cTlsRefs)
1907 {
1908 /* VBOXTLSREFDATA is stored, skip it */
1909 crMemcpy(&pTmpContext->bitid, ((uint8_t*)&bitid) + VBOXTLSREFDATA_SIZE(), sizeof (bitid) - VBOXTLSREFDATA_SIZE());
1910 rc = SSMR3GetMem(pSSM, ((uint8_t*)&pTmpContext->bitid) + sizeof (pTmpContext->bitid) - VBOXTLSREFDATA_SIZE(), sizeof (pTmpContext->neg_bitid) + VBOXTLSREFDATA_SIZE());
1911 AssertRCReturn(rc, rc);
1912
1913 ui = VBOXTLSREFDATA_OFFSET(CRContext) + VBOXTLSREFDATA_SIZE() + sizeof (pTmpContext->bitid) + sizeof (pTmpContext->neg_bitid);
1914 ui = RT_UOFFSETOF(CRContext, shared) - ui;
1915 }
1916 else
1917 {
1918 /* VBOXTLSREFDATA is NOT stored */
1919 crMemcpy(&pTmpContext->bitid, &bitid, sizeof (bitid));
1920 rc = SSMR3GetMem(pSSM, &pTmpContext->neg_bitid, sizeof (pTmpContext->neg_bitid));
1921 AssertRCReturn(rc, rc);
1922
1923 /* the pre-VBOXTLSREFDATA CRContext structure might have additional allignment bits before the CRContext::shared */
1924 ui = VBOXTLSREFDATA_OFFSET(CRContext) + sizeof (pTmpContext->bitid) + sizeof (pTmpContext->neg_bitid);
1925
1926 ui &= (sizeof (void*) - 1);
1927 }
1928
1929 if (ui)
1930 {
1931 void* pTmp = NULL;
1932 rc = SSMR3GetMem(pSSM, &pTmp, ui);
1933 AssertRCReturn(rc, rc);
1934 }
1935
1936 if (u32Version == SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS)
1937 {
1938 SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, shared, attrib);
1939 rc = crStateLoadAttribState_v_BEFORE_CTXUSAGE_BITS(&pTmpContext->attrib, pSSM);
1940 AssertRCReturn(rc, rc);
1941 SHCROGL_CUT_FIELD_ALIGNMENT(CRContext, attrib, buffer);
1942 SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, buffer, point);
1943 rc = crStateLoadStencilPoint_v_37(&pTmpContext->point, pSSM);
1944 AssertRCReturn(rc, rc);
1945 SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, polygon, stencil);
1946 rc = crStateLoadStencilState_v_33(&pTmpContext->stencil, pSSM);
1947 AssertRCReturn(rc, rc);
1948 SHCROGL_CUT_FOR_OLD_TYPE_TO_ENSURE_ALIGNMENT(CRContext, stencil, CRStencilState_v_33, sizeof (void*));
1949 rc = crStateLoadTextureState_v_BEFORE_CTXUSAGE_BITS(&pTmpContext->texture, pSSM);
1950 AssertRCReturn(rc, rc);
1951 SHCROGL_CUT_FIELD_ALIGNMENT(CRContext, texture, transform);
1952 SHCROGL_GET_STRUCT_TAIL(pTmpContext, CRContext, transform);
1953 }
1954 else
1955 {
1956 SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, shared, attrib);
1957 rc = crStateLoadAttribState_v_33(&pTmpContext->attrib, pSSM);
1958 AssertRCReturn(rc, rc);
1959 SHCROGL_CUT_FIELD_ALIGNMENT(CRContext, attrib, buffer);
1960 SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, buffer, point);
1961 rc = crStateLoadStencilPoint_v_37(&pTmpContext->point, pSSM);
1962 AssertRCReturn(rc, rc);
1963 SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, polygon, stencil);
1964 rc = crStateLoadStencilState_v_33(&pTmpContext->stencil, pSSM);
1965 AssertRCReturn(rc, rc);
1966 SHCROGL_CUT_FOR_OLD_TYPE_TO_ENSURE_ALIGNMENT(CRContext, stencil, CRStencilState_v_33, sizeof (void*));
1967 SHCROGL_GET_STRUCT_TAIL(pTmpContext, CRContext, texture);
1968 }
1969
1970 pTmpContext->error = GL_NO_ERROR; /* <- the error state contained some random error data here
1971 * treat as no error */
1972 }
1973 else if (u32Version < SHCROGL_SSM_VERSION_WITH_FIXED_STENCIL)
1974 {
1975 SHCROGL_GET_STRUCT_HEAD(pTmpContext, CRContext, attrib);
1976 rc = crStateLoadAttribState_v_33(&pTmpContext->attrib, pSSM);
1977 AssertRCReturn(rc, rc);
1978 SHCROGL_CUT_FIELD_ALIGNMENT(CRContext, attrib, buffer);
1979 SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, buffer, point);
1980 rc = crStateLoadStencilPoint_v_37(&pTmpContext->point, pSSM);
1981 AssertRCReturn(rc, rc);
1982 SHCROGL_GET_STRUCT_PART(pTmpContext, CRContext, polygon, stencil);
1983 rc = crStateLoadStencilState_v_33(&pTmpContext->stencil, pSSM);
1984 AssertRCReturn(rc, rc);
1985 SHCROGL_CUT_FOR_OLD_TYPE_TO_ENSURE_ALIGNMENT(CRContext, stencil, CRStencilState_v_33, sizeof (void*));
1986 SHCROGL_GET_STRUCT_TAIL(pTmpContext, CRContext, texture);
1987 }
1988 else if (u32Version < SHCROGL_SSM_VERSION_WITH_SPRITE_COORD_ORIGIN)
1989 {
1990 SHCROGL_GET_STRUCT_HEAD(pTmpContext, CRContext, point);
1991 crStateLoadStencilPoint_v_37(&pTmpContext->point, pSSM);
1992 SHCROGL_GET_STRUCT_TAIL(pTmpContext, CRContext, polygon);
1993 }
1994 else
1995 {
1996 rc = SSMR3GetMem(pSSM, pTmpContext, sizeof (*pTmpContext));
1997 AssertRCReturn(rc, rc);
1998 }
1999
2000 /* preserve the error to restore it at the end of context creation,
2001 * it should not normally change, but just in case it it changed */
2002 err = pTmpContext->error;
2003
2004 /* we will later do crMemcpy from entire pTmpContext to pContext,
2005 * for simplicity store the VBOXTLSREFDATA from the pContext to pTmpContext */
2006 VBOXTLSREFDATA_COPY(pTmpContext, pContext);
2007
2008 /* Deal with shared state */
2009 {
2010 crFindSharedCtxParms_t parms;
2011 int32_t shared;
2012
2013 rc = SSMR3GetS32(pSSM, &pContext->shared->id);
2014 AssertRCReturn(rc, rc);
2015
2016 rc = SSMR3GetS32(pSSM, &shared);
2017 AssertRCReturn(rc, rc);
2018
2019 pTmpContext->shared = NULL;
2020 parms.pfnCtxGet = pfnCtxGet;
2021 parms.pSrcCtx = pContext;
2022 parms.pDstCtx = pTmpContext;
2023 crHashtableWalk(pCtxTable, crStateFindSharedCB, &parms);
2024
2025 if (pTmpContext->shared)
2026 {
2027 CRASSERT(pContext->shared->refCount==1);
2028 bLoadShared = GL_FALSE;
2029 crStateFreeShared(pContext, pContext->shared);
2030 pContext->shared = NULL;
2031 pTmpContext->shared->refCount++;
2032 }
2033 else
2034 {
2035 SLC_COPYPTR(shared);
2036 }
2037
2038 if (bLoadShared && shared)
2039 {
2040 crStateSetSharedContext(pTmpContext);
2041 }
2042 }
2043
2044 SLC_COPYPTR(flush_func);
2045 SLC_COPYPTR(flush_arg);
2046
2047 /* We're supposed to be loading into an empty context, so those pointers should be NULL */
2048 for ( i = 0 ; i < CR_MAX_ATTRIB_STACK_DEPTH ; i++)
2049 {
2050 SLC_ASSSERT_NULL_PTR(attrib.enableStack[i].clip);
2051 SLC_ASSSERT_NULL_PTR(attrib.enableStack[i].light);
2052
2053 SLC_ASSSERT_NULL_PTR(attrib.lightingStack[i].light);
2054 SLC_ASSSERT_NULL_PTR(attrib.transformStack[i].clip);
2055 SLC_ASSSERT_NULL_PTR(attrib.transformStack[i].clipPlane);
2056
2057 for (j=0; j<GLEVAL_TOT; ++j)
2058 {
2059 SLC_ASSSERT_NULL_PTR(attrib.evalStack[i].eval1D[j].coeff);
2060 SLC_ASSSERT_NULL_PTR(attrib.evalStack[i].eval2D[j].coeff);
2061 }
2062 }
2063
2064#ifdef CR_ARB_vertex_buffer_object
2065 SLC_COPYPTR(bufferobject.nullBuffer);
2066#endif
2067
2068/*@todo, that should be removed probably as those should hold the offset values, so loading should be fine
2069 but better check*/
2070#if 0
2071#ifdef CR_EXT_compiled_vertex_array
2072 SLC_COPYPTR(client.array.v.prevPtr);
2073 SLC_COPYPTR(client.array.c.prevPtr);
2074 SLC_COPYPTR(client.array.f.prevPtr);
2075 SLC_COPYPTR(client.array.s.prevPtr);
2076 SLC_COPYPTR(client.array.e.prevPtr);
2077 SLC_COPYPTR(client.array.i.prevPtr);
2078 SLC_COPYPTR(client.array.n.prevPtr);
2079 for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
2080 {
2081 SLC_COPYPTR(client.array.t[i].prevPtr);
2082 }
2083
2084# ifdef CR_NV_vertex_program
2085 for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++)
2086 {
2087 SLC_COPYPTR(client.array.a[i].prevPtr);
2088 }
2089# endif
2090#endif
2091#endif
2092
2093#ifdef CR_ARB_vertex_buffer_object
2094 /*That just sets those pointers to NULL*/
2095 SLC_COPYPTR(client.array.v.buffer);
2096 SLC_COPYPTR(client.array.c.buffer);
2097 SLC_COPYPTR(client.array.f.buffer);
2098 SLC_COPYPTR(client.array.s.buffer);
2099 SLC_COPYPTR(client.array.e.buffer);
2100 SLC_COPYPTR(client.array.i.buffer);
2101 SLC_COPYPTR(client.array.n.buffer);
2102 for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
2103 {
2104 SLC_COPYPTR(client.array.t[i].buffer);
2105 }
2106# ifdef CR_NV_vertex_program
2107 for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++)
2108 {
2109 SLC_COPYPTR(client.array.a[i].buffer);
2110 }
2111# endif
2112#endif /*CR_ARB_vertex_buffer_object*/
2113
2114 /** @todo CR_NV_vertex_program*/
2115 crStateCopyEvalPtrs1D(pTmpContext->eval.eval1D, pContext->eval.eval1D);
2116 crStateCopyEvalPtrs2D(pTmpContext->eval.eval2D, pContext->eval.eval2D);
2117
2118 SLC_COPYPTR(feedback.buffer); /** @todo */
2119 SLC_COPYPTR(selection.buffer); /** @todo */
2120
2121 SLC_COPYPTR(lighting.light);
2122
2123 /*This one could be tricky if we're loading snapshot on host with different GPU*/
2124 SLC_COPYPTR(limits.extensions);
2125
2126#if CR_ARB_occlusion_query
2127 SLC_COPYPTR(occlusion.objects); /** @todo */
2128#endif
2129
2130 SLC_COPYPTR(program.errorString);
2131 SLC_COPYPTR(program.programHash);
2132 SLC_COPYPTR(program.defaultVertexProgram);
2133 SLC_COPYPTR(program.defaultFragmentProgram);
2134
2135 /* Texture pointers */
2136 for (i=0; i<6; ++i)
2137 {
2138 SLC_COPYPTR(texture.base1D.level[i]);
2139 SLC_COPYPTR(texture.base2D.level[i]);
2140 SLC_COPYPTR(texture.base3D.level[i]);
2141 SLC_COPYPTR(texture.proxy1D.level[i]);
2142 SLC_COPYPTR(texture.proxy2D.level[i]);
2143 SLC_COPYPTR(texture.proxy3D.level[i]);
2144#ifdef CR_ARB_texture_cube_map
2145 SLC_COPYPTR(texture.baseCubeMap.level[i]);
2146 SLC_COPYPTR(texture.proxyCubeMap.level[i]);
2147#endif
2148#ifdef CR_NV_texture_rectangle
2149 SLC_COPYPTR(texture.baseRect.level[i]);
2150 SLC_COPYPTR(texture.proxyRect.level[i]);
2151#endif
2152 }
2153
2154 /* Load transform state */
2155 SLC_COPYPTR(transform.clipPlane);
2156 SLC_COPYPTR(transform.clip);
2157 /* Don't have to worry about pContext->transform.current as it'd be set in crStateSetCurrent call */
2158 /*SLC_COPYPTR(transform.currentStack);*/
2159 SLC_COPYPTR(transform.modelViewStack.stack);
2160 SLC_COPYPTR(transform.projectionStack.stack);
2161 SLC_COPYPTR(transform.colorStack.stack);
2162
2163 for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
2164 {
2165 SLC_COPYPTR(transform.textureStack[i].stack);
2166 }
2167 for (i = 0 ; i < CR_MAX_PROGRAM_MATRICES ; i++)
2168 {
2169 SLC_COPYPTR(transform.programStack[i].stack);
2170 }
2171
2172#ifdef CR_OPENGL_VERSION_2_0
2173 SLC_COPYPTR(glsl.shaders);
2174 SLC_COPYPTR(glsl.programs);
2175#endif
2176
2177 /* Have to preserve original context id */
2178 CRASSERT(pTmpContext->id == pContext->id);
2179 CRASSERT(VBOXTLSREFDATA_EQUAL(pContext, pTmpContext));
2180 /* Copy ordinary state to real context */
2181 crMemcpy(pContext, pTmpContext, sizeof(*pTmpContext));
2182 crFree(pTmpContext);
2183 pTmpContext = NULL;
2184
2185 /* Now deal with pointers */
2186
2187 /* Load transform state */
2188 rc = SSMR3GetMem(pSSM, pContext->transform.clipPlane, sizeof(GLvectord)*CR_MAX_CLIP_PLANES);
2189 AssertRCReturn(rc, rc);
2190 rc = SSMR3GetMem(pSSM, pContext->transform.clip, sizeof(GLboolean)*CR_MAX_CLIP_PLANES);
2191 AssertRCReturn(rc, rc);
2192 rc = crStateLoadMatrixStack(&pContext->transform.modelViewStack, pSSM);
2193 AssertRCReturn(rc, rc);
2194 rc = crStateLoadMatrixStack(&pContext->transform.projectionStack, pSSM);
2195 AssertRCReturn(rc, rc);
2196 rc = crStateLoadMatrixStack(&pContext->transform.colorStack, pSSM);
2197 AssertRCReturn(rc, rc);
2198 for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
2199 {
2200 rc = crStateLoadMatrixStack(&pContext->transform.textureStack[i], pSSM);
2201 AssertRCReturn(rc, rc);
2202 }
2203 for (i = 0 ; i < CR_MAX_PROGRAM_MATRICES ; i++)
2204 {
2205 rc = crStateLoadMatrixStack(&pContext->transform.programStack[i], pSSM);
2206 AssertRCReturn(rc, rc);
2207 }
2208
2209 /* Load Textures */
2210 rc = crStateLoadTextureObjData(&pContext->texture.base1D, pSSM);
2211 AssertRCReturn(rc, rc);
2212 rc = crStateLoadTextureObjData(&pContext->texture.base2D, pSSM);
2213 AssertRCReturn(rc, rc);
2214 rc = crStateLoadTextureObjData(&pContext->texture.base3D, pSSM);
2215 AssertRCReturn(rc, rc);
2216 rc = crStateLoadTextureObjData(&pContext->texture.proxy1D, pSSM);
2217 AssertRCReturn(rc, rc);
2218 rc = crStateLoadTextureObjData(&pContext->texture.proxy2D, pSSM);
2219 AssertRCReturn(rc, rc);
2220 rc = crStateLoadTextureObjData(&pContext->texture.proxy3D, pSSM);
2221 AssertRCReturn(rc, rc);
2222#ifdef CR_ARB_texture_cube_map
2223 rc = crStateLoadTextureObjData(&pContext->texture.baseCubeMap, pSSM);
2224 AssertRCReturn(rc, rc);
2225 rc = crStateLoadTextureObjData(&pContext->texture.proxyCubeMap, pSSM);
2226 AssertRCReturn(rc, rc);
2227#endif
2228#ifdef CR_NV_texture_rectangle
2229 rc = crStateLoadTextureObjData(&pContext->texture.baseRect, pSSM);
2230 AssertRCReturn(rc, rc);
2231 rc = crStateLoadTextureObjData(&pContext->texture.proxyRect, pSSM);
2232 AssertRCReturn(rc, rc);
2233#endif
2234
2235 if (bLoadShared)
2236 {
2237 /* Load shared textures */
2238 CRASSERT(pContext->shared && pContext->shared->textureTable);
2239
2240 if (u32Version >= SHCROGL_SSM_VERSION_WITH_ALLOCATED_KEYS)
2241 {
2242 rc = crStateLoadKeys(pContext->shared->buffersTable, pSSM, u32Version);
2243 AssertRCReturn(rc, rc);
2244 }
2245
2246 rc = SSMR3GetU32(pSSM, &uiNumElems);
2247 AssertRCReturn(rc, rc);
2248 for (ui=0; ui<uiNumElems; ++ui)
2249 {
2250 CRTextureObj *pTexture;
2251
2252 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
2253 AssertRCReturn(rc, rc);
2254
2255 pTexture = (CRTextureObj *) crCalloc(sizeof(CRTextureObj));
2256 if (!pTexture) return VERR_NO_MEMORY;
2257
2258 rc = crStateLoadTextureObj(pTexture, pSSM, u32Version);
2259 AssertRCReturn(rc, rc);
2260
2261 pTexture->hwid = 0;
2262
2263 /*allocate actual memory*/
2264 for (i=0; i<6; ++i) {
2265 pTexture->level[i] = (CRTextureLevel *) crCalloc(sizeof(CRTextureLevel) * CR_MAX_MIPMAP_LEVELS);
2266 if (!pTexture->level[i]) return VERR_NO_MEMORY;
2267 }
2268
2269 rc = crStateLoadTextureObjData(pTexture, pSSM);
2270 AssertRCReturn(rc, rc);
2271
2272 crHashtableAdd(pContext->shared->textureTable, key, pTexture);
2273 }
2274 }
2275
2276 /* Load current texture pointers */
2277 for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i)
2278 {
2279 rc = crStateLoadTexUnitCurrentTexturePtrs(&pContext->texture.unit[i], pContext, pSSM);
2280 AssertRCReturn(rc, rc);
2281 }
2282
2283 /* Mark textures for resending to GPU */
2284 pContext->shared->bTexResyncNeeded = GL_TRUE;
2285
2286 /* Load lights */
2287 CRASSERT(pContext->lighting.light);
2288 rc = SSMR3GetMem(pSSM, pContext->lighting.light, CR_MAX_LIGHTS * sizeof(*pContext->lighting.light));
2289 AssertRCReturn(rc, rc);
2290
2291 /* Load attrib stack*/
2292 for ( i = 0 ; i < CR_MAX_ATTRIB_STACK_DEPTH ; i++)
2293 {
2294 if (pContext->attrib.enableStack[i].clip)
2295 {
2296 rc = crStateAllocAndSSMR3GetMem(pSSM, (void**)&pContext->attrib.enableStack[i].clip,
2297 pContext->limits.maxClipPlanes*sizeof(GLboolean));
2298 AssertRCReturn(rc, rc);
2299 }
2300
2301 if (pContext->attrib.enableStack[i].light)
2302 {
2303 rc = crStateAllocAndSSMR3GetMem(pSSM, (void**)&pContext->attrib.enableStack[i].light,
2304 pContext->limits.maxLights*sizeof(GLboolean));
2305 AssertRCReturn(rc, rc);
2306 }
2307
2308 if (pContext->attrib.lightingStack[i].light)
2309 {
2310 rc = crStateAllocAndSSMR3GetMem(pSSM, (void**)&pContext->attrib.lightingStack[i].light,
2311 pContext->limits.maxLights*sizeof(CRLight));
2312 AssertRCReturn(rc, rc);
2313 }
2314
2315 for (k=0; k<pContext->limits.maxTextureUnits; ++k)
2316 {
2317 rc = crStateLoadTexUnitCurrentTexturePtrs(&pContext->attrib.textureStack[i].unit[k], pContext, pSSM);
2318 AssertRCReturn(rc, rc);
2319 }
2320
2321 if (pContext->attrib.transformStack[i].clip)
2322 {
2323 rc = crStateAllocAndSSMR3GetMem(pSSM, (void*)&pContext->attrib.transformStack[i].clip,
2324 pContext->limits.maxClipPlanes*sizeof(GLboolean));
2325 AssertRCReturn(rc, rc);
2326 }
2327
2328 if (pContext->attrib.transformStack[i].clipPlane)
2329 {
2330 rc = crStateAllocAndSSMR3GetMem(pSSM, (void**)&pContext->attrib.transformStack[i].clipPlane,
2331 pContext->limits.maxClipPlanes*sizeof(GLvectord));
2332 AssertRCReturn(rc, rc);
2333 }
2334 rc = crSateLoadEvalCoeffs1D(pContext->attrib.evalStack[i].eval1D, GL_TRUE, pSSM);
2335 AssertRCReturn(rc, rc);
2336 rc = crSateLoadEvalCoeffs2D(pContext->attrib.evalStack[i].eval2D, GL_TRUE, pSSM);
2337 AssertRCReturn(rc, rc);
2338 }
2339
2340 /* Load evaluator coeffs */
2341 rc = crSateLoadEvalCoeffs1D(pContext->eval.eval1D, GL_FALSE, pSSM);
2342 AssertRCReturn(rc, rc);
2343 rc = crSateLoadEvalCoeffs2D(pContext->eval.eval2D, GL_FALSE, pSSM);
2344 AssertRCReturn(rc, rc);
2345
2346 /* Load buffer objects */
2347#ifdef CR_ARB_vertex_buffer_object
2348 if (bLoadShared)
2349 {
2350 if (u32Version >= SHCROGL_SSM_VERSION_WITH_ALLOCATED_KEYS)
2351 {
2352 rc = crStateLoadKeys(pContext->shared->textureTable, pSSM, u32Version);
2353 AssertRCReturn(rc, rc);
2354 }
2355 }
2356
2357 rc = SSMR3GetU32(pSSM, &uiNumElems);
2358 AssertRCReturn(rc, rc);
2359 for (ui=0; ui<=uiNumElems; ++ui) /*ui<=uiNumElems to load nullBuffer in same loop*/
2360 {
2361 CRBufferObject *pBufferObj;
2362
2363 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
2364 AssertRCReturn(rc, rc);
2365
2366 /* default one should be already allocated */
2367 if (key==0)
2368 {
2369 pBufferObj = pContext->bufferobject.nullBuffer;
2370 if (!pBufferObj) return VERR_SSM_UNEXPECTED_DATA;
2371 }
2372 else
2373 {
2374 pBufferObj = (CRBufferObject *) crCalloc(sizeof(*pBufferObj));
2375 if (!pBufferObj) return VERR_NO_MEMORY;
2376 }
2377
2378 rc = crStateLoadBufferObject(pBufferObj, pSSM, u32Version);
2379 AssertRCReturn(rc, rc);
2380
2381 pBufferObj->hwid = 0;
2382
2383 if (pBufferObj->data)
2384 {
2385 CRASSERT(pBufferObj->size>0);
2386 pBufferObj->data = crAlloc(pBufferObj->size);
2387 rc = SSMR3GetMem(pSSM, pBufferObj->data, pBufferObj->size);
2388 AssertRCReturn(rc, rc);
2389 }
2390 else if (pBufferObj->id!=0 && pBufferObj->size>0)
2391 {
2392 rc = SSMR3GetMem(pSSM, &pBufferObj->data, sizeof(pBufferObj->data));
2393 AssertRCReturn(rc, rc);
2394
2395 if (pBufferObj->data)
2396 {
2397 pBufferObj->data = crAlloc(pBufferObj->size);
2398 rc = SSMR3GetMem(pSSM, pBufferObj->data, pBufferObj->size);
2399 AssertRCReturn(rc, rc);
2400 }
2401 }
2402
2403
2404 if (key!=0)
2405 crHashtableAdd(pContext->shared->buffersTable, key, pBufferObj);
2406 }
2407 /* Load pointers */
2408#define CRS_GET_BO(name) (((name)==0) ? (pContext->bufferobject.nullBuffer) : crHashtableSearch(pContext->shared->buffersTable, name))
2409 rc = SSMR3GetU32(pSSM, &ui);
2410 AssertRCReturn(rc, rc);
2411 pContext->bufferobject.arrayBuffer = CRS_GET_BO(ui);
2412 rc = SSMR3GetU32(pSSM, &ui);
2413 AssertRCReturn(rc, rc);
2414 pContext->bufferobject.elementsBuffer = CRS_GET_BO(ui);
2415#ifdef CR_ARB_pixel_buffer_object
2416 rc = SSMR3GetU32(pSSM, &ui);
2417 AssertRCReturn(rc, rc);
2418 pContext->bufferobject.packBuffer = CRS_GET_BO(ui);
2419 rc = SSMR3GetU32(pSSM, &ui);
2420 AssertRCReturn(rc, rc);
2421 pContext->bufferobject.unpackBuffer = CRS_GET_BO(ui);
2422#endif
2423#undef CRS_GET_BO
2424
2425 /* Load client pointers and array buffer bindings*/
2426 for (i=0; i<CRSTATECLIENT_MAX_VERTEXARRAYS; ++i)
2427 {
2428 rc = crStateLoadClientPointer(&pContext->client.array, i, pContext, pSSM);
2429 AssertRCReturn(rc, rc);
2430 }
2431 for (j=0; j<pContext->client.vertexArrayStackDepth; ++j)
2432 {
2433 CRVertexArrays *pArray = &pContext->client.vertexArrayStack[j];
2434 for (i=0; i<CRSTATECLIENT_MAX_VERTEXARRAYS; ++i)
2435 {
2436 rc = crStateLoadClientPointer(pArray, i, pContext, pSSM);
2437 AssertRCReturn(rc, rc);
2438 }
2439 }
2440
2441 pContext->shared->bVBOResyncNeeded = GL_TRUE;
2442#endif
2443
2444 /* Load pixel/vertex programs */
2445 rc = SSMR3GetU32(pSSM, &uiNumElems);
2446 AssertRCReturn(rc, rc);
2447 /* Load defaults programs */
2448 rc = crStateLoadProgram(&pContext->program.defaultVertexProgram, pSSM);
2449 AssertRCReturn(rc, rc);
2450 rc = crStateLoadProgram(&pContext->program.defaultFragmentProgram, pSSM);
2451 AssertRCReturn(rc, rc);
2452 /* Load all the rest */
2453 for (ui=0; ui<uiNumElems; ++ui)
2454 {
2455 CRProgram *pProgram = NULL;
2456 rc = crStateLoadProgram(&pProgram, pSSM);
2457 AssertRCReturn(rc, rc);
2458 crHashtableAdd(pContext->program.programHash, pProgram->id, pProgram);
2459 //DIRTY(pProgram->dirtyProgram, pContext->neg_bitid);
2460
2461 }
2462 /* Load Pointers */
2463 rc = SSMR3GetU32(pSSM, &ui);
2464 AssertRCReturn(rc, rc);
2465 pContext->program.currentVertexProgram = ui==0 ? pContext->program.defaultVertexProgram
2466 : crHashtableSearch(pContext->program.programHash, ui);
2467 rc = SSMR3GetU32(pSSM, &ui);
2468 AssertRCReturn(rc, rc);
2469 pContext->program.currentFragmentProgram = ui==0 ? pContext->program.defaultFragmentProgram
2470 : crHashtableSearch(pContext->program.programHash, ui);
2471
2472 /* Mark programs for resending to GPU */
2473 pContext->program.bResyncNeeded = GL_TRUE;
2474
2475#ifdef CR_EXT_framebuffer_object
2476 /* Load FBOs */
2477 if (bLoadShared)
2478 {
2479 if (u32Version >= SHCROGL_SSM_VERSION_WITH_ALLOCATED_KEYS)
2480 {
2481 rc = crStateLoadKeys(pContext->shared->fbTable, pSSM, u32Version);
2482 AssertRCReturn(rc, rc);
2483 }
2484
2485 rc = SSMR3GetU32(pSSM, &uiNumElems);
2486 AssertRCReturn(rc, rc);
2487 for (ui=0; ui<uiNumElems; ++ui)
2488 {
2489 CRFramebufferObject *pFBO;
2490 pFBO = crAlloc(sizeof(*pFBO));
2491 if (!pFBO) return VERR_NO_MEMORY;
2492
2493 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
2494 AssertRCReturn(rc, rc);
2495
2496 rc = crStateLoadFramebufferObject(pFBO, pSSM, u32Version);
2497 AssertRCReturn(rc, rc);
2498
2499 Assert(key == pFBO->id);
2500
2501 crHashtableAdd(pContext->shared->fbTable, key, pFBO);
2502 }
2503
2504 if (u32Version >= SHCROGL_SSM_VERSION_WITH_ALLOCATED_KEYS)
2505 {
2506 rc = crStateLoadKeys(pContext->shared->rbTable, pSSM, u32Version);
2507 AssertRCReturn(rc, rc);
2508 }
2509
2510 rc = SSMR3GetU32(pSSM, &uiNumElems);
2511 AssertRCReturn(rc, rc);
2512 for (ui=0; ui<uiNumElems; ++ui)
2513 {
2514 CRRenderbufferObject *pRBO;
2515 pRBO = crAlloc(sizeof(*pRBO));
2516 if (!pRBO) return VERR_NO_MEMORY;
2517
2518 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
2519 AssertRCReturn(rc, rc);
2520
2521 rc = crStateLoadRenderbufferObject(pRBO, pSSM, u32Version);
2522 AssertRCReturn(rc, rc);
2523
2524 crHashtableAdd(pContext->shared->rbTable, key, pRBO);
2525 }
2526 }
2527
2528 rc = SSMR3GetU32(pSSM, &ui);
2529 AssertRCReturn(rc, rc);
2530 pContext->framebufferobject.drawFB = ui==0 ? NULL
2531 : crHashtableSearch(pContext->shared->fbTable, ui);
2532
2533 rc = SSMR3GetU32(pSSM, &ui);
2534 AssertRCReturn(rc, rc);
2535 pContext->framebufferobject.readFB = ui==0 ? NULL
2536 : crHashtableSearch(pContext->shared->fbTable, ui);
2537
2538 rc = SSMR3GetU32(pSSM, &ui);
2539 AssertRCReturn(rc, rc);
2540 pContext->framebufferobject.renderbuffer = ui==0 ? NULL
2541 : crHashtableSearch(pContext->shared->rbTable, ui);
2542
2543 /* Mark FBOs/RBOs for resending to GPU */
2544 pContext->shared->bFBOResyncNeeded = GL_TRUE;
2545#endif
2546
2547#ifdef CR_OPENGL_VERSION_2_0
2548 /* Load GLSL related info */
2549 rc = SSMR3GetU32(pSSM, &uiNumElems);
2550 AssertRCReturn(rc, rc);
2551
2552 for (ui=0; ui<uiNumElems; ++ui)
2553 {
2554 CRGLSLShader *pShader = crStateLoadGLSLShader(pSSM);
2555 GLboolean fNewKeyCheck;
2556 if (!pShader) return VERR_SSM_UNEXPECTED_DATA;
2557 fNewKeyCheck = crHashtableAllocRegisterKey(pContext->glsl.programs, pShader->id);
2558 CRASSERT(fNewKeyCheck);
2559 crHashtableAdd(pContext->glsl.shaders, pShader->id, pShader);
2560 }
2561
2562 rc = SSMR3GetU32(pSSM, &uiNumElems);
2563 AssertRCReturn(rc, rc);
2564
2565 for (ui=0; ui<uiNumElems; ++ui)
2566 {
2567 CRGLSLProgram *pProgram;
2568 uint32_t numShaders;
2569
2570 pProgram = crAlloc(sizeof(*pProgram));
2571 if (!pProgram) return VERR_NO_MEMORY;
2572
2573 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
2574 AssertRCReturn(rc, rc);
2575
2576 rc = SSMR3GetMem(pSSM, pProgram, sizeof(*pProgram));
2577 AssertRCReturn(rc, rc);
2578
2579 crHashtableAdd(pContext->glsl.programs, key, pProgram);
2580
2581 pProgram->currentState.attachedShaders = crAllocHashtable();
2582
2583 rc = SSMR3GetU32(pSSM, &numShaders);
2584 AssertRCReturn(rc, rc);
2585
2586 for (k=0; k<numShaders; ++k)
2587 {
2588 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
2589 AssertRCReturn(rc, rc);
2590 crHashtableAdd(pProgram->currentState.attachedShaders, key, crHashtableSearch(pContext->glsl.shaders, key));
2591 }
2592
2593 if (pProgram->activeState.attachedShaders)
2594 {
2595 pProgram->activeState.attachedShaders = crAllocHashtable();
2596
2597 rc = SSMR3GetU32(pSSM, &numShaders);
2598 AssertRCReturn(rc, rc);
2599
2600 for (k=0; k<numShaders; ++k)
2601 {
2602 CRGLSLShader *pShader = crStateLoadGLSLShader(pSSM);
2603 if (!pShader) return VERR_SSM_UNEXPECTED_DATA;
2604 crHashtableAdd(pProgram->activeState.attachedShaders, pShader->id, pShader);
2605 }
2606 }
2607
2608 if (pProgram->currentState.cAttribs)
2609 pProgram->currentState.pAttribs = (CRGLSLAttrib*) crAlloc(pProgram->currentState.cAttribs*sizeof(CRGLSLAttrib));
2610 for (k=0; k<pProgram->currentState.cAttribs; ++k)
2611 {
2612 rc = SSMR3GetMem(pSSM, &pProgram->currentState.pAttribs[k].index, sizeof(pProgram->currentState.pAttribs[k].index));
2613 AssertRCReturn(rc, rc);
2614 pProgram->currentState.pAttribs[k].name = crStateLoadString(pSSM);
2615 }
2616
2617 if (pProgram->activeState.cAttribs)
2618 pProgram->activeState.pAttribs = (CRGLSLAttrib*) crAlloc(pProgram->activeState.cAttribs*sizeof(CRGLSLAttrib));
2619 for (k=0; k<pProgram->activeState.cAttribs; ++k)
2620 {
2621 rc = SSMR3GetMem(pSSM, &pProgram->activeState.pAttribs[k].index, sizeof(pProgram->activeState.pAttribs[k].index));
2622 AssertRCReturn(rc, rc);
2623 pProgram->activeState.pAttribs[k].name = crStateLoadString(pSSM);
2624 }
2625
2626 {
2627 int32_t cUniforms;
2628 rc = SSMR3GetS32(pSSM, &cUniforms);
2629 pProgram->cUniforms = cUniforms;
2630 AssertRCReturn(rc, rc);
2631 }
2632
2633 if (pProgram->cUniforms)
2634 {
2635 pProgram->pUniforms = crAlloc(pProgram->cUniforms*sizeof(CRGLSLUniform));
2636 if (!pProgram->pUniforms) return VERR_NO_MEMORY;
2637
2638 for (k=0; k<pProgram->cUniforms; ++k)
2639 {
2640 size_t itemsize, datasize;
2641
2642 rc = SSMR3GetMem(pSSM, &pProgram->pUniforms[k].type, sizeof(GLenum));
2643 AssertRCReturn(rc, rc);
2644 pProgram->pUniforms[k].name = crStateLoadString(pSSM);
2645
2646 if (crStateIsIntUniform(pProgram->pUniforms[k].type))
2647 {
2648 itemsize = sizeof(GLint);
2649 } else itemsize = sizeof(GLfloat);
2650
2651 datasize = crStateGetUniformSize(pProgram->pUniforms[k].type)*itemsize;
2652 pProgram->pUniforms[k].data = crAlloc((unsigned int /* this case is just so stupid */)datasize);
2653 if (!pProgram->pUniforms[k].data) return VERR_NO_MEMORY;
2654
2655 rc = SSMR3GetMem(pSSM, pProgram->pUniforms[k].data, datasize);
2656 AssertRCReturn(rc, rc);
2657 }
2658 }
2659 }
2660
2661 rc = SSMR3GetU32(pSSM, &ui);
2662 AssertRCReturn(rc, rc);
2663 pContext->glsl.activeProgram = ui==0 ? NULL
2664 : crHashtableSearch(pContext->glsl.programs, ui);
2665
2666 /*Mark for resending to GPU*/
2667 pContext->glsl.bResyncNeeded = GL_TRUE;
2668#endif
2669
2670 if (pContext->error != err)
2671 {
2672 crWarning("context error state changed on context restore, was 0x%x, but became 0x%x, resetting to its original value",
2673 err, pContext->error);
2674 pContext->error = err;
2675 }
2676
2677 return VINF_SUCCESS;
2678}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette