VirtualBox

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

最後變更 在這個檔案從63199是 62814,由 vboxsync 提交於 9 年 前

GuestHost/OpenGL: warnings

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

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