VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedOpenGL/crserverlib/server_main.c@ 21990

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

crOpenGL: fix 3d failure after snapshot loading

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 29.2 KB
Line 
1/* Copyright (c) 2001, Stanford University
2 * All rights reserved
3 *
4 * See the file LICENSE.txt for information on redistributing this software.
5 */
6
7#include "server.h"
8#include "cr_net.h"
9#include "cr_unpack.h"
10#include "cr_error.h"
11#include "cr_glstate.h"
12#include "cr_string.h"
13#include "cr_mem.h"
14#include "cr_hash.h"
15#include "server_dispatch.h"
16#include "state/cr_texture.h"
17#include <signal.h>
18#include <stdlib.h>
19#define DEBUG_FP_EXCEPTIONS 0
20#if DEBUG_FP_EXCEPTIONS
21#include <fpu_control.h>
22#include <math.h>
23#endif
24#include <iprt/assert.h>
25
26/**
27 * \mainpage CrServerLib
28 *
29 * \section CrServerLibIntroduction Introduction
30 *
31 * Chromium consists of all the top-level files in the cr
32 * directory. The core module basically takes care of API dispatch,
33 * and OpenGL state management.
34 */
35
36
37/**
38 * CRServer global data
39 */
40CRServer cr_server;
41
42int tearingdown = 0; /* can't be static */
43
44
45/**
46 * Return pointer to server's first SPU.
47 */
48SPU*
49crServerHeadSPU(void)
50{
51 return cr_server.head_spu;
52}
53
54
55
56static void DeleteBarrierCallback( void *data )
57{
58 CRServerBarrier *barrier = (CRServerBarrier *) data;
59 crFree(barrier->waiting);
60 crFree(barrier);
61}
62
63
64static void deleteContextCallback( void *data )
65{
66 CRContext *c = (CRContext *) data;
67 crStateDestroyContext(c);
68}
69
70
71static void crServerTearDown( void )
72{
73 GLint i;
74
75 /* avoid a race condition */
76 if (tearingdown)
77 return;
78
79 tearingdown = 1;
80
81 crStateSetCurrent( NULL );
82
83 cr_server.curClient = NULL;
84 cr_server.run_queue = NULL;
85
86 crFree( cr_server.overlap_intens );
87 cr_server.overlap_intens = NULL;
88
89 /* Deallocate all semaphores */
90 crFreeHashtable(cr_server.semaphores, crFree);
91 cr_server.semaphores = NULL;
92
93 /* Deallocate all barriers */
94 crFreeHashtable(cr_server.barriers, DeleteBarrierCallback);
95 cr_server.barriers = NULL;
96
97 /* Free all context info */
98 crFreeHashtable(cr_server.contextTable, deleteContextCallback);
99
100 /* Free context/window creation info */
101 crFreeHashtable(cr_server.pContextCreateInfoTable, crServerCreateInfoDeleteCB);
102 crFreeHashtable(cr_server.pWindowCreateInfoTable, crServerCreateInfoDeleteCB);
103
104 /* Free vertex programs */
105 crFreeHashtable(cr_server.programTable, crFree);
106
107 for (i = 0; i < cr_server.numClients; i++) {
108 if (cr_server.clients[i]) {
109 CRConnection *conn = cr_server.clients[i]->conn;
110 crNetFreeConnection(conn);
111 crFree(cr_server.clients[i]);
112 }
113 }
114 cr_server.numClients = 0;
115
116#if 1
117 /* disable these two lines if trying to get stack traces with valgrind */
118 crSPUUnloadChain(cr_server.head_spu);
119 cr_server.head_spu = NULL;
120#endif
121}
122
123static void crServerClose( unsigned int id )
124{
125 crError( "Client disconnected!" );
126 (void) id;
127}
128
129static void crServerCleanup( int sigio )
130{
131 crServerTearDown();
132
133 tearingdown = 0;
134}
135
136
137void
138crServerSetPort(int port)
139{
140 cr_server.tcpip_port = port;
141}
142
143
144
145static void
146crPrintHelp(void)
147{
148 printf("Usage: crserver [OPTIONS]\n");
149 printf("Options:\n");
150 printf(" -mothership URL Specifies URL for contacting the mothership.\n");
151 printf(" URL is of the form [protocol://]hostname[:port]\n");
152 printf(" -port N Specifies the port number this server will listen to.\n");
153 printf(" -help Prints this information.\n");
154}
155
156
157/**
158 * Do CRServer initializations. After this, we can begin servicing clients.
159 */
160void
161crServerInit(int argc, char *argv[])
162{
163 int i;
164 char *mothership = NULL;
165 CRMuralInfo *defaultMural;
166
167 for (i = 1 ; i < argc ; i++)
168 {
169 if (!crStrcmp( argv[i], "-mothership" ))
170 {
171 if (i == argc - 1)
172 {
173 crError( "-mothership requires an argument" );
174 }
175 mothership = argv[i+1];
176 i++;
177 }
178 else if (!crStrcmp( argv[i], "-port" ))
179 {
180 /* This is the port on which we'll accept client connections */
181 if (i == argc - 1)
182 {
183 crError( "-port requires an argument" );
184 }
185 cr_server.tcpip_port = crStrToInt(argv[i+1]);
186 i++;
187 }
188 else if (!crStrcmp( argv[i], "-vncmode" ))
189 {
190 cr_server.vncMode = 1;
191 }
192 else if (!crStrcmp( argv[i], "-help" ))
193 {
194 crPrintHelp();
195 exit(0);
196 }
197 }
198
199 signal( SIGTERM, crServerCleanup );
200 signal( SIGINT, crServerCleanup );
201#ifndef WINDOWS
202 signal( SIGPIPE, SIG_IGN );
203#endif
204
205#if DEBUG_FP_EXCEPTIONS
206 {
207 fpu_control_t mask;
208 _FPU_GETCW(mask);
209 mask &= ~(_FPU_MASK_IM | _FPU_MASK_DM | _FPU_MASK_ZM
210 | _FPU_MASK_OM | _FPU_MASK_UM);
211 _FPU_SETCW(mask);
212 }
213#endif
214
215 cr_server.firstCallCreateContext = GL_TRUE;
216 cr_server.firstCallMakeCurrent = GL_TRUE;
217
218 /*
219 * Create default mural info and hash table.
220 */
221 cr_server.muralTable = crAllocHashtable();
222 defaultMural = (CRMuralInfo *) crCalloc(sizeof(CRMuralInfo));
223 crHashtableAdd(cr_server.muralTable, 0, defaultMural);
224
225 cr_server.programTable = crAllocHashtable();
226
227 crNetInit(crServerRecv, crServerClose);
228 crStateInit();
229
230 crServerSetVBoxConfiguration();
231
232 crStateLimitsInit( &(cr_server.limits) );
233
234 /*
235 * Default context
236 */
237 cr_server.contextTable = crAllocHashtable();
238 cr_server.DummyContext = crStateCreateContext( &cr_server.limits,
239 CR_RGB_BIT | CR_DEPTH_BIT, NULL );
240 cr_server.curClient->currentCtx = cr_server.DummyContext;
241
242 crServerInitDispatch();
243 crStateDiffAPI( &(cr_server.head_spu->dispatch_table) );
244
245 crUnpackSetReturnPointer( &(cr_server.return_ptr) );
246 crUnpackSetWritebackPointer( &(cr_server.writeback_ptr) );
247
248 cr_server.barriers = crAllocHashtable();
249 cr_server.semaphores = crAllocHashtable();
250}
251
252void crVBoxServerTearDown(void)
253{
254 crServerTearDown();
255}
256
257/**
258 * Do CRServer initializations. After this, we can begin servicing clients.
259 */
260GLboolean crVBoxServerInit(void)
261{
262 CRMuralInfo *defaultMural;
263
264#if DEBUG_FP_EXCEPTIONS
265 {
266 fpu_control_t mask;
267 _FPU_GETCW(mask);
268 mask &= ~(_FPU_MASK_IM | _FPU_MASK_DM | _FPU_MASK_ZM
269 | _FPU_MASK_OM | _FPU_MASK_UM);
270 _FPU_SETCW(mask);
271 }
272#endif
273
274 crNetInit(crServerRecv, crServerClose);
275
276 cr_server.firstCallCreateContext = GL_TRUE;
277 cr_server.firstCallMakeCurrent = GL_TRUE;
278
279 cr_server.bIsInLoadingState = GL_FALSE;
280 cr_server.bIsInSavingState = GL_FALSE;
281
282 /*
283 * Create default mural info and hash table.
284 */
285 cr_server.muralTable = crAllocHashtable();
286 defaultMural = (CRMuralInfo *) crCalloc(sizeof(CRMuralInfo));
287 crHashtableAdd(cr_server.muralTable, 0, defaultMural);
288
289 cr_server.programTable = crAllocHashtable();
290
291 crStateInit();
292
293 crStateLimitsInit( &(cr_server.limits) );
294
295 cr_server.barriers = crAllocHashtable();
296 cr_server.semaphores = crAllocHashtable();
297
298 crUnpackSetReturnPointer( &(cr_server.return_ptr) );
299 crUnpackSetWritebackPointer( &(cr_server.writeback_ptr) );
300
301 /*
302 * Default context
303 */
304 cr_server.contextTable = crAllocHashtable();
305 cr_server.DummyContext = crStateCreateContext( &cr_server.limits,
306 CR_RGB_BIT | CR_DEPTH_BIT, NULL );
307 cr_server.pContextCreateInfoTable = crAllocHashtable();
308 cr_server.pWindowCreateInfoTable = crAllocHashtable();
309
310 crServerSetVBoxConfigurationHGCM();
311
312 if (!cr_server.head_spu)
313 return GL_FALSE;
314
315 crServerInitDispatch();
316 crStateDiffAPI( &(cr_server.head_spu->dispatch_table) );
317
318 return GL_TRUE;
319}
320
321int32_t crVBoxServerAddClient(uint32_t u32ClientID)
322{
323 CRClient *newClient;
324
325 if (cr_server.numClients>=CR_MAX_CLIENTS)
326 {
327 return VERR_MAX_THRDS_REACHED;
328 }
329
330 newClient = (CRClient *) crCalloc(sizeof(CRClient));
331 crDebug("crServer: AddClient u32ClientID=%d", u32ClientID);
332
333 newClient->spu_id = 0;
334 newClient->currentCtx = cr_server.DummyContext;
335 newClient->currentContextNumber = -1;
336 newClient->conn = crNetAcceptClient(cr_server.protocol, NULL,
337 cr_server.tcpip_port,
338 cr_server.mtu, 0);
339 newClient->conn->u32ClientID = u32ClientID;
340
341 cr_server.clients[cr_server.numClients++] = newClient;
342
343 crServerAddToRunQueue(newClient);
344
345 return VINF_SUCCESS;
346}
347
348void crVBoxServerRemoveClient(uint32_t u32ClientID)
349{
350 CRClient *pClient;
351 int32_t i;
352
353 crDebug("crServer: RemoveClient u32ClientID=%d", u32ClientID);
354
355 for (i = 0; i < cr_server.numClients; i++)
356 {
357 if (cr_server.clients[i] && cr_server.clients[i]->conn
358 && cr_server.clients[i]->conn->u32ClientID==u32ClientID)
359 {
360 break;
361 }
362 }
363 pClient = cr_server.clients[i];
364 CRASSERT(pClient);
365
366 /* Disconnect the client */
367 pClient->conn->Disconnect(pClient->conn);
368
369 /* Let server clear client from the queue */
370 crServerDeleteClient(pClient);
371}
372
373int32_t crVBoxServerClientWrite(uint32_t u32ClientID, uint8_t *pBuffer, uint32_t cbBuffer)
374{
375 CRClient *pClient;
376 int32_t i;
377
378 //crDebug("crServer: [%x] ClientWrite u32ClientID=%d", crThreadID(), u32ClientID);
379
380 for (i = 0; i < cr_server.numClients; i++)
381 {
382 if (cr_server.clients[i] && cr_server.clients[i]->conn
383 && cr_server.clients[i]->conn->u32ClientID==u32ClientID)
384 {
385 break;
386 }
387 }
388 pClient = cr_server.clients[i];
389 CRASSERT(pClient);
390
391 if (!pClient->conn->vMajor) return VERR_NOT_SUPPORTED;
392
393 CRASSERT(pBuffer);
394
395 /* This should never fire unless we start to multithread */
396 CRASSERT(pClient->conn->pBuffer==NULL && pClient->conn->cbBuffer==0);
397
398 /* Check if there's a blocker in queue and it's not this client */
399 if (cr_server.run_queue->client != pClient
400 && crServerClientInBeginEnd(cr_server.run_queue->client))
401 {
402 crDebug("crServer: client %d blocked, allow_redir_ptr = 0", u32ClientID);
403 pClient->conn->allow_redir_ptr = 0;
404 }
405 else
406 {
407 pClient->conn->allow_redir_ptr = 1;
408 }
409
410 pClient->conn->pBuffer = pBuffer;
411 pClient->conn->cbBuffer = cbBuffer;
412
413 crNetRecv();
414 CRASSERT(pClient->conn->pBuffer==NULL && pClient->conn->cbBuffer==0);
415
416 crServerServiceClients();
417
418#if 0
419 if (pClient->currentMural) {
420 crStateViewport( 0, 0, 500, 500 );
421 pClient->currentMural->viewportValidated = GL_FALSE;
422 cr_server.head_spu->dispatch_table.Viewport( 0, 0, 500, 500 );
423 crStateViewport( 0, 0, 600, 600 );
424 pClient->currentMural->viewportValidated = GL_FALSE;
425 cr_server.head_spu->dispatch_table.Viewport( 0, 0, 600, 600 );
426
427 crStateMatrixMode(GL_PROJECTION);
428 cr_server.head_spu->dispatch_table.MatrixMode(GL_PROJECTION);
429 crServerDispatchLoadIdentity();
430 crStateFrustum(-0.6, 0.6, -0.5, 0.5, 1.5, 150.0);
431 cr_server.head_spu->dispatch_table.Frustum(-0.6, 0.6, -0.5, 0.5, 1.5, 150.0);
432 crServerDispatchLoadIdentity();
433 crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
434 cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
435
436 crStateMatrixMode(GL_MODELVIEW);
437 cr_server.head_spu->dispatch_table.MatrixMode(GL_MODELVIEW);
438 crServerDispatchLoadIdentity();
439 crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
440 cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
441 crServerDispatchLoadIdentity();
442 }
443#endif
444
445 crStateResetCurrentPointers(&cr_server.current);
446
447 CRASSERT(!pClient->conn->allow_redir_ptr || crNetNumMessages(pClient->conn)==0);
448
449 return VINF_SUCCESS;
450}
451
452int32_t crVBoxServerClientRead(uint32_t u32ClientID, uint8_t *pBuffer, uint32_t *pcbBuffer)
453{
454 CRClient *pClient;
455 int32_t i;
456
457 //crDebug("crServer: [%x] ClientRead u32ClientID=%d", crThreadID(), u32ClientID);
458
459 for (i = 0; i < cr_server.numClients; i++)
460 {
461 if (cr_server.clients[i] && cr_server.clients[i]->conn
462 && cr_server.clients[i]->conn->u32ClientID==u32ClientID)
463 {
464 break;
465 }
466 }
467 pClient = cr_server.clients[i];
468 CRASSERT(pClient);
469
470 if (!pClient->conn->vMajor) return VERR_NOT_SUPPORTED;
471
472 if (pClient->conn->cbHostBuffer > *pcbBuffer)
473 {
474 crDebug("crServer: [%lx] ClientRead u32ClientID=%d FAIL, host buffer too small %d of %d",
475 crThreadID(), u32ClientID, *pcbBuffer, pClient->conn->cbHostBuffer);
476
477 /* Return the size of needed buffer */
478 *pcbBuffer = pClient->conn->cbHostBuffer;
479
480 return VERR_BUFFER_OVERFLOW;
481 }
482
483 *pcbBuffer = pClient->conn->cbHostBuffer;
484
485 if (*pcbBuffer)
486 {
487 CRASSERT(pClient->conn->pHostBuffer);
488
489 crMemcpy(pBuffer, pClient->conn->pHostBuffer, *pcbBuffer);
490 pClient->conn->cbHostBuffer = 0;
491 }
492
493 return VINF_SUCCESS;
494}
495
496int32_t crVBoxServerClientSetVersion(uint32_t u32ClientID, uint32_t vMajor, uint32_t vMinor)
497{
498 CRClient *pClient;
499 int32_t i;
500
501 for (i = 0; i < cr_server.numClients; i++)
502 {
503 if (cr_server.clients[i] && cr_server.clients[i]->conn
504 && cr_server.clients[i]->conn->u32ClientID==u32ClientID)
505 {
506 break;
507 }
508 }
509 pClient = cr_server.clients[i];
510 CRASSERT(pClient);
511
512 pClient->conn->vMajor = vMajor;
513 pClient->conn->vMinor = vMinor;
514
515 if (vMajor != CR_PROTOCOL_VERSION_MAJOR
516 || vMinor != CR_PROTOCOL_VERSION_MINOR)
517 {
518 return VERR_NOT_SUPPORTED;
519 }
520 else return VINF_SUCCESS;
521}
522
523int
524CRServerMain(int argc, char *argv[])
525{
526 crServerInit(argc, argv);
527
528 crServerSerializeRemoteStreams();
529
530 crServerTearDown();
531
532 tearingdown = 0;
533
534 return 0;
535}
536
537static void crVBoxServerSaveMuralCB(unsigned long key, void *data1, void *data2)
538{
539 CRMuralInfo *pMI = (CRMuralInfo*) data1;
540 PSSMHANDLE pSSM = (PSSMHANDLE) data2;
541 int32_t rc;
542
543 CRASSERT(pMI && pSSM);
544
545 /* Don't store default mural */
546 if (!key) return;
547
548 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
549 CRASSERT(rc == VINF_SUCCESS);
550
551 rc = SSMR3PutMem(pSSM, pMI, sizeof(*pMI));
552 CRASSERT(rc == VINF_SUCCESS);
553}
554
555/* @todo add hashtable walker with result info and intermediate abort */
556static void crVBoxServerSaveCreateInfoCB(unsigned long key, void *data1, void *data2)
557{
558 CRCreateInfo_t *pCreateInfo = (CRCreateInfo_t *) data1;
559 PSSMHANDLE pSSM = (PSSMHANDLE) data2;
560 int32_t rc;
561
562 CRASSERT(pCreateInfo && pSSM);
563
564 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
565 CRASSERT(rc == VINF_SUCCESS);
566
567 rc = SSMR3PutMem(pSSM, pCreateInfo, sizeof(*pCreateInfo));
568 CRASSERT(rc == VINF_SUCCESS);
569
570 if (pCreateInfo->pszDpyName)
571 {
572 rc = SSMR3PutStrZ(pSSM, pCreateInfo->pszDpyName);
573 CRASSERT(rc == VINF_SUCCESS);
574 }
575}
576
577static void crVBoxServerSyncTextureCB(unsigned long key, void *data1, void *data2)
578{
579 CRTextureObj *pTexture = (CRTextureObj *) data1;
580 CRContext *pContext = (CRContext *) data2;
581
582 CRASSERT(pTexture && pContext);
583 crStateTextureObjectDiff(pContext, NULL, NULL, pTexture, GL_TRUE);
584}
585
586static void crVBoxServerSaveContextStateCB(unsigned long key, void *data1, void *data2)
587{
588 CRContext *pContext = (CRContext *) data1;
589 PSSMHANDLE pSSM = (PSSMHANDLE) data2;
590 int32_t rc;
591
592 CRASSERT(pContext && pSSM);
593
594 /* We could have skipped saving the key and use similar callback to load context states back,
595 * but there's no guarantee we'd traverse hashtable in same order after loading.
596 */
597 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
598 CRASSERT(rc == VINF_SUCCESS);
599
600#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
601 if (cr_server.curClient)
602 {
603 crServerDispatchMakeCurrent(cr_server.curClient->currentWindow, 0, pContext->id);
604 }
605#endif
606
607 rc = crStateSaveContext(pContext, pSSM);
608 CRASSERT(rc == VINF_SUCCESS);
609}
610
611static uint32_t g_hackVBoxServerSaveLoadCallsLeft = 0;
612
613DECLEXPORT(int32_t) crVBoxServerSaveState(PSSMHANDLE pSSM)
614{
615 int32_t rc, i;
616 uint32_t ui32;
617 GLboolean b;
618 unsigned long key;
619#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
620 unsigned long ctxID=-1, winID=-1;
621#endif
622
623 /* We shouldn't be called if there's no clients at all*/
624 CRASSERT(cr_server.numClients>0);
625
626 /* @todo it's hack atm */
627 /* We want to be called only once to save server state but atm we're being called from svcSaveState
628 * for every connected client (e.g. guest opengl application)
629 */
630 if (!cr_server.bIsInSavingState) /* It's first call */
631 {
632 cr_server.bIsInSavingState = GL_TRUE;
633
634 /* Store number of clients */
635 rc = SSMR3PutU32(pSSM, (uint32_t) cr_server.numClients);
636 AssertRCReturn(rc, rc);
637
638 g_hackVBoxServerSaveLoadCallsLeft = cr_server.numClients;
639 }
640
641 g_hackVBoxServerSaveLoadCallsLeft--;
642
643 /* Do nothing untill we're being called last time */
644 if (g_hackVBoxServerSaveLoadCallsLeft>0)
645 {
646 return VINF_SUCCESS;
647 }
648
649 /* Save rendering contexts creation info */
650 ui32 = crHashtableNumElements(cr_server.pContextCreateInfoTable);
651 rc = SSMR3PutU32(pSSM, (uint32_t) ui32);
652 AssertRCReturn(rc, rc);
653 crHashtableWalk(cr_server.pContextCreateInfoTable, crVBoxServerSaveCreateInfoCB, pSSM);
654
655#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
656 /* Save current win and ctx IDs, as we'd rebind contexts when saving textures */
657 if (cr_server.curClient)
658 {
659 ctxID = cr_server.curClient->currentContextNumber;
660 winID = cr_server.curClient->currentWindow;
661 }
662#endif
663
664 /* Save contexts state tracker data */
665 /* @todo For now just some blind data dumps,
666 * but I've a feeling those should be saved/restored in a very strict sequence to
667 * allow diff_api to work correctly.
668 * Should be tested more with multiply guest opengl apps working when saving VM snapshot.
669 */
670 crHashtableWalk(cr_server.contextTable, crVBoxServerSaveContextStateCB, pSSM);
671
672#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
673 /* Restore original win and ctx IDs*/
674 if (cr_server.curClient)
675 {
676 crServerDispatchMakeCurrent(winID, 0, ctxID);
677 }
678#endif
679
680 /* Save windows creation info */
681 ui32 = crHashtableNumElements(cr_server.pWindowCreateInfoTable);
682 rc = SSMR3PutU32(pSSM, (uint32_t) ui32);
683 AssertRCReturn(rc, rc);
684 crHashtableWalk(cr_server.pWindowCreateInfoTable, crVBoxServerSaveCreateInfoCB, pSSM);
685
686 /* Save cr_server.muralTable
687 * @todo we don't need it all, just geometry info actually
688 * @todo store visible regions as well
689 */
690 ui32 = crHashtableNumElements(cr_server.muralTable);
691 /* There should be default mural always */
692 CRASSERT(ui32>=1);
693 rc = SSMR3PutU32(pSSM, (uint32_t) ui32-1);
694 AssertRCReturn(rc, rc);
695 crHashtableWalk(cr_server.muralTable, crVBoxServerSaveMuralCB, pSSM);
696
697 /* Save starting free context and window IDs */
698 rc = SSMR3PutMem(pSSM, &cr_server.idsPool, sizeof(cr_server.idsPool));
699 AssertRCReturn(rc, rc);
700
701 /* Save clients info */
702 for (i = 0; i < cr_server.numClients; i++)
703 {
704 if (cr_server.clients[i] && cr_server.clients[i]->conn)
705 {
706 CRClient *pClient = cr_server.clients[i];
707
708 rc = SSMR3PutU32(pSSM, pClient->conn->u32ClientID);
709 AssertRCReturn(rc, rc);
710
711 rc = SSMR3PutU32(pSSM, pClient->conn->vMajor);
712 AssertRCReturn(rc, rc);
713
714 rc = SSMR3PutU32(pSSM, pClient->conn->vMinor);
715 AssertRCReturn(rc, rc);
716
717 rc = SSMR3PutMem(pSSM, pClient, sizeof(*pClient));
718 AssertRCReturn(rc, rc);
719
720 if (pClient->currentCtx && pClient->currentContextNumber>=0)
721 {
722 b = crHashtableGetDataKey(cr_server.contextTable, pClient->currentCtx, &key);
723 CRASSERT(b);
724 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
725 AssertRCReturn(rc, rc);
726 }
727
728 if (pClient->currentMural && pClient->currentWindow>=0)
729 {
730 b = crHashtableGetDataKey(cr_server.muralTable, pClient->currentMural, &key);
731 CRASSERT(b);
732 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
733 AssertRCReturn(rc, rc);
734 }
735 }
736 }
737
738 cr_server.bIsInSavingState = GL_FALSE;
739
740 return VINF_SUCCESS;
741}
742
743DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM, uint32_t version)
744{
745 int32_t rc, i;
746 uint32_t ui, uiNumElems;
747 unsigned long key;
748
749 if (!cr_server.bIsInLoadingState)
750 {
751 /* AssertRCReturn(...) will leave us in loading state, but it doesn't matter as we'd be failing anyway */
752 cr_server.bIsInLoadingState = GL_TRUE;
753
754 /* Read number of clients */
755 rc = SSMR3GetU32(pSSM, &g_hackVBoxServerSaveLoadCallsLeft);
756 AssertRCReturn(rc, rc);
757 }
758
759 g_hackVBoxServerSaveLoadCallsLeft--;
760
761 /* Do nothing untill we're being called last time */
762 if (g_hackVBoxServerSaveLoadCallsLeft>0)
763 {
764 return VINF_SUCCESS;
765 }
766
767 /* Load and recreate rendering contexts */
768 rc = SSMR3GetU32(pSSM, &uiNumElems);
769 AssertRCReturn(rc, rc);
770 for (ui=0; ui<uiNumElems; ++ui)
771 {
772 CRCreateInfo_t createInfo;
773 char psz[200];
774 GLint ctxID;
775
776 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
777 AssertRCReturn(rc, rc);
778 rc = SSMR3GetMem(pSSM, &createInfo, sizeof(createInfo));
779 AssertRCReturn(rc, rc);
780
781 if (createInfo.pszDpyName)
782 {
783 rc = SSMR3GetStrZEx(pSSM, psz, 200, NULL);
784 AssertRCReturn(rc, rc);
785 createInfo.pszDpyName = psz;
786 }
787
788 ctxID = crServerDispatchCreateContextEx(createInfo.pszDpyName, createInfo.visualBits, 0, key, createInfo.internalID);
789 CRASSERT((int64_t)ctxID == (int64_t)key);
790 }
791
792 /* Restore context state data */
793 for (ui=0; ui<uiNumElems; ++ui)
794 {
795 CRContext *pContext;
796
797 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
798 AssertRCReturn(rc, rc);
799
800 pContext = (CRContext*) crHashtableSearch(cr_server.contextTable, key);
801 CRASSERT(pContext);
802
803 rc = crStateLoadContext(pContext, pSSM);
804 AssertRCReturn(rc, rc);
805 }
806
807 /* Load windows */
808 rc = SSMR3GetU32(pSSM, &uiNumElems);
809 AssertRCReturn(rc, rc);
810 for (ui=0; ui<uiNumElems; ++ui)
811 {
812 CRCreateInfo_t createInfo;
813 char psz[200];
814 GLint winID;
815 unsigned long key;
816
817 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
818 AssertRCReturn(rc, rc);
819 rc = SSMR3GetMem(pSSM, &createInfo, sizeof(createInfo));
820 AssertRCReturn(rc, rc);
821
822 if (createInfo.pszDpyName)
823 {
824 rc = SSMR3GetStrZEx(pSSM, psz, 200, NULL);
825 AssertRCReturn(rc, rc);
826 createInfo.pszDpyName = psz;
827 }
828
829 winID = crServerDispatchWindowCreateEx(createInfo.pszDpyName, createInfo.visualBits, key);
830 CRASSERT((int64_t)winID == (int64_t)key);
831 }
832
833 /* Load cr_server.muralTable */
834 rc = SSMR3GetU32(pSSM, &uiNumElems);
835 AssertRCReturn(rc, rc);
836 for (ui=0; ui<uiNumElems; ++ui)
837 {
838 CRMuralInfo muralInfo;
839
840 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
841 AssertRCReturn(rc, rc);
842 rc = SSMR3GetMem(pSSM, &muralInfo, sizeof(muralInfo));
843 AssertRCReturn(rc, rc);
844
845 /* Restore windows geometry info */
846 crServerDispatchWindowSize(key, muralInfo.underlyingDisplay[2], muralInfo.underlyingDisplay[3]);
847 crServerDispatchWindowPosition(key, muralInfo.underlyingDisplay[0], muralInfo.underlyingDisplay[1]);
848 }
849
850 /* Load starting free context and window IDs */
851 rc = SSMR3GetMem(pSSM, &cr_server.idsPool, sizeof(cr_server.idsPool));
852 CRASSERT(rc == VINF_SUCCESS);
853
854 /* Load clients info */
855 for (i = 0; i < cr_server.numClients; i++)
856 {
857 if (cr_server.clients[i] && cr_server.clients[i]->conn)
858 {
859 CRClient *pClient = cr_server.clients[i];
860 CRClient client;
861 unsigned long ctxID=-1, winID=-1;
862
863 rc = SSMR3GetU32(pSSM, &ui);
864 AssertRCReturn(rc, rc);
865 /* If this assert fires, then we should search correct client in the list first*/
866 CRASSERT(ui == pClient->conn->u32ClientID);
867
868 if (version>=4)
869 {
870 rc = SSMR3GetU32(pSSM, &pClient->conn->vMajor);
871 AssertRCReturn(rc, rc);
872
873 rc = SSMR3GetU32(pSSM, &pClient->conn->vMinor);
874 AssertRCReturn(rc, rc);
875 }
876
877 rc = SSMR3GetMem(pSSM, &client, sizeof(client));
878 CRASSERT(rc == VINF_SUCCESS);
879
880 client.conn = pClient->conn;
881 /* We can't reassign client number, as we'd get wrong results in TranslateTextureID
882 * and fail to bind old textures.
883 */
884 /*client.number = pClient->number;*/
885 *pClient = client;
886
887 pClient->currentContextNumber = -1;
888 pClient->currentCtx = cr_server.DummyContext;
889 pClient->currentMural = NULL;
890 pClient->currentWindow = -1;
891
892 cr_server.curClient = pClient;
893
894 if (client.currentCtx && client.currentContextNumber>=0)
895 {
896 rc = SSMR3GetMem(pSSM, &ctxID, sizeof(ctxID));
897 AssertRCReturn(rc, rc);
898 client.currentCtx = (CRContext*) crHashtableSearch(cr_server.contextTable, ctxID);
899 CRASSERT(client.currentCtx);
900 //pClient->currentCtx = client.currentCtx;
901 //pClient->currentContextNumber = ctxID;
902 }
903
904 if (client.currentMural && client.currentWindow>=0)
905 {
906 rc = SSMR3GetMem(pSSM, &winID, sizeof(winID));
907 AssertRCReturn(rc, rc);
908 client.currentMural = (CRMuralInfo*) crHashtableSearch(cr_server.muralTable, winID);
909 CRASSERT(client.currentMural);
910 //pClient->currentMural = client.currentMural;
911 //pClient->currentWindow = winID;
912 }
913
914 /* Restore client active context and window */
915 crServerDispatchMakeCurrent(winID, 0, ctxID);
916
917 if (0)
918 {
919 CRContext *tmpCtx;
920 CRCreateInfo_t *createInfo;
921 GLfloat one[4] = { 1, 1, 1, 1 };
922 GLfloat amb[4] = { 0.4f, 0.4f, 0.4f, 1.0f };
923
924 crServerDispatchMakeCurrent(winID, 0, ctxID);
925
926 crHashtableWalk(client.currentCtx->shared->textureTable, crVBoxServerSyncTextureCB, client.currentCtx);
927
928 crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.base1D, GL_TRUE);
929 crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.base2D, GL_TRUE);
930 crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.base3D, GL_TRUE);
931#ifdef CR_ARB_texture_cube_map
932 crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.baseCubeMap, GL_TRUE);
933#endif
934#ifdef CR_NV_texture_rectangle
935 //@todo this doesn't work as expected
936 //crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.baseRect, GL_TRUE);
937#endif
938 /*cr_server.head_spu->dispatch_table.Materialfv(GL_FRONT_AND_BACK, GL_AMBIENT, amb);
939 cr_server.head_spu->dispatch_table.LightModelfv(GL_LIGHT_MODEL_AMBIENT, amb);
940 cr_server.head_spu->dispatch_table.Lightfv(GL_LIGHT1, GL_DIFFUSE, one);
941
942 cr_server.head_spu->dispatch_table.Enable(GL_LIGHTING);
943 cr_server.head_spu->dispatch_table.Enable(GL_LIGHT0);
944 cr_server.head_spu->dispatch_table.Enable(GL_LIGHT1);
945
946 cr_server.head_spu->dispatch_table.Enable(GL_CULL_FACE);
947 cr_server.head_spu->dispatch_table.Enable(GL_TEXTURE_2D);*/
948
949 //crStateViewport( 0, 0, 600, 600 );
950 //pClient->currentMural->viewportValidated = GL_FALSE;
951 //cr_server.head_spu->dispatch_table.Viewport( 0, 0, 600, 600 );
952
953 //crStateMatrixMode(GL_PROJECTION);
954 //cr_server.head_spu->dispatch_table.MatrixMode(GL_PROJECTION);
955
956 //crStateLoadIdentity();
957 //cr_server.head_spu->dispatch_table.LoadIdentity();
958
959 //crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
960 //cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
961
962 //crStateMatrixMode(GL_MODELVIEW);
963 //cr_server.head_spu->dispatch_table.MatrixMode(GL_MODELVIEW);
964 //crServerDispatchLoadIdentity();
965 //crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
966 //cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
967 //crServerDispatchLoadIdentity();
968
969 /*createInfo = (CRCreateInfo_t *) crHashtableSearch(cr_server.pContextCreateInfoTable, ctxID);
970 CRASSERT(createInfo);
971 tmpCtx = crStateCreateContext(NULL, createInfo->visualBits, NULL);
972 CRASSERT(tmpCtx);
973 crStateDiffContext(tmpCtx, client.currentCtx);
974 crStateDestroyContext(tmpCtx);*/
975 }
976 }
977 }
978
979 //crServerDispatchMakeCurrent(-1, 0, -1);
980
981 cr_server.curClient = NULL;
982
983 {
984 GLenum err = crServerDispatchGetError();
985
986 if (err != GL_NO_ERROR)
987 {
988 crWarning("crServer: glGetError %d after loading snapshot", err);
989 }
990 }
991
992 cr_server.bIsInLoadingState = GL_FALSE;
993
994 return VINF_SUCCESS;
995}
996
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