VirtualBox

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

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

crOpenGL: cache uniforms info

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