VirtualBox

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

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

Additions/common/crOpengl,GuestHost/OpenGL,HostServices/SharedOpenGL: Eliminate all global variables from the state tracker library (state_tracker) in preparation of the SPU DLL merging, bugref:9435

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