VirtualBox

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

Last change on this file since 25216 was 25216, checked in by vboxsync, 15 years ago

crOpenGL: fix black screen after snapshots loading for apps using compiled vertex arrays

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 60.6 KB
Line 
1/* $Id: state_snapshot.c 25216 2009-12-07 16:42:26Z vboxsync $ */
2
3/** @file
4 * VBox Context state saving/loading used by VM snapshot
5 */
6
7/*
8 * Copyright (C) 2008 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
19 * Clara, CA 95054 USA or visit http://www.sun.com if you need
20 * additional information or have any questions.
21 */
22
23#include "state.h"
24#include "state/cr_statetypes.h"
25#include "state/cr_texture.h"
26#include "cr_mem.h"
27#include "cr_string.h"
28#include "cr_pixeldata.h"
29#include <stdio.h>
30
31#include <iprt/assert.h>
32#include <iprt/types.h>
33#include <iprt/err.h>
34#include <VBox/err.h>
35
36/* @todo
37 * We have two ways of saving/loading states.
38 *
39 * First which is being used atm, just pure saving/loading of structures.
40 * The drawback is we have to deal with all the pointers around those structures,
41 * we'd have to update this code if we'd change state tracking.
42 * On the bright side it's fast, though it's not really needed as it's not that often operation.
43 * It could also worth to split those functions into appropriate parts,
44 * similar to the way context creation is being done.
45 *
46 * Second way would be to implement full dispatch api table and substitute diff_api during saving/loading.
47 * Then if we implement that api in a similar way to packer/unpacker with a change to store/load
48 * via provided pSSM handle instead of pack buffer,
49 * saving state could be done by simple diffing against empty "dummy" context.
50 * Restoring state in such case would look like unpacking commands from pSSM instead of network buffer.
51 * This would be slower (who cares) but most likely will not require any code changes to support in future.
52 * We will reduce amount of saved data as we'd save only changed state parts, but I doubt it'd be that much.
53 * It could be done for the first way as well, but requires tons of bit checks.
54 */
55
56static int32_t crStateAllocAndSSMR3GetMem(PSSMHANDLE pSSM, void **pBuffer, size_t cbBuffer)
57{
58 CRASSERT(pSSM && pBuffer && cbBuffer>0);
59
60 *pBuffer = crAlloc(cbBuffer);
61 if (!*pBuffer)
62 return VERR_NO_MEMORY;
63
64 return SSMR3GetMem(pSSM, *pBuffer, cbBuffer);
65}
66
67static int32_t crStateSaveTextureObjData(CRTextureObj *pTexture, PSSMHANDLE pSSM)
68{
69 int32_t rc, face, i;
70 GLboolean bound = GL_FALSE;
71
72 CRASSERT(pTexture && pSSM);
73
74 crDebug("crStateSaveTextureObjData %u. START", pTexture->name);
75
76 for (face = 0; face < 6; face++) {
77 CRASSERT(pTexture->level[face]);
78
79 for (i = 0; i < CR_MAX_MIPMAP_LEVELS; i++) {
80 CRTextureLevel *ptl = &(pTexture->level[face][i]);
81 rc = SSMR3PutMem(pSSM, ptl, sizeof(*ptl));
82 AssertRCReturn(rc, rc);
83 if (ptl->img)
84 {
85 CRASSERT(ptl->bytes);
86 rc = SSMR3PutMem(pSSM, ptl->img, ptl->bytes);
87 AssertRCReturn(rc, rc);
88 }
89#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
90 /* Note, this is not a bug.
91 * Even with CR_STATE_NO_TEXTURE_IMAGE_STORE defined, it's possible that ptl->img!=NULL.
92 * For ex. we're saving snapshot right after it was loaded
93 * and some context hasn't been used by the guest application yet
94 * (pContext->texture.bResyncNeeded==GL_TRUE).
95 */
96 else if (ptl->bytes)
97 {
98 char *pImg;
99 GLenum target;
100
101 if (!bound)
102 {
103 diff_api.BindTexture(pTexture->target, pTexture->name);
104 bound = GL_TRUE;
105 }
106
107 if (pTexture->target!=GL_TEXTURE_CUBE_MAP_ARB)
108 {
109 target = pTexture->target;
110 }
111 else
112 {
113 target = GL_TEXTURE_CUBE_MAP_POSITIVE_X + face;
114 }
115
116#ifdef DEBUG
117 pImg = crAlloc(ptl->bytes+4);
118#else
119 pImg = crAlloc(ptl->bytes);
120#endif
121 if (!pImg) return VERR_NO_MEMORY;
122
123#ifdef DEBUG
124 {
125 GLint w,h=0;
126 *(int*)((char*)pImg+ptl->bytes) = 0xDEADDEAD;
127 crDebug("get image: compressed %i, face %i, level %i, width %i, height %i, bytes %i",
128 ptl->compressed, face, i, ptl->width, ptl->height, ptl->bytes);
129 diff_api.GetTexLevelParameteriv(target, i, GL_TEXTURE_WIDTH, &w);
130 diff_api.GetTexLevelParameteriv(target, i, GL_TEXTURE_HEIGHT, &h);
131 if (w!=ptl->width || h!=ptl->height)
132 {
133 crWarning("!!!tex size mismatch %i, %i!!!", w, h);
134 }
135 }
136#endif
137
138 /*@todo: ugly workaround for crashes inside ati driver,
139 * they overwrite their own allocated memory in cases where texlevel >=4
140 and width or height <=2.
141 */
142 if (i<4 || (ptl->width>2 && ptl->height>2))
143 if (!ptl->compressed)
144 {
145 diff_api.GetTexImage(target, i, ptl->format, ptl->type, pImg);
146 }
147 else
148 {
149 diff_api.GetCompressedTexImageARB(target, i, pImg);
150 }
151
152#ifdef DEBUG
153 if (*(int*)((char*)pImg+ptl->bytes) != 0xDEADDEAD)
154 {
155 crWarning("Texture is bigger than expected!!!");
156 }
157#endif
158
159 rc = SSMR3PutMem(pSSM, pImg, ptl->bytes);
160 crFree(pImg);
161 AssertRCReturn(rc, rc);
162 }
163#endif
164 }
165 }
166
167 crDebug("crStateSaveTextureObjData %u. END", pTexture->name);
168
169 return VINF_SUCCESS;
170}
171
172static int32_t crStateLoadTextureObjData(CRTextureObj *pTexture, PSSMHANDLE pSSM)
173{
174 int32_t rc, face, i;
175
176 CRASSERT(pTexture && pSSM);
177
178 for (face = 0; face < 6; face++) {
179 CRASSERT(pTexture->level[face]);
180
181 for (i = 0; i < CR_MAX_MIPMAP_LEVELS; i++) {
182 CRTextureLevel *ptl = &(pTexture->level[face][i]);
183 CRASSERT(!ptl->img);
184
185 rc = SSMR3GetMem(pSSM, ptl, sizeof(*ptl));
186 AssertRCReturn(rc, rc);
187 if (ptl->img)
188 {
189 CRASSERT(ptl->bytes);
190
191 ptl->img = crAlloc(ptl->bytes);
192 if (!ptl->img) return VERR_NO_MEMORY;
193
194 rc = SSMR3GetMem(pSSM, ptl->img, ptl->bytes);
195 AssertRCReturn(rc, rc);
196 }
197#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
198 /* Same story as in crStateSaveTextureObjData */
199 else if (ptl->bytes)
200 {
201 ptl->img = crAlloc(ptl->bytes);
202 if (!ptl->img) return VERR_NO_MEMORY;
203
204 rc = SSMR3GetMem(pSSM, ptl->img, ptl->bytes);
205 AssertRCReturn(rc, rc);
206 }
207#endif
208 crStateTextureInitTextureFormat(ptl, ptl->internalFormat);
209
210 //FILLDIRTY(ptl->dirty);
211 }
212 }
213
214 return VINF_SUCCESS;
215}
216
217static void crStateSaveSharedTextureCB(unsigned long key, void *data1, void *data2)
218{
219 CRTextureObj *pTexture = (CRTextureObj *) data1;
220 PSSMHANDLE pSSM = (PSSMHANDLE) data2;
221 int32_t rc;
222
223 CRASSERT(pTexture && pSSM);
224
225 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
226 CRASSERT(rc == VINF_SUCCESS);
227 rc = SSMR3PutMem(pSSM, pTexture, sizeof(*pTexture));
228 CRASSERT(rc == VINF_SUCCESS);
229 rc = crStateSaveTextureObjData(pTexture, pSSM);
230 CRASSERT(rc == VINF_SUCCESS);
231}
232
233static int32_t crStateSaveMatrixStack(CRMatrixStack *pStack, PSSMHANDLE pSSM)
234{
235 return SSMR3PutMem(pSSM, pStack->stack, sizeof(CRmatrix) * pStack->maxDepth);
236}
237
238static int32_t crStateLoadMatrixStack(CRMatrixStack *pStack, PSSMHANDLE pSSM)
239{
240 int32_t rc;
241
242 CRASSERT(pStack && pSSM);
243
244 rc = SSMR3GetMem(pSSM, pStack->stack, sizeof(CRmatrix) * pStack->maxDepth);
245 /* fixup stack top pointer */
246 pStack->top = &pStack->stack[pStack->depth];
247 return rc;
248}
249
250static int32_t crStateSaveTextureObjPtr(CRTextureObj *pTexture, PSSMHANDLE pSSM)
251{
252 /* Current texture pointer can't be NULL for real texture unit states,
253 * but it could be NULL for unused attribute stack depths.
254 */
255 if (pTexture)
256 return SSMR3PutU32(pSSM, pTexture->name);
257 else
258 return VINF_SUCCESS;
259}
260
261static int32_t crStateLoadTextureObjPtr(CRTextureObj **pTexture, CRContext *pContext, GLenum target, PSSMHANDLE pSSM)
262{
263 uint32_t texName;
264 int32_t rc;
265
266 /* We're loading attrib stack with unused state */
267 if (!*pTexture)
268 return VINF_SUCCESS;
269
270 rc = SSMR3GetU32(pSSM, &texName);
271 AssertRCReturn(rc, rc);
272
273 if (texName)
274 {
275 *pTexture = (CRTextureObj *) crHashtableSearch(pContext->shared->textureTable, texName);
276 }
277 else
278 {
279 switch (target)
280 {
281 case GL_TEXTURE_1D:
282 *pTexture = &(pContext->texture.base1D);
283 break;
284 case GL_TEXTURE_2D:
285 *pTexture = &(pContext->texture.base2D);
286 break;
287#ifdef CR_OPENGL_VERSION_1_2
288 case GL_TEXTURE_3D:
289 *pTexture = &(pContext->texture.base3D);
290 break;
291#endif
292#ifdef CR_ARB_texture_cube_map
293 case GL_TEXTURE_CUBE_MAP_ARB:
294 *pTexture = &(pContext->texture.baseCubeMap);
295 break;
296#endif
297#ifdef CR_NV_texture_rectangle
298 case GL_TEXTURE_RECTANGLE_NV:
299 *pTexture = &(pContext->texture.baseRect);
300 break;
301#endif
302 default:
303 crError("LoadTextureObjPtr: Unknown texture target %d", target);
304 }
305 }
306
307 return rc;
308}
309
310static int32_t crStateSaveTexUnitCurrentTexturePtrs(CRTextureUnit *pTexUnit, PSSMHANDLE pSSM)
311{
312 int32_t rc;
313
314 rc = crStateSaveTextureObjPtr(pTexUnit->currentTexture1D, pSSM);
315 AssertRCReturn(rc, rc);
316 rc = crStateSaveTextureObjPtr(pTexUnit->currentTexture2D, pSSM);
317 AssertRCReturn(rc, rc);
318 rc = crStateSaveTextureObjPtr(pTexUnit->currentTexture3D, pSSM);
319 AssertRCReturn(rc, rc);
320#ifdef CR_ARB_texture_cube_map
321 rc = crStateSaveTextureObjPtr(pTexUnit->currentTextureCubeMap, pSSM);
322 AssertRCReturn(rc, rc);
323#endif
324#ifdef CR_NV_texture_rectangle
325 rc = crStateSaveTextureObjPtr(pTexUnit->currentTextureRect, pSSM);
326 AssertRCReturn(rc, rc);
327#endif
328
329 return rc;
330}
331
332static int32_t crStateLoadTexUnitCurrentTexturePtrs(CRTextureUnit *pTexUnit, CRContext *pContext, PSSMHANDLE pSSM)
333{
334 int32_t rc;
335
336 rc = crStateLoadTextureObjPtr(&pTexUnit->currentTexture1D, pContext, GL_TEXTURE_1D, pSSM);
337 AssertRCReturn(rc, rc);
338 rc = crStateLoadTextureObjPtr(&pTexUnit->currentTexture2D, pContext, GL_TEXTURE_1D, pSSM);
339 AssertRCReturn(rc, rc);
340 rc = crStateLoadTextureObjPtr(&pTexUnit->currentTexture3D, pContext, GL_TEXTURE_2D, pSSM);
341 AssertRCReturn(rc, rc);
342#ifdef CR_ARB_texture_cube_map
343 rc = crStateLoadTextureObjPtr(&pTexUnit->currentTextureCubeMap, pContext, GL_TEXTURE_CUBE_MAP_ARB, pSSM);
344 AssertRCReturn(rc, rc);
345#endif
346#ifdef CR_NV_texture_rectangle
347 rc = crStateLoadTextureObjPtr(&pTexUnit->currentTextureRect, pContext, GL_TEXTURE_RECTANGLE_NV, pSSM);
348 AssertRCReturn(rc, rc);
349#endif
350
351 return rc;
352}
353
354static int32_t crSateSaveEvalCoeffs1D(CREvaluator1D *pEval, PSSMHANDLE pSSM)
355{
356 int32_t rc, i;
357
358 for (i=0; i<GLEVAL_TOT; ++i)
359 {
360 if (pEval[i].coeff)
361 {
362 rc = SSMR3PutMem(pSSM, pEval[i].coeff, pEval[i].order * gleval_sizes[i] * sizeof(GLfloat));
363 AssertRCReturn(rc, rc);
364 }
365 }
366
367 return VINF_SUCCESS;
368}
369
370static int32_t crSateSaveEvalCoeffs2D(CREvaluator2D *pEval, PSSMHANDLE pSSM)
371{
372 int32_t rc, i;
373
374 for (i=0; i<GLEVAL_TOT; ++i)
375 {
376 if (pEval[i].coeff)
377 {
378 rc = SSMR3PutMem(pSSM, pEval[i].coeff, pEval[i].uorder * pEval[i].vorder * gleval_sizes[i] * sizeof(GLfloat));
379 AssertRCReturn(rc, rc);
380 }
381 }
382
383 return VINF_SUCCESS;
384}
385
386static int32_t crSateLoadEvalCoeffs1D(CREvaluator1D *pEval, GLboolean bReallocMem, PSSMHANDLE pSSM)
387{
388 int32_t rc, i;
389 size_t size;
390
391 for (i=0; i<GLEVAL_TOT; ++i)
392 {
393 if (pEval[i].coeff)
394 {
395 size = pEval[i].order * gleval_sizes[i] * sizeof(GLfloat);
396 if (bReallocMem)
397 {
398 pEval[i].coeff = (GLfloat*) crAlloc(size);
399 if (!pEval[i].coeff) return VERR_NO_MEMORY;
400 }
401 rc = SSMR3GetMem(pSSM, pEval[i].coeff, size);
402 AssertRCReturn(rc, rc);
403 }
404 }
405
406 return VINF_SUCCESS;
407}
408
409static int32_t crSateLoadEvalCoeffs2D(CREvaluator2D *pEval, GLboolean bReallocMem, PSSMHANDLE pSSM)
410{
411 int32_t rc, i;
412 size_t size;
413
414 for (i=0; i<GLEVAL_TOT; ++i)
415 {
416 if (pEval[i].coeff)
417 {
418 size = pEval[i].uorder * pEval[i].vorder * gleval_sizes[i] * sizeof(GLfloat);
419 if (bReallocMem)
420 {
421 pEval[i].coeff = (GLfloat*) crAlloc(size);
422 if (!pEval[i].coeff) return VERR_NO_MEMORY;
423 }
424 rc = SSMR3GetMem(pSSM, pEval[i].coeff, size);
425 AssertRCReturn(rc, rc);
426 }
427 }
428
429 return VINF_SUCCESS;
430}
431
432static void crStateCopyEvalPtrs1D(CREvaluator1D *pDst, CREvaluator1D *pSrc)
433{
434 int32_t i;
435
436 for (i=0; i<GLEVAL_TOT; ++i)
437 pDst[i].coeff = pSrc[i].coeff;
438
439 /*
440 pDst[GL_MAP1_VERTEX_3-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_VERTEX_3-GL_MAP1_COLOR_4].coeff;
441 pDst[GL_MAP1_VERTEX_4-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_VERTEX_4-GL_MAP1_COLOR_4].coeff;
442 pDst[GL_MAP1_INDEX-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_INDEX-GL_MAP1_COLOR_4].coeff;
443 pDst[GL_MAP1_COLOR_4-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_COLOR_4-GL_MAP1_COLOR_4].coeff;
444 pDst[GL_MAP1_NORMAL-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_NORMAL-GL_MAP1_COLOR_4].coeff;
445 pDst[GL_MAP1_TEXTURE_COORD_1-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_TEXTURE_COORD_1-GL_MAP1_COLOR_4].coeff;
446 pDst[GL_MAP1_TEXTURE_COORD_2-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_TEXTURE_COORD_2-GL_MAP1_COLOR_4].coeff;
447 pDst[GL_MAP1_TEXTURE_COORD_3-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_TEXTURE_COORD_3-GL_MAP1_COLOR_4].coeff;
448 pDst[GL_MAP1_TEXTURE_COORD_4-GL_MAP1_COLOR_4].coeff = pSrc[GL_MAP1_TEXTURE_COORD_4-GL_MAP1_COLOR_4].coeff;
449 */
450}
451
452static void crStateCopyEvalPtrs2D(CREvaluator2D *pDst, CREvaluator2D *pSrc)
453{
454 int32_t i;
455
456 for (i=0; i<GLEVAL_TOT; ++i)
457 pDst[i].coeff = pSrc[i].coeff;
458
459 /*
460 pDst[GL_MAP2_VERTEX_3-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_VERTEX_3-GL_MAP2_COLOR_4].coeff;
461 pDst[GL_MAP2_VERTEX_4-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_VERTEX_4-GL_MAP2_COLOR_4].coeff;
462 pDst[GL_MAP2_INDEX-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_INDEX-GL_MAP2_COLOR_4].coeff;
463 pDst[GL_MAP2_COLOR_4-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_COLOR_4-GL_MAP2_COLOR_4].coeff;
464 pDst[GL_MAP2_NORMAL-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_NORMAL-GL_MAP2_COLOR_4].coeff;
465 pDst[GL_MAP2_TEXTURE_COORD_1-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_TEXTURE_COORD_1-GL_MAP2_COLOR_4].coeff;
466 pDst[GL_MAP2_TEXTURE_COORD_2-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_TEXTURE_COORD_2-GL_MAP2_COLOR_4].coeff;
467 pDst[GL_MAP2_TEXTURE_COORD_3-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_TEXTURE_COORD_3-GL_MAP2_COLOR_4].coeff;
468 pDst[GL_MAP2_TEXTURE_COORD_4-GL_MAP2_COLOR_4].coeff = pSrc[GL_MAP2_TEXTURE_COORD_4-GL_MAP2_COLOR_4].coeff;
469 */
470}
471
472static void crStateSaveBufferObjectCB(unsigned long key, void *data1, void *data2)
473{
474 CRBufferObject *pBufferObj = (CRBufferObject *) data1;
475 PSSMHANDLE pSSM = (PSSMHANDLE) data2;
476 int32_t rc;
477
478 CRASSERT(pBufferObj && pSSM);
479
480 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
481 CRASSERT(rc == VINF_SUCCESS);
482 rc = SSMR3PutMem(pSSM, pBufferObj, sizeof(*pBufferObj));
483 CRASSERT(rc == VINF_SUCCESS);
484
485 if (pBufferObj->data)
486 {
487 /*We could get here even though retainBufferData is false on host side, in case when we're taking snapshot
488 after state load and before this context was ever made current*/
489 CRASSERT(pBufferObj->size>0);
490 rc = SSMR3PutMem(pSSM, pBufferObj->data, pBufferObj->size);
491 CRASSERT(rc == VINF_SUCCESS);
492 }
493 else if (pBufferObj->name!=0 && pBufferObj->size>0)
494 {
495 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, pBufferObj->name);
496 pBufferObj->pointer = diff_api.MapBufferARB(GL_ARRAY_BUFFER_ARB, GL_READ_ONLY_ARB);
497 rc = SSMR3PutMem(pSSM, &pBufferObj->pointer, sizeof(pBufferObj->pointer));
498 CRASSERT(rc == VINF_SUCCESS);
499 if (pBufferObj->pointer)
500 {
501 rc = SSMR3PutMem(pSSM, pBufferObj->pointer, pBufferObj->size);
502 CRASSERT(rc == VINF_SUCCESS);
503 }
504 diff_api.UnmapBufferARB(GL_ARRAY_BUFFER_ARB);
505 pBufferObj->pointer = NULL;
506 }
507}
508
509static void crStateSaveProgramCB(unsigned long key, void *data1, void *data2)
510{
511 CRProgram *pProgram = (CRProgram *) data1;
512 PSSMHANDLE pSSM = (PSSMHANDLE) data2;
513 CRProgramSymbol *pSymbol;
514 int32_t rc;
515
516 CRASSERT(pProgram && pSSM);
517
518 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
519 CRASSERT(rc == VINF_SUCCESS);
520 rc = SSMR3PutMem(pSSM, pProgram, sizeof(*pProgram));
521 CRASSERT(rc == VINF_SUCCESS);
522 if (pProgram->string)
523 {
524 CRASSERT(pProgram->length);
525 rc = SSMR3PutMem(pSSM, pProgram->string, pProgram->length);
526 CRASSERT(rc == VINF_SUCCESS);
527 }
528
529 for (pSymbol = pProgram->symbolTable; pSymbol; pSymbol=pSymbol->next)
530 {
531 rc = SSMR3PutMem(pSSM, pSymbol, sizeof(*pSymbol));
532 CRASSERT(rc == VINF_SUCCESS);
533 if (pSymbol->name)
534 {
535 CRASSERT(pSymbol->cbName>0);
536 rc = SSMR3PutMem(pSSM, pSymbol->name, pSymbol->cbName);
537 CRASSERT(rc == VINF_SUCCESS);
538 }
539 }
540}
541
542static void crStateSaveFramebuffersCB(unsigned long key, void *data1, void *data2)
543{
544 CRFramebufferObject *pFBO = (CRFramebufferObject*) data1;
545 PSSMHANDLE pSSM = (PSSMHANDLE) data2;
546 int32_t rc;
547
548 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
549 CRASSERT(rc == VINF_SUCCESS);
550
551 rc = SSMR3PutMem(pSSM, pFBO, sizeof(*pFBO));
552 CRASSERT(rc == VINF_SUCCESS);
553}
554
555static void crStateSaveRenderbuffersCB(unsigned long key, void *data1, void *data2)
556{
557 CRRenderbufferObject *pRBO = (CRRenderbufferObject*) data1;
558 PSSMHANDLE pSSM = (PSSMHANDLE) data2;
559 int32_t rc;
560
561 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
562 CRASSERT(rc == VINF_SUCCESS);
563
564 rc = SSMR3PutMem(pSSM, pRBO, sizeof(*pRBO));
565 CRASSERT(rc == VINF_SUCCESS);
566}
567
568static int32_t crStateLoadProgram(CRProgram **ppProgram, PSSMHANDLE pSSM)
569{
570 CRProgramSymbol **ppSymbol;
571 int32_t rc;
572 unsigned long key;
573
574 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
575 AssertRCReturn(rc, rc);
576
577 /* we're loading default vertex or pixel program*/
578 if (*ppProgram)
579 {
580 if (key!=0) return VERR_SSM_UNEXPECTED_DATA;
581 }
582 else
583 {
584 *ppProgram = (CRProgram*) crAlloc(sizeof(CRProgram));
585 if (!ppProgram) return VERR_NO_MEMORY;
586 if (key==0) return VERR_SSM_UNEXPECTED_DATA;
587 }
588
589 rc = SSMR3GetMem(pSSM, *ppProgram, sizeof(**ppProgram));
590 AssertRCReturn(rc, rc);
591
592 if ((*ppProgram)->string)
593 {
594 CRASSERT((*ppProgram)->length);
595 (*ppProgram)->string = crAlloc((*ppProgram)->length);
596 if (!(*ppProgram)->string) return VERR_NO_MEMORY;
597 rc = SSMR3GetMem(pSSM, (void*) (*ppProgram)->string, (*ppProgram)->length);
598 AssertRCReturn(rc, rc);
599 }
600
601 for (ppSymbol = &(*ppProgram)->symbolTable; *ppSymbol; ppSymbol=&(*ppSymbol)->next)
602 {
603 *ppSymbol = crAlloc(sizeof(CRProgramSymbol));
604 if (!ppSymbol) return VERR_NO_MEMORY;
605
606 rc = SSMR3GetMem(pSSM, *ppSymbol, sizeof(**ppSymbol));
607 AssertRCReturn(rc, rc);
608
609 if ((*ppSymbol)->name)
610 {
611 CRASSERT((*ppSymbol)->cbName>0);
612 (*ppSymbol)->name = crAlloc((*ppSymbol)->cbName);
613 if (!(*ppSymbol)->name) return VERR_NO_MEMORY;
614
615 rc = SSMR3GetMem(pSSM, (void*) (*ppSymbol)->name, (*ppSymbol)->cbName);
616 AssertRCReturn(rc, rc);
617 }
618 }
619
620 return VINF_SUCCESS;
621}
622
623static void crStateSaveString(const char *pStr, PSSMHANDLE pSSM)
624{
625 int32_t len;
626 int32_t rc;
627
628 if (pStr)
629 {
630 len = crStrlen(pStr)+1;
631
632 rc = SSMR3PutS32(pSSM, len);
633 CRASSERT(rc == VINF_SUCCESS);
634
635 rc = SSMR3PutMem(pSSM, pStr, len*sizeof(*pStr));
636 CRASSERT(rc == VINF_SUCCESS);
637 }
638 else
639 {
640 rc = SSMR3PutS32(pSSM, 0);
641 CRASSERT(rc == VINF_SUCCESS);
642 }
643}
644
645static char* crStateLoadString(PSSMHANDLE pSSM)
646{
647 int32_t len, rc;
648 char* pStr = NULL;
649
650 rc = SSMR3GetS32(pSSM, &len);
651 CRASSERT(rc == VINF_SUCCESS);
652
653 if (len!=0)
654 {
655 pStr = crAlloc(len*sizeof(*pStr));
656
657 rc = SSMR3GetMem(pSSM, pStr, len*sizeof(*pStr));
658 CRASSERT(rc == VINF_SUCCESS);
659 }
660
661 return pStr;
662}
663
664static void crStateSaveGLSLShaderCB(unsigned long key, void *data1, void *data2)
665{
666 CRGLSLShader *pShader = (CRGLSLShader*) data1;
667 PSSMHANDLE pSSM = (PSSMHANDLE) data2;
668 int32_t rc;
669
670 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
671 CRASSERT(rc == VINF_SUCCESS);
672
673 rc = SSMR3PutMem(pSSM, pShader, sizeof(*pShader));
674 CRASSERT(rc == VINF_SUCCESS);
675
676 if (pShader->source)
677 {
678 crStateSaveString(pShader->source, pSSM);
679 }
680 else
681 {
682 GLint sLen=0;
683 GLchar *source=NULL;
684
685 diff_api.GetShaderiv(pShader->hwid, GL_SHADER_SOURCE_LENGTH, &sLen);
686 if (sLen>0)
687 {
688 source = (GLchar*) crAlloc(sLen);
689 diff_api.GetShaderSource(pShader->hwid, sLen, NULL, source);
690 }
691
692 crStateSaveString(source, pSSM);
693 if (source) crFree(source);
694 }
695}
696
697static CRGLSLShader* crStateLoadGLSLShader(PSSMHANDLE pSSM)
698{
699 CRGLSLShader *pShader;
700 int32_t rc;
701 unsigned long key;
702
703 pShader = crAlloc(sizeof(*pShader));
704 if (!pShader) return NULL;
705
706 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
707 CRASSERT(rc == VINF_SUCCESS);
708
709 rc = SSMR3GetMem(pSSM, pShader, sizeof(*pShader));
710 CRASSERT(rc == VINF_SUCCESS);
711
712 pShader->source = crStateLoadString(pSSM);
713
714 return pShader;
715}
716
717
718static void crStateSaveGLSLShaderKeyCB(unsigned long key, void *data1, void *data2)
719{
720 CRGLSLShader *pShader = (CRGLSLShader*) data1;
721 PSSMHANDLE pSSM = (PSSMHANDLE) data2;
722 int32_t rc;
723
724 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
725 CRASSERT(rc == VINF_SUCCESS);
726}
727
728static void crStateSaveGLSLProgramAttribs(CRGLSLProgramState *pState, PSSMHANDLE pSSM)
729{
730 GLuint i;
731 int32_t rc;
732
733 for (i=0; i<pState->cAttribs; ++i)
734 {
735 rc = SSMR3PutMem(pSSM, &pState->pAttribs[i].index, sizeof(pState->pAttribs[i].index));
736 CRASSERT(rc == VINF_SUCCESS);
737 crStateSaveString(pState->pAttribs[i].name, pSSM);
738 }
739}
740
741static void crStateSaveGLSLProgramCB(unsigned long key, void *data1, void *data2)
742{
743 CRGLSLProgram *pProgram = (CRGLSLProgram*) data1;
744 PSSMHANDLE pSSM = (PSSMHANDLE) data2;
745 int32_t rc;
746 uint32_t ui32;
747 GLint maxUniformLen, activeUniforms=0, uniformsCount=0, i, j;
748 GLchar *name = NULL;
749 GLenum type;
750 GLint size, location;
751
752 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
753 CRASSERT(rc == VINF_SUCCESS);
754
755 rc = SSMR3PutMem(pSSM, pProgram, sizeof(*pProgram));
756 CRASSERT(rc == VINF_SUCCESS);
757
758 ui32 = crHashtableNumElements(pProgram->currentState.attachedShaders);
759 rc = SSMR3PutU32(pSSM, ui32);
760 CRASSERT(rc == VINF_SUCCESS);
761
762 crHashtableWalk(pProgram->currentState.attachedShaders, crStateSaveGLSLShaderKeyCB, pSSM);
763
764 if (pProgram->activeState.attachedShaders)
765 {
766 ui32 = crHashtableNumElements(pProgram->activeState.attachedShaders);
767 rc = SSMR3PutU32(pSSM, ui32);
768 CRASSERT(rc == VINF_SUCCESS);
769 crHashtableWalk(pProgram->currentState.attachedShaders, crStateSaveGLSLShaderCB, pSSM);
770 }
771
772 crStateSaveGLSLProgramAttribs(&pProgram->currentState, pSSM);
773 crStateSaveGLSLProgramAttribs(&pProgram->activeState, pSSM);
774
775 diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_UNIFORM_MAX_LENGTH, &maxUniformLen);
776 diff_api.GetProgramiv(pProgram->hwid, GL_ACTIVE_UNIFORMS, &activeUniforms);
777
778 if (activeUniforms>0)
779 {
780 name = (GLchar *) crAlloc((maxUniformLen+8)*sizeof(GLchar));
781
782 if (!name)
783 {
784 crWarning("crStateSaveGLSLProgramCB: out of memory");
785 return;
786 }
787 }
788
789 for (i=0; i<activeUniforms; ++i)
790 {
791 diff_api.GetActiveUniform(pProgram->hwid, i, maxUniformLen, NULL, &size, &type, name);
792 uniformsCount += size;
793 }
794 CRASSERT(uniformsCount>=activeUniforms);
795
796 rc = SSMR3PutS32(pSSM, uniformsCount);
797 CRASSERT(rc == VINF_SUCCESS);
798
799 if (activeUniforms>0)
800 {
801 GLfloat fdata[16];
802 GLint idata[16];
803 char *pIndexStr=NULL;
804
805 for (i=0; i<activeUniforms; ++i)
806 {
807 diff_api.GetActiveUniform(pProgram->hwid, i, maxUniformLen, NULL, &size, &type, name);
808
809 if (size>1)
810 {
811 pIndexStr = crStrchr(name, '[');
812 if (!pIndexStr)
813 {
814 pIndexStr = name+crStrlen(name);
815 }
816 }
817
818 for (j=0; j<size; ++j)
819 {
820 if (size>1)
821 {
822 sprintf(pIndexStr, "[%i]", j);
823 location = diff_api.GetUniformLocation(pProgram->hwid, name);
824 }
825 else
826 {
827 location = i;
828 }
829
830 rc = SSMR3PutMem(pSSM, &type, sizeof(type));
831 CRASSERT(rc == VINF_SUCCESS);
832
833 crStateSaveString(name, pSSM);
834
835 if (crStateIsIntUniform(type))
836 {
837 diff_api.GetUniformiv(pProgram->hwid, location, &idata[0]);
838 rc = SSMR3PutMem(pSSM, &idata[0], crStateGetUniformSize(type)*sizeof(idata[0]));
839 CRASSERT(rc == VINF_SUCCESS);
840 }
841 else
842 {
843 diff_api.GetUniformfv(pProgram->hwid, location, &fdata[0]);
844 rc = SSMR3PutMem(pSSM, &fdata[0], crStateGetUniformSize(type)*sizeof(fdata[0]));
845 CRASSERT(rc == VINF_SUCCESS);
846 }
847 }
848 }
849
850 crFree(name);
851 }
852}
853
854static int32_t crStateSaveClientPointer(CRVertexArrays *pArrays, int32_t index, PSSMHANDLE pSSM)
855{
856 int32_t rc;
857 CRClientPointer *cp;
858
859 cp = crStateGetClientPointerByIndex(index, pArrays);
860
861 rc = SSMR3PutU32(pSSM, cp->buffer->name);
862 AssertRCReturn(rc, rc);
863
864#ifdef CR_EXT_compiled_vertex_array
865 if (cp->locked)
866 {
867 CRASSERT(cp->p);
868 rc = SSMR3PutMem(pSSM, cp->p, cp->stride*(pArrays->lockFirst+pArrays->lockCount));
869 AssertRCReturn(rc, rc);
870 }
871#endif
872
873 return VINF_SUCCESS;
874}
875
876static int32_t crStateLoadClientPointer(CRVertexArrays *pArrays, int32_t index, CRContext *pContext, PSSMHANDLE pSSM)
877{
878 int32_t rc;
879 uint32_t ui;
880 CRClientPointer *cp;
881
882 cp = crStateGetClientPointerByIndex(index, pArrays);
883
884 rc = SSMR3GetU32(pSSM, &ui);
885 AssertRCReturn(rc, rc);
886 cp->buffer = ui==0 ? pContext->bufferobject.nullBuffer : crHashtableSearch(pContext->bufferobject.buffers, ui);
887
888#ifdef CR_EXT_compiled_vertex_array
889 if (cp->locked)
890 {
891 rc = crStateAllocAndSSMR3GetMem(pSSM, &cp->p, cp->stride*(pArrays->lockFirst+pArrays->lockCount));
892 AssertRCReturn(rc, rc);
893 }
894#endif
895
896 return VINF_SUCCESS;
897}
898
899int32_t crStateSaveContext(CRContext *pContext, PSSMHANDLE pSSM)
900{
901 int32_t rc, i;
902 uint32_t ui32, j;
903
904 CRASSERT(pContext && pSSM);
905
906 rc = SSMR3PutMem(pSSM, pContext, sizeof(*pContext));
907 AssertRCReturn(rc, rc);
908
909 if (crHashtableNumElements(pContext->shared->dlistTable)>0)
910 crWarning("Saving state with %d display lists, unsupported", crHashtableNumElements(pContext->shared->dlistTable));
911
912 if (crHashtableNumElements(pContext->program.programHash)>0)
913 crDebug("Saving state with %d programs", crHashtableNumElements(pContext->program.programHash));
914
915 /* Save transform state */
916 rc = SSMR3PutMem(pSSM, pContext->transform.clipPlane, sizeof(GLvectord)*CR_MAX_CLIP_PLANES);
917 AssertRCReturn(rc, rc);
918 rc = SSMR3PutMem(pSSM, pContext->transform.clip, sizeof(GLboolean)*CR_MAX_CLIP_PLANES);
919 AssertRCReturn(rc, rc);
920 rc = crStateSaveMatrixStack(&pContext->transform.modelViewStack, pSSM);
921 AssertRCReturn(rc, rc);
922 rc = crStateSaveMatrixStack(&pContext->transform.projectionStack, pSSM);
923 AssertRCReturn(rc, rc);
924 rc = crStateSaveMatrixStack(&pContext->transform.colorStack, pSSM);
925 AssertRCReturn(rc, rc);
926 for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
927 {
928 rc = crStateSaveMatrixStack(&pContext->transform.textureStack[i], pSSM);
929 AssertRCReturn(rc, rc);
930 }
931 for (i = 0 ; i < CR_MAX_PROGRAM_MATRICES ; i++)
932 {
933 rc = crStateSaveMatrixStack(&pContext->transform.programStack[i], pSSM);
934 AssertRCReturn(rc, rc);
935 }
936
937 /* Save textures */
938 rc = crStateSaveTextureObjData(&pContext->texture.base1D, pSSM);
939 AssertRCReturn(rc, rc);
940 rc = crStateSaveTextureObjData(&pContext->texture.base2D, pSSM);
941 AssertRCReturn(rc, rc);
942 rc = crStateSaveTextureObjData(&pContext->texture.base3D, pSSM);
943 AssertRCReturn(rc, rc);
944 rc = crStateSaveTextureObjData(&pContext->texture.proxy1D, pSSM);
945 AssertRCReturn(rc, rc);
946 rc = crStateSaveTextureObjData(&pContext->texture.proxy2D, pSSM);
947 AssertRCReturn(rc, rc);
948 rc = crStateSaveTextureObjData(&pContext->texture.proxy3D, pSSM);
949#ifdef CR_ARB_texture_cube_map
950 rc = crStateSaveTextureObjData(&pContext->texture.baseCubeMap, pSSM);
951 AssertRCReturn(rc, rc);
952 rc = crStateSaveTextureObjData(&pContext->texture.proxyCubeMap, pSSM);
953 AssertRCReturn(rc, rc);
954#endif
955#ifdef CR_NV_texture_rectangle
956 rc = crStateSaveTextureObjData(&pContext->texture.baseRect, pSSM);
957 AssertRCReturn(rc, rc);
958 rc = crStateSaveTextureObjData(&pContext->texture.proxyRect, pSSM);
959 AssertRCReturn(rc, rc);
960#endif
961
962 /* Save shared textures */
963 CRASSERT(pContext->shared && pContext->shared->textureTable);
964 ui32 = crHashtableNumElements(pContext->shared->textureTable);
965 rc = SSMR3PutU32(pSSM, ui32);
966 AssertRCReturn(rc, rc);
967 crHashtableWalk(pContext->shared->textureTable, crStateSaveSharedTextureCB, pSSM);
968
969#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
970 /* Restore previous texture bindings via diff_api */
971 if (ui32)
972 {
973 CRTextureUnit *pTexUnit;
974
975 pTexUnit = &pContext->texture.unit[pContext->texture.curTextureUnit];
976
977 diff_api.BindTexture(GL_TEXTURE_1D, pTexUnit->currentTexture1D->name);
978 diff_api.BindTexture(GL_TEXTURE_2D, pTexUnit->currentTexture2D->name);
979 diff_api.BindTexture(GL_TEXTURE_3D, pTexUnit->currentTexture3D->name);
980#ifdef CR_ARB_texture_cube_map
981 diff_api.BindTexture(GL_TEXTURE_CUBE_MAP_ARB, pTexUnit->currentTextureCubeMap->name);
982#endif
983#ifdef CR_NV_texture_rectangle
984 diff_api.BindTexture(GL_TEXTURE_RECTANGLE_NV, pTexUnit->currentTextureRect->name);
985#endif
986 }
987#endif
988
989 /* Save current texture pointers */
990 for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i)
991 {
992 rc = crStateSaveTexUnitCurrentTexturePtrs(&pContext->texture.unit[i], pSSM);
993 AssertRCReturn(rc, rc);
994 }
995
996 /* Save lights */
997 CRASSERT(pContext->lighting.light);
998 rc = SSMR3PutMem(pSSM, pContext->lighting.light, CR_MAX_LIGHTS * sizeof(*pContext->lighting.light));
999 AssertRCReturn(rc, rc);
1000
1001 /* Save attrib stack*/
1002 /*@todo could go up to used stack depth here?*/
1003 for ( i = 0 ; i < CR_MAX_ATTRIB_STACK_DEPTH ; i++)
1004 {
1005 if (pContext->attrib.enableStack[i].clip)
1006 {
1007 rc = SSMR3PutMem(pSSM, pContext->attrib.enableStack[i].clip,
1008 pContext->limits.maxClipPlanes*sizeof(GLboolean));
1009 AssertRCReturn(rc, rc);
1010 }
1011
1012 if (pContext->attrib.enableStack[i].light)
1013 {
1014 rc = SSMR3PutMem(pSSM, pContext->attrib.enableStack[i].light,
1015 pContext->limits.maxLights*sizeof(GLboolean));
1016 AssertRCReturn(rc, rc);
1017 }
1018
1019 if (pContext->attrib.lightingStack[i].light)
1020 {
1021 rc = SSMR3PutMem(pSSM, pContext->attrib.lightingStack[i].light,
1022 pContext->limits.maxLights*sizeof(CRLight));
1023 AssertRCReturn(rc, rc);
1024 }
1025
1026 for (j=0; j<pContext->limits.maxTextureUnits; ++j)
1027 {
1028 rc = crStateSaveTexUnitCurrentTexturePtrs(&pContext->attrib.textureStack[i].unit[j], pSSM);
1029 AssertRCReturn(rc, rc);
1030 }
1031
1032 if (pContext->attrib.transformStack[i].clip)
1033 {
1034 rc = SSMR3PutMem(pSSM, pContext->attrib.transformStack[i].clip,
1035 pContext->limits.maxClipPlanes*sizeof(GLboolean));
1036 AssertRCReturn(rc, rc);
1037 }
1038
1039 if (pContext->attrib.transformStack[i].clipPlane)
1040 {
1041 rc = SSMR3PutMem(pSSM, pContext->attrib.transformStack[i].clipPlane,
1042 pContext->limits.maxClipPlanes*sizeof(GLvectord));
1043 AssertRCReturn(rc, rc);
1044 }
1045
1046 rc = crSateSaveEvalCoeffs1D(pContext->attrib.evalStack[i].eval1D, pSSM);
1047 AssertRCReturn(rc, rc);
1048 rc = crSateSaveEvalCoeffs2D(pContext->attrib.evalStack[i].eval2D, pSSM);
1049 AssertRCReturn(rc, rc);
1050 }
1051
1052 /* Save evaluator coeffs */
1053 rc = crSateSaveEvalCoeffs1D(pContext->eval.eval1D, pSSM);
1054 AssertRCReturn(rc, rc);
1055 rc = crSateSaveEvalCoeffs2D(pContext->eval.eval2D, pSSM);
1056 AssertRCReturn(rc, rc);
1057
1058#ifdef CR_ARB_vertex_buffer_object
1059 /* Save buffer objects */
1060 ui32 = crHashtableNumElements(pContext->bufferobject.buffers);
1061 rc = SSMR3PutU32(pSSM, ui32);
1062 AssertRCReturn(rc, rc);
1063 /* Save default one*/
1064 crStateSaveBufferObjectCB(0, pContext->bufferobject.nullBuffer, pSSM);
1065 /* Save all the rest */
1066 crHashtableWalk(pContext->bufferobject.buffers, crStateSaveBufferObjectCB, pSSM);
1067 /* Restore binding */
1068 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, pContext->bufferobject.arrayBuffer->name);
1069 /* Save pointers */
1070 rc = SSMR3PutU32(pSSM, pContext->bufferobject.arrayBuffer->name);
1071 AssertRCReturn(rc, rc);
1072 rc = SSMR3PutU32(pSSM, pContext->bufferobject.elementsBuffer->name);
1073 AssertRCReturn(rc, rc);
1074 /* Save clint pointers and buffer bindings*/
1075 for (i=0; i<CRSTATECLIENT_MAX_VERTEXARRAYS; ++i)
1076 {
1077 rc = crStateSaveClientPointer(&pContext->client.array, i, pSSM);
1078 AssertRCReturn(rc, rc);
1079 }
1080
1081 crDebug("client.vertexArrayStackDepth %i", pContext->client.vertexArrayStackDepth);
1082 for (i=0; i<pContext->client.vertexArrayStackDepth; ++i)
1083 {
1084 CRVertexArrays *pArray = &pContext->client.vertexArrayStack[i];
1085 for (j=0; j<CRSTATECLIENT_MAX_VERTEXARRAYS; ++j)
1086 {
1087 rc = crStateSaveClientPointer(pArray, j, pSSM);
1088 AssertRCReturn(rc, rc);
1089 }
1090 }
1091#endif /*CR_ARB_vertex_buffer_object*/
1092
1093 /* Save pixel/vertex programs */
1094 ui32 = crHashtableNumElements(pContext->program.programHash);
1095 rc = SSMR3PutU32(pSSM, ui32);
1096 AssertRCReturn(rc, rc);
1097 /* Save defauls programs */
1098 crStateSaveProgramCB(0, pContext->program.defaultVertexProgram, pSSM);
1099 crStateSaveProgramCB(0, pContext->program.defaultFragmentProgram, pSSM);
1100 /* Save all the rest */
1101 crHashtableWalk(pContext->program.programHash, crStateSaveProgramCB, pSSM);
1102 /* Save Pointers */
1103 rc = SSMR3PutU32(pSSM, pContext->program.currentVertexProgram->id);
1104 AssertRCReturn(rc, rc);
1105 rc = SSMR3PutU32(pSSM, pContext->program.currentFragmentProgram->id);
1106 AssertRCReturn(rc, rc);
1107 /* This one is unused it seems*/
1108 CRASSERT(!pContext->program.errorString);
1109
1110#ifdef CR_EXT_framebuffer_object
1111 /* Save FBOs */
1112 ui32 = crHashtableNumElements(pContext->framebufferobject.framebuffers);
1113 rc = SSMR3PutU32(pSSM, ui32);
1114 AssertRCReturn(rc, rc);
1115 crHashtableWalk(pContext->framebufferobject.framebuffers, crStateSaveFramebuffersCB, pSSM);
1116 ui32 = crHashtableNumElements(pContext->framebufferobject.renderbuffers);
1117 rc = SSMR3PutU32(pSSM, ui32);
1118 AssertRCReturn(rc, rc);
1119 crHashtableWalk(pContext->framebufferobject.renderbuffers, crStateSaveRenderbuffersCB, pSSM);
1120 rc = SSMR3PutU32(pSSM, pContext->framebufferobject.drawFB?pContext->framebufferobject.drawFB->id:0);
1121 AssertRCReturn(rc, rc);
1122 rc = SSMR3PutU32(pSSM, pContext->framebufferobject.readFB?pContext->framebufferobject.readFB->id:0);
1123 AssertRCReturn(rc, rc);
1124 rc = SSMR3PutU32(pSSM, pContext->framebufferobject.renderbuffer?pContext->framebufferobject.renderbuffer->id:0);
1125 AssertRCReturn(rc, rc);
1126#endif
1127
1128#ifdef CR_OPENGL_VERSION_2_0
1129 /* Save GLSL related info */
1130 ui32 = crHashtableNumElements(pContext->glsl.shaders);
1131 rc = SSMR3PutU32(pSSM, ui32);
1132 AssertRCReturn(rc, rc);
1133 crHashtableWalk(pContext->glsl.shaders, crStateSaveGLSLShaderCB, pSSM);
1134 ui32 = crHashtableNumElements(pContext->glsl.programs);
1135 rc = SSMR3PutU32(pSSM, ui32);
1136 AssertRCReturn(rc, rc);
1137 crHashtableWalk(pContext->glsl.programs, crStateSaveGLSLProgramCB, pSSM);
1138 rc = SSMR3PutU32(pSSM, pContext->glsl.activeProgram?pContext->glsl.activeProgram->id:0);
1139 AssertRCReturn(rc, rc);
1140#endif
1141
1142 {
1143 CRViewportState *pVP = &pContext->viewport;
1144 CRPixelPackState packing = pContext->client.pack;
1145 GLint cbData = crPixelSize(GL_RGBA, GL_UNSIGNED_BYTE) * pVP->viewportH * pVP->viewportW;
1146 void *pData = crAlloc(cbData);
1147
1148 if (!pData)
1149 {
1150 return VERR_NO_MEMORY;
1151 }
1152
1153 diff_api.PixelStorei(GL_PACK_SKIP_ROWS, 0);
1154 diff_api.PixelStorei(GL_PACK_SKIP_PIXELS, 0);
1155 diff_api.PixelStorei(GL_PACK_ALIGNMENT, 1);
1156 diff_api.PixelStorei(GL_PACK_ROW_LENGTH, 0);
1157 diff_api.PixelStorei(GL_PACK_IMAGE_HEIGHT, 0);
1158 diff_api.PixelStorei(GL_PACK_SKIP_IMAGES, 0);
1159 diff_api.PixelStorei(GL_PACK_SWAP_BYTES, 0);
1160 diff_api.PixelStorei(GL_PACK_LSB_FIRST, 0);
1161
1162 diff_api.ReadBuffer(GL_FRONT);
1163 diff_api.ReadPixels(0, 0, pVP->viewportW, pVP->viewportH, GL_RGBA, GL_UNSIGNED_BYTE, pData);
1164
1165 diff_api.ReadBuffer(pContext->framebufferobject.readFB ?
1166 pContext->framebufferobject.readFB->readbuffer : pContext->buffer.readBuffer);
1167 diff_api.PixelStorei(GL_PACK_SKIP_ROWS, packing.skipRows);
1168 diff_api.PixelStorei(GL_PACK_SKIP_PIXELS, packing.skipPixels);
1169 diff_api.PixelStorei(GL_PACK_ALIGNMENT, packing.alignment);
1170 diff_api.PixelStorei(GL_PACK_ROW_LENGTH, packing.rowLength);
1171 diff_api.PixelStorei(GL_PACK_IMAGE_HEIGHT, packing.imageHeight);
1172 diff_api.PixelStorei(GL_PACK_SKIP_IMAGES, packing.skipImages);
1173 diff_api.PixelStorei(GL_PACK_SWAP_BYTES, packing.swapBytes);
1174 diff_api.PixelStorei(GL_PACK_LSB_FIRST, packing.psLSBFirst);
1175
1176 rc = SSMR3PutMem(pSSM, pData, cbData);
1177 AssertRCReturn(rc, rc);
1178
1179 crFree(pData);
1180 }
1181
1182 return VINF_SUCCESS;
1183}
1184
1185#define SLC_COPYPTR(ptr) pTmpContext->ptr = pContext->ptr
1186#define SLC_ASSSERT_NULL_PTR(ptr) CRASSERT(!pContext->ptr)
1187
1188int32_t crStateLoadContext(CRContext *pContext, PSSMHANDLE pSSM)
1189{
1190 CRContext* pTmpContext;
1191 int32_t rc, i, j;
1192 uint32_t uiNumElems, ui, k;
1193 unsigned long key;
1194
1195 CRASSERT(pContext && pSSM);
1196
1197 /* This one is rather big for stack allocation and causes macs to crash */
1198 pTmpContext = (CRContext*)crAlloc(sizeof(*pTmpContext));
1199 if (!pTmpContext)
1200 return VERR_NO_MEMORY;
1201
1202 rc = SSMR3GetMem(pSSM, pTmpContext, sizeof(*pTmpContext));
1203 AssertRCReturn(rc, rc);
1204
1205 SLC_COPYPTR(shared);
1206 SLC_COPYPTR(flush_func);
1207 SLC_COPYPTR(flush_arg);
1208
1209 /* We're supposed to be loading into an empty context, so those pointers should be NULL */
1210 for ( i = 0 ; i < CR_MAX_ATTRIB_STACK_DEPTH ; i++)
1211 {
1212 SLC_ASSSERT_NULL_PTR(attrib.enableStack[i].clip);
1213 SLC_ASSSERT_NULL_PTR(attrib.enableStack[i].light);
1214
1215 SLC_ASSSERT_NULL_PTR(attrib.lightingStack[i].light);
1216 SLC_ASSSERT_NULL_PTR(attrib.transformStack[i].clip);
1217 SLC_ASSSERT_NULL_PTR(attrib.transformStack[i].clipPlane);
1218
1219 for (j=0; j<GLEVAL_TOT; ++j)
1220 {
1221 SLC_ASSSERT_NULL_PTR(attrib.evalStack[i].eval1D[j].coeff);
1222 SLC_ASSSERT_NULL_PTR(attrib.evalStack[i].eval2D[j].coeff);
1223 }
1224 }
1225
1226#ifdef CR_ARB_vertex_buffer_object
1227 SLC_COPYPTR(bufferobject.buffers);
1228 SLC_COPYPTR(bufferobject.nullBuffer);
1229#endif
1230
1231/*@todo, that should be removed probably as those should hold the offset values, so loading should be fine
1232 but better check*/
1233#if 0
1234#ifdef CR_EXT_compiled_vertex_array
1235 SLC_COPYPTR(client.array.v.prevPtr);
1236 SLC_COPYPTR(client.array.c.prevPtr);
1237 SLC_COPYPTR(client.array.f.prevPtr);
1238 SLC_COPYPTR(client.array.s.prevPtr);
1239 SLC_COPYPTR(client.array.e.prevPtr);
1240 SLC_COPYPTR(client.array.i.prevPtr);
1241 SLC_COPYPTR(client.array.n.prevPtr);
1242 for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
1243 {
1244 SLC_COPYPTR(client.array.t[i].prevPtr);
1245 }
1246
1247# ifdef CR_NV_vertex_program
1248 for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++)
1249 {
1250 SLC_COPYPTR(client.array.a[i].prevPtr);
1251 }
1252# endif
1253#endif
1254#endif
1255
1256#ifdef CR_ARB_vertex_buffer_object
1257 /*That just sets those pointers to NULL*/
1258 SLC_COPYPTR(client.array.v.buffer);
1259 SLC_COPYPTR(client.array.c.buffer);
1260 SLC_COPYPTR(client.array.f.buffer);
1261 SLC_COPYPTR(client.array.s.buffer);
1262 SLC_COPYPTR(client.array.e.buffer);
1263 SLC_COPYPTR(client.array.i.buffer);
1264 SLC_COPYPTR(client.array.n.buffer);
1265 for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
1266 {
1267 SLC_COPYPTR(client.array.t[i].buffer);
1268 }
1269# ifdef CR_NV_vertex_program
1270 for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++)
1271 {
1272 SLC_COPYPTR(client.array.a[i].buffer);
1273 }
1274# endif
1275#endif /*CR_ARB_vertex_buffer_object*/
1276
1277 /*@todo CR_NV_vertex_program*/
1278 crStateCopyEvalPtrs1D(pTmpContext->eval.eval1D, pContext->eval.eval1D);
1279 crStateCopyEvalPtrs2D(pTmpContext->eval.eval2D, pContext->eval.eval2D);
1280
1281 SLC_COPYPTR(feedback.buffer); /*@todo*/
1282 SLC_COPYPTR(selection.buffer); /*@todo*/
1283
1284 SLC_COPYPTR(lighting.light);
1285
1286 /*This one could be tricky if we're loading snapshot on host with different GPU*/
1287 SLC_COPYPTR(limits.extensions);
1288
1289#if CR_ARB_occlusion_query
1290 SLC_COPYPTR(occlusion.objects); /*@todo*/
1291#endif
1292
1293 SLC_COPYPTR(program.errorString);
1294 SLC_COPYPTR(program.programHash);
1295 SLC_COPYPTR(program.defaultVertexProgram);
1296 SLC_COPYPTR(program.defaultFragmentProgram);
1297
1298 /* Texture pointers */
1299 for (i=0; i<6; ++i)
1300 {
1301 SLC_COPYPTR(texture.base1D.level[i]);
1302 SLC_COPYPTR(texture.base2D.level[i]);
1303 SLC_COPYPTR(texture.base3D.level[i]);
1304 SLC_COPYPTR(texture.proxy1D.level[i]);
1305 SLC_COPYPTR(texture.proxy2D.level[i]);
1306 SLC_COPYPTR(texture.proxy3D.level[i]);
1307#ifdef CR_ARB_texture_cube_map
1308 SLC_COPYPTR(texture.baseCubeMap.level[i]);
1309 SLC_COPYPTR(texture.proxyCubeMap.level[i]);
1310#endif
1311#ifdef CR_NV_texture_rectangle
1312 SLC_COPYPTR(texture.baseRect.level[i]);
1313 SLC_COPYPTR(texture.proxyRect.level[i]);
1314#endif
1315 }
1316
1317 /* Load transform state */
1318 SLC_COPYPTR(transform.clipPlane);
1319 SLC_COPYPTR(transform.clip);
1320 /* Don't have to worry about pContext->transform.current as it'd be set in crStateSetCurrent call */
1321 /*SLC_COPYPTR(transform.currentStack);*/
1322 SLC_COPYPTR(transform.modelViewStack.stack);
1323 SLC_COPYPTR(transform.projectionStack.stack);
1324 SLC_COPYPTR(transform.colorStack.stack);
1325
1326 for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
1327 {
1328 SLC_COPYPTR(transform.textureStack[i].stack);
1329 }
1330 for (i = 0 ; i < CR_MAX_PROGRAM_MATRICES ; i++)
1331 {
1332 SLC_COPYPTR(transform.programStack[i].stack);
1333 }
1334
1335#ifdef CR_EXT_framebuffer_object
1336 SLC_COPYPTR(framebufferobject.framebuffers);
1337 SLC_COPYPTR(framebufferobject.renderbuffers);
1338#endif
1339
1340#ifdef CR_OPENGL_VERSION_2_0
1341 SLC_COPYPTR(glsl.shaders);
1342 SLC_COPYPTR(glsl.programs);
1343#endif
1344
1345 /* Have to preserve original context id */
1346 CRASSERT(pTmpContext->id == pContext->id);
1347 /* Copy ordinary state to real context */
1348 crMemcpy(pContext, pTmpContext, sizeof(*pTmpContext));
1349 crFree(pTmpContext);
1350 pTmpContext = NULL;
1351
1352 /* Now deal with pointers */
1353
1354 /* Load transform state */
1355 rc = SSMR3GetMem(pSSM, pContext->transform.clipPlane, sizeof(GLvectord)*CR_MAX_CLIP_PLANES);
1356 AssertRCReturn(rc, rc);
1357 rc = SSMR3GetMem(pSSM, pContext->transform.clip, sizeof(GLboolean)*CR_MAX_CLIP_PLANES);
1358 AssertRCReturn(rc, rc);
1359 rc = crStateLoadMatrixStack(&pContext->transform.modelViewStack, pSSM);
1360 AssertRCReturn(rc, rc);
1361 rc = crStateLoadMatrixStack(&pContext->transform.projectionStack, pSSM);
1362 AssertRCReturn(rc, rc);
1363 rc = crStateLoadMatrixStack(&pContext->transform.colorStack, pSSM);
1364 AssertRCReturn(rc, rc);
1365 for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
1366 {
1367 rc = crStateLoadMatrixStack(&pContext->transform.textureStack[i], pSSM);
1368 AssertRCReturn(rc, rc);
1369 }
1370 for (i = 0 ; i < CR_MAX_PROGRAM_MATRICES ; i++)
1371 {
1372 rc = crStateLoadMatrixStack(&pContext->transform.programStack[i], pSSM);
1373 AssertRCReturn(rc, rc);
1374 }
1375
1376 /* Load Textures */
1377 rc = crStateLoadTextureObjData(&pContext->texture.base1D, pSSM);
1378 AssertRCReturn(rc, rc);
1379 rc = crStateLoadTextureObjData(&pContext->texture.base2D, pSSM);
1380 AssertRCReturn(rc, rc);
1381 rc = crStateLoadTextureObjData(&pContext->texture.base3D, pSSM);
1382 AssertRCReturn(rc, rc);
1383 rc = crStateLoadTextureObjData(&pContext->texture.proxy1D, pSSM);
1384 AssertRCReturn(rc, rc);
1385 rc = crStateLoadTextureObjData(&pContext->texture.proxy2D, pSSM);
1386 AssertRCReturn(rc, rc);
1387 rc = crStateLoadTextureObjData(&pContext->texture.proxy3D, pSSM);
1388 AssertRCReturn(rc, rc);
1389#ifdef CR_ARB_texture_cube_map
1390 rc = crStateLoadTextureObjData(&pContext->texture.baseCubeMap, pSSM);
1391 AssertRCReturn(rc, rc);
1392 rc = crStateLoadTextureObjData(&pContext->texture.proxyCubeMap, pSSM);
1393 AssertRCReturn(rc, rc);
1394#endif
1395#ifdef CR_NV_texture_rectangle
1396 rc = crStateLoadTextureObjData(&pContext->texture.baseRect, pSSM);
1397 AssertRCReturn(rc, rc);
1398 rc = crStateLoadTextureObjData(&pContext->texture.proxyRect, pSSM);
1399 AssertRCReturn(rc, rc);
1400#endif
1401
1402 /* Load shared textures */
1403 CRASSERT(pContext->shared && pContext->shared->textureTable);
1404 rc = SSMR3GetU32(pSSM, &uiNumElems);
1405 AssertRCReturn(rc, rc);
1406 for (ui=0; ui<uiNumElems; ++ui)
1407 {
1408 CRTextureObj *pTexture;
1409
1410 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
1411 AssertRCReturn(rc, rc);
1412
1413 pTexture = (CRTextureObj *) crCalloc(sizeof(CRTextureObj));
1414 if (!pTexture) return VERR_NO_MEMORY;
1415
1416 rc = SSMR3GetMem(pSSM, pTexture, sizeof(*pTexture));
1417 AssertRCReturn(rc, rc);
1418
1419 //DIRTY(pTexture->dirty, pContext->neg_bitid);
1420 //DIRTY(pTexture->imageBit, pContext->neg_bitid);
1421
1422 /*allocate actual memory*/
1423 for (i=0; i<6; ++i) {
1424 pTexture->level[i] = (CRTextureLevel *) crCalloc(sizeof(CRTextureLevel) * CR_MAX_MIPMAP_LEVELS);
1425 if (!pTexture->level[i]) return VERR_NO_MEMORY;
1426 }
1427
1428 rc = crStateLoadTextureObjData(pTexture, pSSM);
1429 AssertRCReturn(rc, rc);
1430
1431 crHashtableAdd(pContext->shared->textureTable, key, pTexture);
1432 }
1433
1434 /* Load current texture pointers */
1435 for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i)
1436 {
1437 rc = crStateLoadTexUnitCurrentTexturePtrs(&pContext->texture.unit[i], pContext, pSSM);
1438 AssertRCReturn(rc, rc);
1439 }
1440 //FILLDIRTY(GetCurrentBits()->texture.dirty);
1441
1442 /* Mark textures for resending to GPU */
1443 pContext->texture.bResyncNeeded = GL_TRUE;
1444
1445 /* Load lights */
1446 CRASSERT(pContext->lighting.light);
1447 rc = SSMR3GetMem(pSSM, pContext->lighting.light, CR_MAX_LIGHTS * sizeof(*pContext->lighting.light));
1448 AssertRCReturn(rc, rc);
1449
1450 /* Load attrib stack*/
1451 for ( i = 0 ; i < CR_MAX_ATTRIB_STACK_DEPTH ; i++)
1452 {
1453 if (pContext->attrib.enableStack[i].clip)
1454 {
1455 rc = crStateAllocAndSSMR3GetMem(pSSM, (void**)&pContext->attrib.enableStack[i].clip,
1456 pContext->limits.maxClipPlanes*sizeof(GLboolean));
1457 AssertRCReturn(rc, rc);
1458 }
1459
1460 if (pContext->attrib.enableStack[i].light)
1461 {
1462 rc = crStateAllocAndSSMR3GetMem(pSSM, (void**)&pContext->attrib.enableStack[i].light,
1463 pContext->limits.maxLights*sizeof(GLboolean));
1464 AssertRCReturn(rc, rc);
1465 }
1466
1467 if (pContext->attrib.lightingStack[i].light)
1468 {
1469 rc = crStateAllocAndSSMR3GetMem(pSSM, (void**)&pContext->attrib.lightingStack[i].light,
1470 pContext->limits.maxLights*sizeof(CRLight));
1471 AssertRCReturn(rc, rc);
1472 }
1473
1474 for (k=0; k<pContext->limits.maxTextureUnits; ++k)
1475 {
1476 rc = crStateLoadTexUnitCurrentTexturePtrs(&pContext->attrib.textureStack[i].unit[k], pContext, pSSM);
1477 AssertRCReturn(rc, rc);
1478 }
1479
1480 if (pContext->attrib.transformStack[i].clip)
1481 {
1482 rc = crStateAllocAndSSMR3GetMem(pSSM, (void*)&pContext->attrib.transformStack[i].clip,
1483 pContext->limits.maxClipPlanes*sizeof(GLboolean));
1484 AssertRCReturn(rc, rc);
1485 }
1486
1487 if (pContext->attrib.transformStack[i].clipPlane)
1488 {
1489 rc = crStateAllocAndSSMR3GetMem(pSSM, (void**)&pContext->attrib.transformStack[i].clipPlane,
1490 pContext->limits.maxClipPlanes*sizeof(GLvectord));
1491 AssertRCReturn(rc, rc);
1492 }
1493 rc = crSateLoadEvalCoeffs1D(pContext->attrib.evalStack[i].eval1D, GL_TRUE, pSSM);
1494 AssertRCReturn(rc, rc);
1495 rc = crSateLoadEvalCoeffs2D(pContext->attrib.evalStack[i].eval2D, GL_TRUE, pSSM);
1496 AssertRCReturn(rc, rc);
1497 }
1498
1499 /* Load evaluator coeffs */
1500 rc = crSateLoadEvalCoeffs1D(pContext->eval.eval1D, GL_FALSE, pSSM);
1501 AssertRCReturn(rc, rc);
1502 rc = crSateLoadEvalCoeffs2D(pContext->eval.eval2D, GL_FALSE, pSSM);
1503 AssertRCReturn(rc, rc);
1504
1505 /* Load buffer objects */
1506#ifdef CR_ARB_vertex_buffer_object
1507 rc = SSMR3GetU32(pSSM, &uiNumElems);
1508 AssertRCReturn(rc, rc);
1509 for (ui=0; ui<=uiNumElems; ++ui) /*ui<=uiNumElems to load nullBuffer in same loop*/
1510 {
1511 CRBufferObject *pBufferObj;
1512
1513 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
1514 AssertRCReturn(rc, rc);
1515
1516 /* default one should be already allocated */
1517 if (key==0)
1518 {
1519 pBufferObj = pContext->bufferobject.nullBuffer;
1520 if (!pBufferObj) return VERR_SSM_UNEXPECTED_DATA;
1521 }
1522 else
1523 {
1524 pBufferObj = (CRBufferObject *) crCalloc(sizeof(*pBufferObj));
1525 if (!pBufferObj) return VERR_NO_MEMORY;
1526 }
1527
1528 rc = SSMR3GetMem(pSSM, pBufferObj, sizeof(*pBufferObj));
1529 AssertRCReturn(rc, rc);
1530
1531 if (pBufferObj->data)
1532 {
1533 CRASSERT(pBufferObj->size>0);
1534 pBufferObj->data = crAlloc(pBufferObj->size);
1535 rc = SSMR3GetMem(pSSM, pBufferObj->data, pBufferObj->size);
1536 AssertRCReturn(rc, rc);
1537
1538 //DIRTY(pBufferObj->dirty, pContext->neg_bitid);
1539 //pBufferObj->dirtyStart = 0;
1540 //pBufferObj->dirtyLength = pBufferObj->size;
1541 }
1542 else if (pBufferObj->name!=0 && pBufferObj->size>0)
1543 {
1544 rc = SSMR3GetMem(pSSM, &pBufferObj->data, sizeof(pBufferObj->data));
1545 AssertRCReturn(rc, rc);
1546
1547 if (pBufferObj->data)
1548 {
1549 pBufferObj->data = crAlloc(pBufferObj->size);
1550 rc = SSMR3GetMem(pSSM, pBufferObj->data, pBufferObj->size);
1551 AssertRCReturn(rc, rc);
1552 }
1553 }
1554
1555
1556 if (key!=0)
1557 crHashtableAdd(pContext->bufferobject.buffers, key, pBufferObj);
1558 }
1559 //FILLDIRTY(GetCurrentBits()->bufferobject.dirty);
1560 /* Load pointers */
1561#define CRS_GET_BO(name) (((name)==0) ? (pContext->bufferobject.nullBuffer) : crHashtableSearch(pContext->bufferobject.buffers, name))
1562 rc = SSMR3GetU32(pSSM, &ui);
1563 AssertRCReturn(rc, rc);
1564 pContext->bufferobject.arrayBuffer = CRS_GET_BO(ui);
1565 rc = SSMR3GetU32(pSSM, &ui);
1566 AssertRCReturn(rc, rc);
1567 pContext->bufferobject.elementsBuffer = CRS_GET_BO(ui);
1568#undef CRS_GET_BO
1569
1570 /* Load client pointers and array buffer bindings*/
1571 for (i=0; i<CRSTATECLIENT_MAX_VERTEXARRAYS; ++i)
1572 {
1573 rc = crStateLoadClientPointer(&pContext->client.array, i, pContext, pSSM);
1574 AssertRCReturn(rc, rc);
1575 }
1576 for (j=0; j<pContext->client.vertexArrayStackDepth; ++j)
1577 {
1578 CRVertexArrays *pArray = &pContext->client.vertexArrayStack[j];
1579 for (i=0; i<CRSTATECLIENT_MAX_VERTEXARRAYS; ++i)
1580 {
1581 rc = crStateLoadClientPointer(pArray, i, pContext, pSSM);
1582 AssertRCReturn(rc, rc);
1583 }
1584 }
1585
1586 pContext->bufferobject.bResyncNeeded = GL_TRUE;
1587#endif
1588
1589 /* Load pixel/vertex programs */
1590 rc = SSMR3GetU32(pSSM, &uiNumElems);
1591 AssertRCReturn(rc, rc);
1592 /* Load defauls programs */
1593 rc = crStateLoadProgram(&pContext->program.defaultVertexProgram, pSSM);
1594 AssertRCReturn(rc, rc);
1595 //FILLDIRTY(pContext->program.defaultVertexProgram->dirtyProgram);
1596 rc = crStateLoadProgram(&pContext->program.defaultFragmentProgram, pSSM);
1597 AssertRCReturn(rc, rc);
1598 //FILLDIRTY(pContext->program.defaultFragmentProgram->dirtyProgram);
1599 /* Load all the rest */
1600 for (ui=0; ui<uiNumElems; ++ui)
1601 {
1602 CRProgram *pProgram = NULL;
1603 rc = crStateLoadProgram(&pProgram, pSSM);
1604 AssertRCReturn(rc, rc);
1605 crHashtableAdd(pContext->program.programHash, pProgram->id, pProgram);
1606 //DIRTY(pProgram->dirtyProgram, pContext->neg_bitid);
1607
1608 }
1609 //FILLDIRTY(GetCurrentBits()->program.dirty);
1610 /* Load Pointers */
1611 rc = SSMR3GetU32(pSSM, &ui);
1612 AssertRCReturn(rc, rc);
1613 pContext->program.currentVertexProgram = ui==0 ? pContext->program.defaultVertexProgram
1614 : crHashtableSearch(pContext->program.programHash, ui);
1615 rc = SSMR3GetU32(pSSM, &ui);
1616 AssertRCReturn(rc, rc);
1617 pContext->program.currentFragmentProgram = ui==0 ? pContext->program.defaultFragmentProgram
1618 : crHashtableSearch(pContext->program.programHash, ui);
1619
1620 /* Mark programs for resending to GPU */
1621 pContext->program.bResyncNeeded = GL_TRUE;
1622
1623#ifdef CR_EXT_framebuffer_object
1624 /* Load FBOs */
1625 rc = SSMR3GetU32(pSSM, &uiNumElems);
1626 AssertRCReturn(rc, rc);
1627 for (ui=0; ui<uiNumElems; ++ui)
1628 {
1629 CRFramebufferObject *pFBO;
1630 pFBO = crAlloc(sizeof(*pFBO));
1631 if (!pFBO) return VERR_NO_MEMORY;
1632
1633 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
1634 AssertRCReturn(rc, rc);
1635
1636 rc = SSMR3GetMem(pSSM, pFBO, sizeof(*pFBO));
1637 AssertRCReturn(rc, rc);
1638
1639 crHashtableAdd(pContext->framebufferobject.framebuffers, key, pFBO);
1640 }
1641
1642 rc = SSMR3GetU32(pSSM, &uiNumElems);
1643 AssertRCReturn(rc, rc);
1644 for (ui=0; ui<uiNumElems; ++ui)
1645 {
1646 CRRenderbufferObject *pRBO;
1647 pRBO = crAlloc(sizeof(*pRBO));
1648 if (!pRBO) return VERR_NO_MEMORY;
1649
1650 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
1651 AssertRCReturn(rc, rc);
1652
1653 rc = SSMR3GetMem(pSSM, pRBO, sizeof(*pRBO));
1654 AssertRCReturn(rc, rc);
1655
1656 crHashtableAdd(pContext->framebufferobject.renderbuffers, key, pRBO);
1657 }
1658
1659 rc = SSMR3GetU32(pSSM, &ui);
1660 AssertRCReturn(rc, rc);
1661 pContext->framebufferobject.drawFB = ui==0 ? NULL
1662 : crHashtableSearch(pContext->framebufferobject.framebuffers, ui);
1663
1664 rc = SSMR3GetU32(pSSM, &ui);
1665 AssertRCReturn(rc, rc);
1666 pContext->framebufferobject.readFB = ui==0 ? NULL
1667 : crHashtableSearch(pContext->framebufferobject.framebuffers, ui);
1668
1669 rc = SSMR3GetU32(pSSM, &ui);
1670 AssertRCReturn(rc, rc);
1671 pContext->framebufferobject.renderbuffer = ui==0 ? NULL
1672 : crHashtableSearch(pContext->framebufferobject.renderbuffers, ui);
1673
1674 /* Mark FBOs/RBOs for resending to GPU */
1675 pContext->framebufferobject.bResyncNeeded = GL_TRUE;
1676#endif
1677
1678#ifdef CR_OPENGL_VERSION_2_0
1679 /* Load GLSL related info */
1680 rc = SSMR3GetU32(pSSM, &uiNumElems);
1681 AssertRCReturn(rc, rc);
1682
1683 for (ui=0; ui<uiNumElems; ++ui)
1684 {
1685 CRGLSLShader *pShader = crStateLoadGLSLShader(pSSM);
1686 if (!pShader) return VERR_SSM_UNEXPECTED_DATA;
1687 crHashtableAdd(pContext->glsl.shaders, pShader->id, pShader);
1688 }
1689
1690 rc = SSMR3GetU32(pSSM, &uiNumElems);
1691 AssertRCReturn(rc, rc);
1692
1693 for (ui=0; ui<uiNumElems; ++ui)
1694 {
1695 CRGLSLProgram *pProgram;
1696 uint32_t numShaders;
1697
1698 pProgram = crAlloc(sizeof(*pProgram));
1699 if (!pProgram) return VERR_NO_MEMORY;
1700
1701 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
1702 AssertRCReturn(rc, rc);
1703
1704 rc = SSMR3GetMem(pSSM, pProgram, sizeof(*pProgram));
1705 AssertRCReturn(rc, rc);
1706
1707 crHashtableAdd(pContext->glsl.programs, key, pProgram);
1708
1709 pProgram->currentState.attachedShaders = crAllocHashtable();
1710
1711 rc = SSMR3GetU32(pSSM, &numShaders);
1712 AssertRCReturn(rc, rc);
1713
1714 for (k=0; k<numShaders; ++k)
1715 {
1716 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
1717 AssertRCReturn(rc, rc);
1718 crHashtableAdd(pProgram->currentState.attachedShaders, key, crHashtableSearch(pContext->glsl.shaders, key));
1719 }
1720
1721 if (pProgram->activeState.attachedShaders)
1722 {
1723 pProgram->activeState.attachedShaders = crAllocHashtable();
1724
1725 rc = SSMR3GetU32(pSSM, &numShaders);
1726 AssertRCReturn(rc, rc);
1727
1728 for (k=0; k<numShaders; ++k)
1729 {
1730 CRGLSLShader *pShader = crStateLoadGLSLShader(pSSM);
1731 if (!pShader) return VERR_SSM_UNEXPECTED_DATA;
1732 crHashtableAdd(pProgram->activeState.attachedShaders, pShader->id, pShader);
1733 }
1734 }
1735
1736 if (pProgram->currentState.cAttribs)
1737 pProgram->currentState.pAttribs = (CRGLSLAttrib*) crAlloc(pProgram->currentState.cAttribs*sizeof(CRGLSLAttrib));
1738 for (k=0; k<pProgram->currentState.cAttribs; ++k)
1739 {
1740 rc = SSMR3GetMem(pSSM, &pProgram->currentState.pAttribs[k].index, sizeof(pProgram->currentState.pAttribs[k].index));
1741 AssertRCReturn(rc, rc);
1742 pProgram->currentState.pAttribs[k].name = crStateLoadString(pSSM);
1743 }
1744
1745 if (pProgram->activeState.cAttribs)
1746 pProgram->activeState.pAttribs = (CRGLSLAttrib*) crAlloc(pProgram->activeState.cAttribs*sizeof(CRGLSLAttrib));
1747 for (k=0; k<pProgram->activeState.cAttribs; ++k)
1748 {
1749 rc = SSMR3GetMem(pSSM, &pProgram->activeState.pAttribs[k].index, sizeof(pProgram->activeState.pAttribs[k].index));
1750 AssertRCReturn(rc, rc);
1751 pProgram->activeState.pAttribs[k].name = crStateLoadString(pSSM);
1752 }
1753
1754 {
1755 int32_t cUniforms;
1756 rc = SSMR3GetS32(pSSM, &cUniforms);
1757 pProgram->cUniforms = cUniforms;
1758 AssertRCReturn(rc, rc);
1759 }
1760
1761 if (pProgram->cUniforms)
1762 {
1763 pProgram->pUniforms = crAlloc(pProgram->cUniforms*sizeof(CRGLSLUniform));
1764 if (!pProgram) return VERR_NO_MEMORY;
1765
1766 for (k=0; k<pProgram->cUniforms; ++k)
1767 {
1768 size_t itemsize, datasize;
1769
1770 rc = SSMR3GetMem(pSSM, &pProgram->pUniforms[k].type, sizeof(GLenum));
1771 pProgram->pUniforms[k].name = crStateLoadString(pSSM);
1772
1773 if (crStateIsIntUniform(pProgram->pUniforms[k].type))
1774 {
1775 itemsize = sizeof(GLint);
1776 } else itemsize = sizeof(GLfloat);
1777
1778 datasize = crStateGetUniformSize(pProgram->pUniforms[k].type)*itemsize;
1779 pProgram->pUniforms[k].data = crAlloc(datasize);
1780 if (!pProgram->pUniforms[k].data) return VERR_NO_MEMORY;
1781
1782 rc = SSMR3GetMem(pSSM, pProgram->pUniforms[k].data, datasize);
1783 }
1784 }
1785 }
1786
1787 rc = SSMR3GetU32(pSSM, &ui);
1788 AssertRCReturn(rc, rc);
1789 pContext->glsl.activeProgram = ui==0 ? NULL
1790 : crHashtableSearch(pContext->glsl.programs, ui);
1791
1792 /*Mark for resending to GPU*/
1793 pContext->glsl.bResyncNeeded = GL_TRUE;
1794#endif
1795
1796 {
1797 CRViewportState *pVP = &pContext->viewport;
1798 GLint cbData = crPixelSize(GL_RGBA, GL_UNSIGNED_BYTE) * pVP->viewportH * pVP->viewportW;
1799 void *pData = crAlloc(cbData);
1800
1801 if (!pData)
1802 {
1803 pContext->pImage = NULL;
1804 return VERR_NO_MEMORY;
1805 }
1806
1807 rc = SSMR3GetMem(pSSM, pData, cbData);
1808 AssertRCReturn(rc, rc);
1809
1810 pContext->pImage = pData;
1811 }
1812
1813 return VINF_SUCCESS;
1814}
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