VirtualBox

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

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

crOpenGL: snapshots support for GLSL shaders

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 56.5 KB
Line 
1/* $Id: state_snapshot.c 23274 2009-09-24 09:31:32Z 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 if (size!=1) crWarning("@todo");
736
737 rc = SSMR3PutMem(pSSM, &type, sizeof(type));
738 CRASSERT(rc == VINF_SUCCESS);
739
740 crStateSaveString(name, pSSM);
741
742 if (GL_INT==type
743 || GL_INT_VEC2==type
744 || GL_INT_VEC3==type
745 || GL_INT_VEC4==type
746 || GL_BOOL==type
747 || GL_BOOL_VEC2==type
748 || GL_BOOL_VEC3==type
749 || GL_BOOL_VEC4==type
750 || GL_SAMPLER_1D==type
751 || GL_SAMPLER_2D==type
752 || GL_SAMPLER_3D==type
753 || GL_SAMPLER_CUBE==type
754 || GL_SAMPLER_1D_SHADOW==type
755 || GL_SAMPLER_2D_SHADOW==type)
756 {
757 diff_api.GetUniformiv(pProgram->hwid, i, &idata[0]);
758 rc = SSMR3PutMem(pSSM, &idata[0], crStateGetUniformSize(type)*sizeof(idata[0]));
759 CRASSERT(rc == VINF_SUCCESS);
760 }
761 else
762 {
763 diff_api.GetUniformfv(pProgram->hwid, i, &fdata[0]);
764 rc = SSMR3PutMem(pSSM, &fdata[0], crStateGetUniformSize(type)*sizeof(fdata[0]));
765 CRASSERT(rc == VINF_SUCCESS);
766 }
767 }
768
769 crFree(name);
770 }
771}
772
773int32_t crStateSaveContext(CRContext *pContext, PSSMHANDLE pSSM)
774{
775 int32_t rc, i;
776 uint32_t ui32, j;
777
778 CRASSERT(pContext && pSSM);
779
780 rc = SSMR3PutMem(pSSM, pContext, sizeof(*pContext));
781 AssertRCReturn(rc, rc);
782
783 if (crHashtableNumElements(pContext->shared->dlistTable)>0)
784 crWarning("Saving state with %d display lists, unsupported", crHashtableNumElements(pContext->shared->dlistTable));
785
786 if (crHashtableNumElements(pContext->program.programHash)>0)
787 crDebug("Saving state with %d programs", crHashtableNumElements(pContext->program.programHash));
788
789 /* Save transform state */
790 rc = SSMR3PutMem(pSSM, pContext->transform.clipPlane, sizeof(GLvectord)*CR_MAX_CLIP_PLANES);
791 AssertRCReturn(rc, rc);
792 rc = SSMR3PutMem(pSSM, pContext->transform.clip, sizeof(GLboolean)*CR_MAX_CLIP_PLANES);
793 AssertRCReturn(rc, rc);
794 rc = crStateSaveMatrixStack(&pContext->transform.modelViewStack, pSSM);
795 AssertRCReturn(rc, rc);
796 rc = crStateSaveMatrixStack(&pContext->transform.projectionStack, pSSM);
797 AssertRCReturn(rc, rc);
798 rc = crStateSaveMatrixStack(&pContext->transform.colorStack, pSSM);
799 AssertRCReturn(rc, rc);
800 for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
801 {
802 rc = crStateSaveMatrixStack(&pContext->transform.textureStack[i], pSSM);
803 AssertRCReturn(rc, rc);
804 }
805 for (i = 0 ; i < CR_MAX_PROGRAM_MATRICES ; i++)
806 {
807 rc = crStateSaveMatrixStack(&pContext->transform.programStack[i], pSSM);
808 AssertRCReturn(rc, rc);
809 }
810
811 /* Save textures */
812 rc = crStateSaveTextureObjData(&pContext->texture.base1D, pSSM);
813 AssertRCReturn(rc, rc);
814 rc = crStateSaveTextureObjData(&pContext->texture.base2D, pSSM);
815 AssertRCReturn(rc, rc);
816 rc = crStateSaveTextureObjData(&pContext->texture.base3D, pSSM);
817 AssertRCReturn(rc, rc);
818 rc = crStateSaveTextureObjData(&pContext->texture.proxy1D, pSSM);
819 AssertRCReturn(rc, rc);
820 rc = crStateSaveTextureObjData(&pContext->texture.proxy2D, pSSM);
821 AssertRCReturn(rc, rc);
822 rc = crStateSaveTextureObjData(&pContext->texture.proxy3D, pSSM);
823#ifdef CR_ARB_texture_cube_map
824 rc = crStateSaveTextureObjData(&pContext->texture.baseCubeMap, pSSM);
825 AssertRCReturn(rc, rc);
826 rc = crStateSaveTextureObjData(&pContext->texture.proxyCubeMap, pSSM);
827 AssertRCReturn(rc, rc);
828#endif
829#ifdef CR_NV_texture_rectangle
830 rc = crStateSaveTextureObjData(&pContext->texture.baseRect, pSSM);
831 AssertRCReturn(rc, rc);
832 rc = crStateSaveTextureObjData(&pContext->texture.proxyRect, pSSM);
833 AssertRCReturn(rc, rc);
834#endif
835
836 /* Save shared textures */
837 CRASSERT(pContext->shared && pContext->shared->textureTable);
838 ui32 = crHashtableNumElements(pContext->shared->textureTable);
839 rc = SSMR3PutU32(pSSM, ui32);
840 AssertRCReturn(rc, rc);
841 crHashtableWalk(pContext->shared->textureTable, crStateSaveSharedTextureCB, pSSM);
842
843#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
844 /* Restore previous texture bindings via diff_api */
845 if (ui32)
846 {
847 CRTextureUnit *pTexUnit;
848
849 pTexUnit = &pContext->texture.unit[pContext->texture.curTextureUnit];
850
851 diff_api.BindTexture(GL_TEXTURE_1D, pTexUnit->currentTexture1D->name);
852 diff_api.BindTexture(GL_TEXTURE_2D, pTexUnit->currentTexture2D->name);
853 diff_api.BindTexture(GL_TEXTURE_3D, pTexUnit->currentTexture3D->name);
854#ifdef CR_ARB_texture_cube_map
855 diff_api.BindTexture(GL_TEXTURE_CUBE_MAP_ARB, pTexUnit->currentTextureCubeMap->name);
856#endif
857#ifdef CR_NV_texture_rectangle
858 diff_api.BindTexture(GL_TEXTURE_RECTANGLE_NV, pTexUnit->currentTextureRect->name);
859#endif
860 }
861#endif
862
863 /* Save current texture pointers */
864 for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i)
865 {
866 rc = crStateSaveTexUnitCurrentTexturePtrs(&pContext->texture.unit[i], pSSM);
867 AssertRCReturn(rc, rc);
868 }
869
870 /* Save lights */
871 CRASSERT(pContext->lighting.light);
872 rc = SSMR3PutMem(pSSM, pContext->lighting.light, CR_MAX_LIGHTS * sizeof(*pContext->lighting.light));
873 AssertRCReturn(rc, rc);
874
875 /* Save attrib stack*/
876 /*@todo could go up to used stack depth here?*/
877 for ( i = 0 ; i < CR_MAX_ATTRIB_STACK_DEPTH ; i++)
878 {
879 if (pContext->attrib.enableStack[i].clip)
880 {
881 rc = SSMR3PutMem(pSSM, pContext->attrib.enableStack[i].clip,
882 pContext->limits.maxClipPlanes*sizeof(GLboolean));
883 AssertRCReturn(rc, rc);
884 }
885
886 if (pContext->attrib.enableStack[i].light)
887 {
888 rc = SSMR3PutMem(pSSM, pContext->attrib.enableStack[i].light,
889 pContext->limits.maxLights*sizeof(GLboolean));
890 AssertRCReturn(rc, rc);
891 }
892
893 if (pContext->attrib.lightingStack[i].light)
894 {
895 rc = SSMR3PutMem(pSSM, pContext->attrib.lightingStack[i].light,
896 pContext->limits.maxLights*sizeof(CRLight));
897 AssertRCReturn(rc, rc);
898 }
899
900 for (j=0; j<pContext->limits.maxTextureUnits; ++j)
901 {
902 rc = crStateSaveTexUnitCurrentTexturePtrs(&pContext->attrib.textureStack[i].unit[j], pSSM);
903 AssertRCReturn(rc, rc);
904 }
905
906 if (pContext->attrib.transformStack[i].clip)
907 {
908 rc = SSMR3PutMem(pSSM, pContext->attrib.transformStack[i].clip,
909 pContext->limits.maxClipPlanes*sizeof(GLboolean));
910 AssertRCReturn(rc, rc);
911 }
912
913 if (pContext->attrib.transformStack[i].clipPlane)
914 {
915 rc = SSMR3PutMem(pSSM, pContext->attrib.transformStack[i].clipPlane,
916 pContext->limits.maxClipPlanes*sizeof(GLvectord));
917 AssertRCReturn(rc, rc);
918 }
919
920 rc = crSateSaveEvalCoeffs1D(pContext->attrib.evalStack[i].eval1D, pSSM);
921 AssertRCReturn(rc, rc);
922 rc = crSateSaveEvalCoeffs2D(pContext->attrib.evalStack[i].eval2D, pSSM);
923 AssertRCReturn(rc, rc);
924 }
925
926 /* Save evaluator coeffs */
927 rc = crSateSaveEvalCoeffs1D(pContext->eval.eval1D, pSSM);
928 AssertRCReturn(rc, rc);
929 rc = crSateSaveEvalCoeffs2D(pContext->eval.eval2D, pSSM);
930 AssertRCReturn(rc, rc);
931
932#ifdef CR_ARB_vertex_buffer_object
933 /* Save buffer objects */
934 ui32 = crHashtableNumElements(pContext->bufferobject.buffers);
935 rc = SSMR3PutU32(pSSM, ui32);
936 AssertRCReturn(rc, rc);
937 /* Save default one*/
938 crStateSaveBufferObjectCB(0, pContext->bufferobject.nullBuffer, pSSM);
939 /* Save all the rest */
940 crHashtableWalk(pContext->bufferobject.buffers, crStateSaveBufferObjectCB, pSSM);
941 /* Restore binding */
942 diff_api.BindBufferARB(GL_ARRAY_BUFFER_ARB, pContext->bufferobject.arrayBuffer->name);
943 /* Save pointers */
944 rc = SSMR3PutU32(pSSM, pContext->bufferobject.arrayBuffer->name);
945 AssertRCReturn(rc, rc);
946 rc = SSMR3PutU32(pSSM, pContext->bufferobject.elementsBuffer->name);
947 AssertRCReturn(rc, rc);
948 /* Save bound array buffers*/ /*@todo vertexArrayStack*/
949 rc = SSMR3PutU32(pSSM, pContext->client.array.v.buffer->name);
950 AssertRCReturn(rc, rc);
951 rc = SSMR3PutU32(pSSM, pContext->client.array.c.buffer->name);
952 AssertRCReturn(rc, rc);
953 rc = SSMR3PutU32(pSSM, pContext->client.array.f.buffer->name);
954 AssertRCReturn(rc, rc);
955 rc = SSMR3PutU32(pSSM, pContext->client.array.s.buffer->name);
956 AssertRCReturn(rc, rc);
957 rc = SSMR3PutU32(pSSM, pContext->client.array.e.buffer->name);
958 AssertRCReturn(rc, rc);
959 rc = SSMR3PutU32(pSSM, pContext->client.array.i.buffer->name);
960 AssertRCReturn(rc, rc);
961 rc = SSMR3PutU32(pSSM, pContext->client.array.n.buffer->name);
962 AssertRCReturn(rc, rc);
963 for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++)
964 {
965 rc = SSMR3PutU32(pSSM, pContext->client.array.t[i].buffer->name);
966 AssertRCReturn(rc, rc);
967 }
968# ifdef CR_NV_vertex_program
969 for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++)
970 {
971 rc = SSMR3PutU32(pSSM, pContext->client.array.a[i].buffer->name);
972 AssertRCReturn(rc, rc);
973 }
974# endif
975#endif /*CR_ARB_vertex_buffer_object*/
976
977 /* Save pixel/vertex programs */
978 ui32 = crHashtableNumElements(pContext->program.programHash);
979 rc = SSMR3PutU32(pSSM, ui32);
980 AssertRCReturn(rc, rc);
981 /* Save defauls programs */
982 crStateSaveProgramCB(0, pContext->program.defaultVertexProgram, pSSM);
983 crStateSaveProgramCB(0, pContext->program.defaultFragmentProgram, pSSM);
984 /* Save all the rest */
985 crHashtableWalk(pContext->program.programHash, crStateSaveProgramCB, pSSM);
986 /* Save Pointers */
987 rc = SSMR3PutU32(pSSM, pContext->program.currentVertexProgram->id);
988 AssertRCReturn(rc, rc);
989 rc = SSMR3PutU32(pSSM, pContext->program.currentFragmentProgram->id);
990 AssertRCReturn(rc, rc);
991 /* This one is unused it seems*/
992 CRASSERT(!pContext->program.errorString);
993
994#ifdef CR_EXT_framebuffer_object
995 /* Save FBOs */
996 ui32 = crHashtableNumElements(pContext->framebufferobject.framebuffers);
997 rc = SSMR3PutU32(pSSM, ui32);
998 AssertRCReturn(rc, rc);
999 crHashtableWalk(pContext->framebufferobject.framebuffers, crStateSaveFramebuffersCB, pSSM);
1000 ui32 = crHashtableNumElements(pContext->framebufferobject.renderbuffers);
1001 rc = SSMR3PutU32(pSSM, ui32);
1002 AssertRCReturn(rc, rc);
1003 crHashtableWalk(pContext->framebufferobject.renderbuffers, crStateSaveRenderbuffersCB, pSSM);
1004 rc = SSMR3PutU32(pSSM, pContext->framebufferobject.framebuffer?pContext->framebufferobject.framebuffer->id:0);
1005 AssertRCReturn(rc, rc);
1006 rc = SSMR3PutU32(pSSM, pContext->framebufferobject.renderbuffer?pContext->framebufferobject.renderbuffer->id:0);
1007 AssertRCReturn(rc, rc);
1008#endif
1009
1010#ifdef CR_OPENGL_VERSION_2_0
1011 /* Save GLSL related info */
1012 ui32 = crHashtableNumElements(pContext->glsl.shaders);
1013 rc = SSMR3PutU32(pSSM, ui32);
1014 AssertRCReturn(rc, rc);
1015 crHashtableWalk(pContext->glsl.shaders, crStateSaveGLSLShaderCB, pSSM);
1016 ui32 = crHashtableNumElements(pContext->glsl.programs);
1017 rc = SSMR3PutU32(pSSM, ui32);
1018 AssertRCReturn(rc, rc);
1019 crHashtableWalk(pContext->glsl.programs, crStateSaveGLSLProgramCB, pSSM);
1020 rc = SSMR3PutU32(pSSM, pContext->glsl.activeProgram?pContext->glsl.activeProgram->id:0);
1021 AssertRCReturn(rc, rc);
1022#endif
1023
1024 return VINF_SUCCESS;
1025}
1026
1027#define SLC_COPYPTR(ptr) pTmpContext->ptr = pContext->ptr
1028#define SLC_ASSSERT_NULL_PTR(ptr) CRASSERT(!pContext->ptr)
1029
1030int32_t crStateLoadContext(CRContext *pContext, PSSMHANDLE pSSM)
1031{
1032 CRContext* pTmpContext;
1033 int32_t rc, i, j;
1034 uint32_t uiNumElems, ui, k;
1035 unsigned long key;
1036
1037 CRASSERT(pContext && pSSM);
1038
1039 /* This one is rather big for stack allocation and causes macs to crash */
1040 pTmpContext = (CRContext*)crAlloc(sizeof(*pTmpContext));
1041 if (!pTmpContext)
1042 return VERR_NO_MEMORY;
1043
1044 rc = SSMR3GetMem(pSSM, pTmpContext, sizeof(*pTmpContext));
1045 AssertRCReturn(rc, rc);
1046
1047 SLC_COPYPTR(shared);
1048 SLC_COPYPTR(flush_func);
1049 SLC_COPYPTR(flush_arg);
1050
1051 /* We're supposed to be loading into an empty context, so those pointers should be NULL */
1052 for ( i = 0 ; i < CR_MAX_ATTRIB_STACK_DEPTH ; i++)
1053 {
1054 SLC_ASSSERT_NULL_PTR(attrib.enableStack[i].clip);
1055 SLC_ASSSERT_NULL_PTR(attrib.enableStack[i].light);
1056
1057 SLC_ASSSERT_NULL_PTR(attrib.lightingStack[i].light);
1058 SLC_ASSSERT_NULL_PTR(attrib.transformStack[i].clip);
1059 SLC_ASSSERT_NULL_PTR(attrib.transformStack[i].clipPlane);
1060
1061 for (j=0; j<GLEVAL_TOT; ++j)
1062 {
1063 SLC_ASSSERT_NULL_PTR(attrib.evalStack[i].eval1D[j].coeff);
1064 SLC_ASSSERT_NULL_PTR(attrib.evalStack[i].eval2D[j].coeff);
1065 }
1066 }
1067
1068#ifdef CR_ARB_vertex_buffer_object
1069 SLC_COPYPTR(bufferobject.buffers);
1070 SLC_COPYPTR(bufferobject.nullBuffer);
1071#endif
1072
1073/*@todo, that should be removed probably as those should hold the offset values, so loading should be fine
1074 but better check*/
1075#if 0
1076#ifdef CR_EXT_compiled_vertex_array
1077 SLC_COPYPTR(client.array.v.prevPtr);
1078 SLC_COPYPTR(client.array.c.prevPtr);
1079 SLC_COPYPTR(client.array.f.prevPtr);
1080 SLC_COPYPTR(client.array.s.prevPtr);
1081 SLC_COPYPTR(client.array.e.prevPtr);
1082 SLC_COPYPTR(client.array.i.prevPtr);
1083 SLC_COPYPTR(client.array.n.prevPtr);
1084 for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
1085 {
1086 SLC_COPYPTR(client.array.t[i].prevPtr);
1087 }
1088
1089# ifdef CR_NV_vertex_program
1090 for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++)
1091 {
1092 SLC_COPYPTR(client.array.a[i].prevPtr);
1093 }
1094# endif
1095#endif
1096#endif
1097
1098#ifdef CR_ARB_vertex_buffer_object
1099 /*That just sets those pointers to NULL*/
1100 SLC_COPYPTR(client.array.v.buffer);
1101 SLC_COPYPTR(client.array.c.buffer);
1102 SLC_COPYPTR(client.array.f.buffer);
1103 SLC_COPYPTR(client.array.s.buffer);
1104 SLC_COPYPTR(client.array.e.buffer);
1105 SLC_COPYPTR(client.array.i.buffer);
1106 SLC_COPYPTR(client.array.n.buffer);
1107 for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
1108 {
1109 SLC_COPYPTR(client.array.t[i].buffer);
1110 }
1111# ifdef CR_NV_vertex_program
1112 for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++)
1113 {
1114 SLC_COPYPTR(client.array.a[i].buffer);
1115 }
1116# endif
1117#endif /*CR_ARB_vertex_buffer_object*/
1118
1119 /*@todo CR_NV_vertex_program*/
1120 crStateCopyEvalPtrs1D(pTmpContext->eval.eval1D, pContext->eval.eval1D);
1121 crStateCopyEvalPtrs2D(pTmpContext->eval.eval2D, pContext->eval.eval2D);
1122
1123 SLC_COPYPTR(feedback.buffer); /*@todo*/
1124 SLC_COPYPTR(selection.buffer); /*@todo*/
1125
1126 SLC_COPYPTR(lighting.light);
1127
1128 /*This one could be tricky if we're loading snapshot on host with different GPU*/
1129 SLC_COPYPTR(limits.extensions);
1130
1131#if CR_ARB_occlusion_query
1132 SLC_COPYPTR(occlusion.objects); /*@todo*/
1133#endif
1134
1135 SLC_COPYPTR(program.errorString);
1136 SLC_COPYPTR(program.programHash);
1137 SLC_COPYPTR(program.defaultVertexProgram);
1138 SLC_COPYPTR(program.defaultFragmentProgram);
1139
1140 /* Texture pointers */
1141 for (i=0; i<6; ++i)
1142 {
1143 SLC_COPYPTR(texture.base1D.level[i]);
1144 SLC_COPYPTR(texture.base2D.level[i]);
1145 SLC_COPYPTR(texture.base3D.level[i]);
1146 SLC_COPYPTR(texture.proxy1D.level[i]);
1147 SLC_COPYPTR(texture.proxy2D.level[i]);
1148 SLC_COPYPTR(texture.proxy3D.level[i]);
1149#ifdef CR_ARB_texture_cube_map
1150 SLC_COPYPTR(texture.baseCubeMap.level[i]);
1151 SLC_COPYPTR(texture.proxyCubeMap.level[i]);
1152#endif
1153#ifdef CR_NV_texture_rectangle
1154 SLC_COPYPTR(texture.baseRect.level[i]);
1155 SLC_COPYPTR(texture.proxyRect.level[i]);
1156#endif
1157 }
1158
1159 /* Load transform state */
1160 SLC_COPYPTR(transform.clipPlane);
1161 SLC_COPYPTR(transform.clip);
1162 /* Don't have to worry about pContext->transform.current as it'd be set in crStateSetCurrent call */
1163 /*SLC_COPYPTR(transform.currentStack);*/
1164 SLC_COPYPTR(transform.modelViewStack.stack);
1165 SLC_COPYPTR(transform.projectionStack.stack);
1166 SLC_COPYPTR(transform.colorStack.stack);
1167
1168 for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
1169 {
1170 SLC_COPYPTR(transform.textureStack[i].stack);
1171 }
1172 for (i = 0 ; i < CR_MAX_PROGRAM_MATRICES ; i++)
1173 {
1174 SLC_COPYPTR(transform.programStack[i].stack);
1175 }
1176
1177#ifdef CR_EXT_framebuffer_object
1178 SLC_COPYPTR(framebufferobject.framebuffers);
1179 SLC_COPYPTR(framebufferobject.renderbuffers);
1180#endif
1181
1182#ifdef CR_OPENGL_VERSION_2_0
1183 SLC_COPYPTR(glsl.shaders);
1184 SLC_COPYPTR(glsl.programs);
1185#endif
1186
1187 /* Have to preserve original context id */
1188 CRASSERT(pTmpContext->id == pContext->id);
1189 /* Copy ordinary state to real context */
1190 crMemcpy(pContext, pTmpContext, sizeof(*pTmpContext));
1191 crFree(pTmpContext);
1192 pTmpContext = NULL;
1193
1194 /* Now deal with pointers */
1195
1196 /* Load transform state */
1197 rc = SSMR3GetMem(pSSM, pContext->transform.clipPlane, sizeof(GLvectord)*CR_MAX_CLIP_PLANES);
1198 AssertRCReturn(rc, rc);
1199 rc = SSMR3GetMem(pSSM, pContext->transform.clip, sizeof(GLboolean)*CR_MAX_CLIP_PLANES);
1200 AssertRCReturn(rc, rc);
1201 rc = crStateLoadMatrixStack(&pContext->transform.modelViewStack, pSSM);
1202 AssertRCReturn(rc, rc);
1203 rc = crStateLoadMatrixStack(&pContext->transform.projectionStack, pSSM);
1204 AssertRCReturn(rc, rc);
1205 rc = crStateLoadMatrixStack(&pContext->transform.colorStack, pSSM);
1206 AssertRCReturn(rc, rc);
1207 for (i = 0 ; i < CR_MAX_TEXTURE_UNITS ; i++)
1208 {
1209 rc = crStateLoadMatrixStack(&pContext->transform.textureStack[i], pSSM);
1210 AssertRCReturn(rc, rc);
1211 }
1212 for (i = 0 ; i < CR_MAX_PROGRAM_MATRICES ; i++)
1213 {
1214 rc = crStateLoadMatrixStack(&pContext->transform.programStack[i], pSSM);
1215 AssertRCReturn(rc, rc);
1216 }
1217
1218 /* Load Textures */
1219 rc = crStateLoadTextureObjData(&pContext->texture.base1D, pSSM);
1220 AssertRCReturn(rc, rc);
1221 rc = crStateLoadTextureObjData(&pContext->texture.base2D, pSSM);
1222 AssertRCReturn(rc, rc);
1223 rc = crStateLoadTextureObjData(&pContext->texture.base3D, pSSM);
1224 AssertRCReturn(rc, rc);
1225 rc = crStateLoadTextureObjData(&pContext->texture.proxy1D, pSSM);
1226 AssertRCReturn(rc, rc);
1227 rc = crStateLoadTextureObjData(&pContext->texture.proxy2D, pSSM);
1228 AssertRCReturn(rc, rc);
1229 rc = crStateLoadTextureObjData(&pContext->texture.proxy3D, pSSM);
1230 AssertRCReturn(rc, rc);
1231#ifdef CR_ARB_texture_cube_map
1232 rc = crStateLoadTextureObjData(&pContext->texture.baseCubeMap, pSSM);
1233 AssertRCReturn(rc, rc);
1234 rc = crStateLoadTextureObjData(&pContext->texture.proxyCubeMap, pSSM);
1235 AssertRCReturn(rc, rc);
1236#endif
1237#ifdef CR_NV_texture_rectangle
1238 rc = crStateLoadTextureObjData(&pContext->texture.baseRect, pSSM);
1239 AssertRCReturn(rc, rc);
1240 rc = crStateLoadTextureObjData(&pContext->texture.proxyRect, pSSM);
1241 AssertRCReturn(rc, rc);
1242#endif
1243
1244 /* Load shared textures */
1245 CRASSERT(pContext->shared && pContext->shared->textureTable);
1246 rc = SSMR3GetU32(pSSM, &uiNumElems);
1247 AssertRCReturn(rc, rc);
1248 for (ui=0; ui<uiNumElems; ++ui)
1249 {
1250 CRTextureObj *pTexture;
1251
1252 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
1253 AssertRCReturn(rc, rc);
1254
1255 pTexture = (CRTextureObj *) crCalloc(sizeof(CRTextureObj));
1256 if (!pTexture) return VERR_NO_MEMORY;
1257
1258 rc = SSMR3GetMem(pSSM, pTexture, sizeof(*pTexture));
1259 AssertRCReturn(rc, rc);
1260
1261 //DIRTY(pTexture->dirty, pContext->neg_bitid);
1262 //DIRTY(pTexture->imageBit, pContext->neg_bitid);
1263
1264 /*allocate actual memory*/
1265 for (i=0; i<6; ++i) {
1266 pTexture->level[i] = (CRTextureLevel *) crCalloc(sizeof(CRTextureLevel) * MAX_MIPMAP_LEVELS);
1267 if (!pTexture->level[i]) return VERR_NO_MEMORY;
1268 }
1269
1270 rc = crStateLoadTextureObjData(pTexture, pSSM);
1271 AssertRCReturn(rc, rc);
1272
1273 crHashtableAdd(pContext->shared->textureTable, key, pTexture);
1274 }
1275
1276 /* Load current texture pointers */
1277 for (i=0; i<CR_MAX_TEXTURE_UNITS; ++i)
1278 {
1279 rc = crStateLoadTexUnitCurrentTexturePtrs(&pContext->texture.unit[i], pContext, pSSM);
1280 AssertRCReturn(rc, rc);
1281 }
1282 //FILLDIRTY(GetCurrentBits()->texture.dirty);
1283
1284 /* Mark textures for resending to GPU */
1285 pContext->texture.bResyncNeeded = GL_TRUE;
1286
1287 /* Load lights */
1288 CRASSERT(pContext->lighting.light);
1289 rc = SSMR3GetMem(pSSM, pContext->lighting.light, CR_MAX_LIGHTS * sizeof(*pContext->lighting.light));
1290 AssertRCReturn(rc, rc);
1291
1292 /* Load attrib stack*/
1293 for ( i = 0 ; i < CR_MAX_ATTRIB_STACK_DEPTH ; i++)
1294 {
1295 if (pContext->attrib.enableStack[i].clip)
1296 {
1297 rc = crStateAllocAndSSMR3GetMem(pSSM, (void**)&pContext->attrib.enableStack[i].clip,
1298 pContext->limits.maxClipPlanes*sizeof(GLboolean));
1299 AssertRCReturn(rc, rc);
1300 }
1301
1302 if (pContext->attrib.enableStack[i].light)
1303 {
1304 rc = crStateAllocAndSSMR3GetMem(pSSM, (void**)&pContext->attrib.enableStack[i].light,
1305 pContext->limits.maxLights*sizeof(GLboolean));
1306 AssertRCReturn(rc, rc);
1307 }
1308
1309 if (pContext->attrib.lightingStack[i].light)
1310 {
1311 rc = crStateAllocAndSSMR3GetMem(pSSM, (void**)&pContext->attrib.lightingStack[i].light,
1312 pContext->limits.maxLights*sizeof(CRLight));
1313 AssertRCReturn(rc, rc);
1314 }
1315
1316 for (k=0; k<pContext->limits.maxTextureUnits; ++k)
1317 {
1318 rc = crStateLoadTexUnitCurrentTexturePtrs(&pContext->attrib.textureStack[i].unit[k], pContext, pSSM);
1319 AssertRCReturn(rc, rc);
1320 }
1321
1322 if (pContext->attrib.transformStack[i].clip)
1323 {
1324 rc = crStateAllocAndSSMR3GetMem(pSSM, (void*)&pContext->attrib.transformStack[i].clip,
1325 pContext->limits.maxClipPlanes*sizeof(GLboolean));
1326 AssertRCReturn(rc, rc);
1327 }
1328
1329 if (pContext->attrib.transformStack[i].clipPlane)
1330 {
1331 rc = crStateAllocAndSSMR3GetMem(pSSM, (void**)&pContext->attrib.transformStack[i].clipPlane,
1332 pContext->limits.maxClipPlanes*sizeof(GLvectord));
1333 AssertRCReturn(rc, rc);
1334 }
1335 rc = crSateLoadEvalCoeffs1D(pContext->attrib.evalStack[i].eval1D, GL_TRUE, pSSM);
1336 AssertRCReturn(rc, rc);
1337 rc = crSateLoadEvalCoeffs2D(pContext->attrib.evalStack[i].eval2D, GL_TRUE, pSSM);
1338 AssertRCReturn(rc, rc);
1339 }
1340
1341 /* Load evaluator coeffs */
1342 rc = crSateLoadEvalCoeffs1D(pContext->eval.eval1D, GL_FALSE, pSSM);
1343 AssertRCReturn(rc, rc);
1344 rc = crSateLoadEvalCoeffs2D(pContext->eval.eval2D, GL_FALSE, pSSM);
1345 AssertRCReturn(rc, rc);
1346
1347 /* Load buffer objects */
1348#ifdef CR_ARB_vertex_buffer_object
1349 rc = SSMR3GetU32(pSSM, &uiNumElems);
1350 AssertRCReturn(rc, rc);
1351 for (ui=0; ui<=uiNumElems; ++ui) /*ui<=uiNumElems to load nullBuffer in same loop*/
1352 {
1353 CRBufferObject *pBufferObj;
1354
1355 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
1356 AssertRCReturn(rc, rc);
1357
1358 /* default one should be already allocated */
1359 if (key==0)
1360 {
1361 pBufferObj = pContext->bufferobject.nullBuffer;
1362 if (!pBufferObj) return VERR_SSM_UNEXPECTED_DATA;
1363 }
1364 else
1365 {
1366 pBufferObj = (CRBufferObject *) crCalloc(sizeof(*pBufferObj));
1367 if (!pBufferObj) return VERR_NO_MEMORY;
1368 }
1369
1370 rc = SSMR3GetMem(pSSM, pBufferObj, sizeof(*pBufferObj));
1371 AssertRCReturn(rc, rc);
1372
1373 if (pBufferObj->data)
1374 {
1375 CRASSERT(pBufferObj->size>0);
1376 pBufferObj->data = crAlloc(pBufferObj->size);
1377 rc = SSMR3GetMem(pSSM, pBufferObj->data, pBufferObj->size);
1378 AssertRCReturn(rc, rc);
1379
1380 //DIRTY(pBufferObj->dirty, pContext->neg_bitid);
1381 //pBufferObj->dirtyStart = 0;
1382 //pBufferObj->dirtyLength = pBufferObj->size;
1383 }
1384 else if (pBufferObj->name!=0 && pBufferObj->size>0)
1385 {
1386 rc = SSMR3GetMem(pSSM, &pBufferObj->data, sizeof(pBufferObj->data));
1387 AssertRCReturn(rc, rc);
1388
1389 if (pBufferObj->data)
1390 {
1391 pBufferObj->data = crAlloc(pBufferObj->size);
1392 rc = SSMR3GetMem(pSSM, pBufferObj->data, pBufferObj->size);
1393 AssertRCReturn(rc, rc);
1394 }
1395 }
1396
1397
1398 if (key!=0)
1399 crHashtableAdd(pContext->bufferobject.buffers, key, pBufferObj);
1400 }
1401 //FILLDIRTY(GetCurrentBits()->bufferobject.dirty);
1402 /* Load pointers */
1403#define CRS_GET_BO(name) (((name)==0) ? (pContext->bufferobject.nullBuffer) : crHashtableSearch(pContext->bufferobject.buffers, name))
1404 rc = SSMR3GetU32(pSSM, &ui);
1405 AssertRCReturn(rc, rc);
1406 pContext->bufferobject.arrayBuffer = CRS_GET_BO(ui);
1407 rc = SSMR3GetU32(pSSM, &ui);
1408 AssertRCReturn(rc, rc);
1409 pContext->bufferobject.elementsBuffer = CRS_GET_BO(ui);
1410
1411 /* Load bound array buffers*/
1412 rc = SSMR3GetU32(pSSM, &ui);
1413 AssertRCReturn(rc, rc);
1414 pContext->client.array.v.buffer = CRS_GET_BO(ui);
1415
1416 rc = SSMR3GetU32(pSSM, &ui);
1417 AssertRCReturn(rc, rc);
1418 pContext->client.array.c.buffer = CRS_GET_BO(ui);
1419
1420 rc = SSMR3GetU32(pSSM, &ui);
1421 AssertRCReturn(rc, rc);
1422 pContext->client.array.f.buffer = CRS_GET_BO(ui);
1423
1424 rc = SSMR3GetU32(pSSM, &ui);
1425 AssertRCReturn(rc, rc);
1426 pContext->client.array.s.buffer = CRS_GET_BO(ui);
1427
1428 rc = SSMR3GetU32(pSSM, &ui);
1429 AssertRCReturn(rc, rc);
1430 pContext->client.array.e.buffer = CRS_GET_BO(ui);
1431
1432 rc = SSMR3GetU32(pSSM, &ui);
1433 AssertRCReturn(rc, rc);
1434 pContext->client.array.i.buffer = CRS_GET_BO(ui);
1435
1436 rc = SSMR3GetU32(pSSM, &ui);
1437 AssertRCReturn(rc, rc);
1438 pContext->client.array.n.buffer = CRS_GET_BO(ui);
1439
1440 for (i = 0; i < CR_MAX_TEXTURE_UNITS; i++)
1441 {
1442 rc = SSMR3GetU32(pSSM, &ui);
1443 AssertRCReturn(rc, rc);
1444 pContext->client.array.t[i].buffer = CRS_GET_BO(ui);
1445 }
1446# ifdef CR_NV_vertex_program
1447 for (i = 0; i < CR_MAX_VERTEX_ATTRIBS; i++)
1448 {
1449 rc = SSMR3GetU32(pSSM, &ui);
1450 AssertRCReturn(rc, rc);
1451 pContext->client.array.a[i].buffer = CRS_GET_BO(ui);
1452 }
1453# endif
1454#undef CRS_GET_BO
1455
1456 pContext->bufferobject.bResyncNeeded = GL_TRUE;
1457#endif
1458
1459 /* Load pixel/vertex programs */
1460 rc = SSMR3GetU32(pSSM, &uiNumElems);
1461 AssertRCReturn(rc, rc);
1462 /* Load defauls programs */
1463 rc = crStateLoadProgram(&pContext->program.defaultVertexProgram, pSSM);
1464 AssertRCReturn(rc, rc);
1465 //FILLDIRTY(pContext->program.defaultVertexProgram->dirtyProgram);
1466 rc = crStateLoadProgram(&pContext->program.defaultFragmentProgram, pSSM);
1467 AssertRCReturn(rc, rc);
1468 //FILLDIRTY(pContext->program.defaultFragmentProgram->dirtyProgram);
1469 /* Load all the rest */
1470 for (ui=0; ui<uiNumElems; ++ui)
1471 {
1472 CRProgram *pProgram = NULL;
1473 rc = crStateLoadProgram(&pProgram, pSSM);
1474 AssertRCReturn(rc, rc);
1475 crHashtableAdd(pContext->program.programHash, pProgram->id, pProgram);
1476 //DIRTY(pProgram->dirtyProgram, pContext->neg_bitid);
1477
1478 }
1479 //FILLDIRTY(GetCurrentBits()->program.dirty);
1480 /* Load Pointers */
1481 rc = SSMR3GetU32(pSSM, &ui);
1482 AssertRCReturn(rc, rc);
1483 pContext->program.currentVertexProgram = ui==0 ? pContext->program.defaultVertexProgram
1484 : crHashtableSearch(pContext->program.programHash, ui);
1485 rc = SSMR3GetU32(pSSM, &ui);
1486 AssertRCReturn(rc, rc);
1487 pContext->program.currentFragmentProgram = ui==0 ? pContext->program.defaultFragmentProgram
1488 : crHashtableSearch(pContext->program.programHash, ui);
1489
1490 /* Mark programs for resending to GPU */
1491 pContext->program.bResyncNeeded = GL_TRUE;
1492
1493#ifdef CR_EXT_framebuffer_object
1494 /* Load FBOs */
1495 rc = SSMR3GetU32(pSSM, &uiNumElems);
1496 AssertRCReturn(rc, rc);
1497 for (ui=0; ui<uiNumElems; ++ui)
1498 {
1499 CRFramebufferObject *pFBO;
1500 pFBO = crAlloc(sizeof(*pFBO));
1501 if (!pFBO) return VERR_NO_MEMORY;
1502
1503 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
1504 AssertRCReturn(rc, rc);
1505
1506 rc = SSMR3GetMem(pSSM, pFBO, sizeof(*pFBO));
1507 AssertRCReturn(rc, rc);
1508
1509 crHashtableAdd(pContext->framebufferobject.framebuffers, key, pFBO);
1510 }
1511
1512 rc = SSMR3GetU32(pSSM, &uiNumElems);
1513 AssertRCReturn(rc, rc);
1514 for (ui=0; ui<uiNumElems; ++ui)
1515 {
1516 CRRenderbufferObject *pRBO;
1517 pRBO = crAlloc(sizeof(*pRBO));
1518 if (!pRBO) return VERR_NO_MEMORY;
1519
1520 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
1521 AssertRCReturn(rc, rc);
1522
1523 rc = SSMR3GetMem(pSSM, pRBO, sizeof(*pRBO));
1524 AssertRCReturn(rc, rc);
1525
1526 crHashtableAdd(pContext->framebufferobject.renderbuffers, key, pRBO);
1527 }
1528
1529 rc = SSMR3GetU32(pSSM, &ui);
1530 AssertRCReturn(rc, rc);
1531 pContext->framebufferobject.framebuffer = ui==0 ? NULL
1532 : crHashtableSearch(pContext->framebufferobject.framebuffers, ui);
1533
1534 rc = SSMR3GetU32(pSSM, &ui);
1535 AssertRCReturn(rc, rc);
1536 pContext->framebufferobject.renderbuffer = ui==0 ? NULL
1537 : crHashtableSearch(pContext->framebufferobject.renderbuffers, ui);
1538
1539 /* Mark FBOs/RBOs for resending to GPU */
1540 pContext->framebufferobject.bResyncNeeded = GL_TRUE;
1541#endif
1542
1543#ifdef CR_OPENGL_VERSION_2_0
1544 /* Load GLSL related info */
1545 rc = SSMR3GetU32(pSSM, &uiNumElems);
1546 AssertRCReturn(rc, rc);
1547
1548 for (ui=0; ui<uiNumElems; ++ui)
1549 {
1550 CRGLSLShader *pShader = crStateLoadGLSLShader(pSSM);
1551 if (!pShader) return VERR_SSM_UNEXPECTED_DATA;
1552 crHashtableAdd(pContext->glsl.shaders, pShader->id, pShader);
1553 }
1554
1555 rc = SSMR3GetU32(pSSM, &uiNumElems);
1556 AssertRCReturn(rc, rc);
1557
1558 for (ui=0; ui<uiNumElems; ++ui)
1559 {
1560 CRGLSLProgram *pProgram;
1561 uint32_t numShaders;
1562
1563 pProgram = crAlloc(sizeof(*pProgram));
1564 if (!pProgram) return VERR_NO_MEMORY;
1565
1566 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
1567 AssertRCReturn(rc, rc);
1568
1569 rc = SSMR3GetMem(pSSM, pProgram, sizeof(*pProgram));
1570 AssertRCReturn(rc, rc);
1571
1572 crHashtableAdd(pContext->glsl.programs, key, pProgram);
1573
1574 pProgram->currentState.attachedShaders = crAllocHashtable();
1575
1576 rc = SSMR3GetU32(pSSM, &numShaders);
1577 AssertRCReturn(rc, rc);
1578
1579 for (k=0; k<numShaders; ++k)
1580 {
1581 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
1582 AssertRCReturn(rc, rc);
1583 crHashtableAdd(pProgram->currentState.attachedShaders, key, crHashtableSearch(pContext->glsl.shaders, key));
1584 }
1585
1586 if (pProgram->activeState.attachedShaders)
1587 {
1588 pProgram->activeState.attachedShaders = crAllocHashtable();
1589
1590 rc = SSMR3GetU32(pSSM, &numShaders);
1591 AssertRCReturn(rc, rc);
1592
1593 for (k=0; k<numShaders; ++k)
1594 {
1595 CRGLSLShader *pShader = crStateLoadGLSLShader(pSSM);
1596 if (!pShader) return VERR_SSM_UNEXPECTED_DATA;
1597 crHashtableAdd(pProgram->activeState.attachedShaders, pShader->id, pShader);
1598 }
1599 }
1600
1601 if (pProgram->currentState.cAttribs)
1602 pProgram->currentState.pAttribs = (CRGLSLAttrib*) crAlloc(pProgram->currentState.cAttribs*sizeof(CRGLSLAttrib));
1603 for (k=0; k<pProgram->currentState.cAttribs; ++k)
1604 {
1605 rc = SSMR3GetMem(pSSM, &pProgram->currentState.pAttribs[k].index, sizeof(pProgram->currentState.pAttribs[k].index));
1606 AssertRCReturn(rc, rc);
1607 pProgram->currentState.pAttribs[k].name = crStateLoadString(pSSM);
1608 }
1609
1610 if (pProgram->activeState.cAttribs)
1611 pProgram->activeState.pAttribs = (CRGLSLAttrib*) crAlloc(pProgram->activeState.cAttribs*sizeof(CRGLSLAttrib));
1612 for (k=0; k<pProgram->activeState.cAttribs; ++k)
1613 {
1614 rc = SSMR3GetMem(pSSM, &pProgram->activeState.pAttribs[k].index, sizeof(pProgram->activeState.pAttribs[k].index));
1615 AssertRCReturn(rc, rc);
1616 pProgram->activeState.pAttribs[k].name = crStateLoadString(pSSM);
1617 }
1618
1619 rc = SSMR3GetS32(pSSM, &pProgram->cUniforms);
1620 AssertRCReturn(rc, rc);
1621
1622 if (pProgram->cUniforms)
1623 {
1624 pProgram->pUniforms = crAlloc(pProgram->cUniforms*sizeof(CRGLSLUniform));
1625 if (!pProgram) return VERR_NO_MEMORY;
1626
1627 for (k=0; k<pProgram->cUniforms; ++k)
1628 {
1629 size_t itemsize, datasize;
1630
1631 rc = SSMR3GetMem(pSSM, &pProgram->pUniforms[k].type, sizeof(GLenum));
1632 pProgram->pUniforms[k].name = crStateLoadString(pSSM);
1633
1634 if (GL_INT==pProgram->pUniforms[k].type
1635 || GL_INT_VEC2==pProgram->pUniforms[k].type
1636 || GL_INT_VEC3==pProgram->pUniforms[k].type
1637 || GL_INT_VEC4==pProgram->pUniforms[k].type
1638 || GL_BOOL==pProgram->pUniforms[k].type
1639 || GL_BOOL_VEC2==pProgram->pUniforms[k].type
1640 || GL_BOOL_VEC3==pProgram->pUniforms[k].type
1641 || GL_BOOL_VEC4==pProgram->pUniforms[k].type
1642 || GL_SAMPLER_1D==pProgram->pUniforms[k].type
1643 || GL_SAMPLER_2D==pProgram->pUniforms[k].type
1644 || GL_SAMPLER_3D==pProgram->pUniforms[k].type
1645 || GL_SAMPLER_CUBE==pProgram->pUniforms[k].type
1646 || GL_SAMPLER_1D_SHADOW==pProgram->pUniforms[k].type
1647 || GL_SAMPLER_2D_SHADOW==pProgram->pUniforms[k].type)
1648 {
1649 itemsize = sizeof(GLint);
1650 } else itemsize = sizeof(GLfloat);
1651
1652 datasize = crStateGetUniformSize(pProgram->pUniforms[k].type)*itemsize;
1653 pProgram->pUniforms[k].data = crAlloc(datasize);
1654 if (!pProgram->pUniforms[k].data) return VERR_NO_MEMORY;
1655
1656 rc = SSMR3GetMem(pSSM, pProgram->pUniforms[k].data, datasize);
1657 }
1658 }
1659 }
1660
1661 rc = SSMR3GetU32(pSSM, &ui);
1662 AssertRCReturn(rc, rc);
1663 pContext->glsl.activeProgram = ui==0 ? NULL
1664 : crHashtableSearch(pContext->glsl.programs, ui);
1665
1666 /*Mark for resending to GPU*/
1667 pContext->glsl.bResyncNeeded = GL_TRUE;
1668#endif
1669
1670 return VINF_SUCCESS;
1671}
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