VirtualBox

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

Last change on this file since 44937 was 44937, checked in by vboxsync, 12 years ago

crOpenGL: Fedora 18 saved state working, multiple saved state fixes, debugging stuff

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