VirtualBox

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

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

crOpenGL: fix FBO/RBOs support, add snapshots compatibility

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 29.5 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 unsigned long id;
604 if (!crHashtableGetDataKey(cr_server.contextTable, pContext, &id))
605 {
606 crWarning("No client id for server ctx %d", pContext->id);
607 }
608 else
609 {
610 crServerDispatchMakeCurrent(cr_server.curClient->currentWindow, 0, id);
611 }
612 }
613#endif
614
615 rc = crStateSaveContext(pContext, pSSM);
616 CRASSERT(rc == VINF_SUCCESS);
617}
618
619static uint32_t g_hackVBoxServerSaveLoadCallsLeft = 0;
620
621DECLEXPORT(int32_t) crVBoxServerSaveState(PSSMHANDLE pSSM)
622{
623 int32_t rc, i;
624 uint32_t ui32;
625 GLboolean b;
626 unsigned long key;
627#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
628 unsigned long ctxID=-1, winID=-1;
629#endif
630
631 /* We shouldn't be called if there's no clients at all*/
632 CRASSERT(cr_server.numClients>0);
633
634 /* @todo it's hack atm */
635 /* We want to be called only once to save server state but atm we're being called from svcSaveState
636 * for every connected client (e.g. guest opengl application)
637 */
638 if (!cr_server.bIsInSavingState) /* It's first call */
639 {
640 cr_server.bIsInSavingState = GL_TRUE;
641
642 /* Store number of clients */
643 rc = SSMR3PutU32(pSSM, (uint32_t) cr_server.numClients);
644 AssertRCReturn(rc, rc);
645
646 g_hackVBoxServerSaveLoadCallsLeft = cr_server.numClients;
647 }
648
649 g_hackVBoxServerSaveLoadCallsLeft--;
650
651 /* Do nothing untill we're being called last time */
652 if (g_hackVBoxServerSaveLoadCallsLeft>0)
653 {
654 return VINF_SUCCESS;
655 }
656
657 /* Save rendering contexts creation info */
658 ui32 = crHashtableNumElements(cr_server.pContextCreateInfoTable);
659 rc = SSMR3PutU32(pSSM, (uint32_t) ui32);
660 AssertRCReturn(rc, rc);
661 crHashtableWalk(cr_server.pContextCreateInfoTable, crVBoxServerSaveCreateInfoCB, pSSM);
662
663#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
664 /* Save current win and ctx IDs, as we'd rebind contexts when saving textures */
665 if (cr_server.curClient)
666 {
667 ctxID = cr_server.curClient->currentContextNumber;
668 winID = cr_server.curClient->currentWindow;
669 }
670#endif
671
672 /* Save contexts state tracker data */
673 /* @todo For now just some blind data dumps,
674 * but I've a feeling those should be saved/restored in a very strict sequence to
675 * allow diff_api to work correctly.
676 * Should be tested more with multiply guest opengl apps working when saving VM snapshot.
677 */
678 crHashtableWalk(cr_server.contextTable, crVBoxServerSaveContextStateCB, pSSM);
679
680#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
681 /* Restore original win and ctx IDs*/
682 if (cr_server.curClient)
683 {
684 crServerDispatchMakeCurrent(winID, 0, ctxID);
685 }
686#endif
687
688 /* Save windows creation info */
689 ui32 = crHashtableNumElements(cr_server.pWindowCreateInfoTable);
690 rc = SSMR3PutU32(pSSM, (uint32_t) ui32);
691 AssertRCReturn(rc, rc);
692 crHashtableWalk(cr_server.pWindowCreateInfoTable, crVBoxServerSaveCreateInfoCB, pSSM);
693
694 /* Save cr_server.muralTable
695 * @todo we don't need it all, just geometry info actually
696 * @todo store visible regions as well
697 */
698 ui32 = crHashtableNumElements(cr_server.muralTable);
699 /* There should be default mural always */
700 CRASSERT(ui32>=1);
701 rc = SSMR3PutU32(pSSM, (uint32_t) ui32-1);
702 AssertRCReturn(rc, rc);
703 crHashtableWalk(cr_server.muralTable, crVBoxServerSaveMuralCB, pSSM);
704
705 /* Save starting free context and window IDs */
706 rc = SSMR3PutMem(pSSM, &cr_server.idsPool, sizeof(cr_server.idsPool));
707 AssertRCReturn(rc, rc);
708
709 /* Save clients info */
710 for (i = 0; i < cr_server.numClients; i++)
711 {
712 if (cr_server.clients[i] && cr_server.clients[i]->conn)
713 {
714 CRClient *pClient = cr_server.clients[i];
715
716 rc = SSMR3PutU32(pSSM, pClient->conn->u32ClientID);
717 AssertRCReturn(rc, rc);
718
719 rc = SSMR3PutU32(pSSM, pClient->conn->vMajor);
720 AssertRCReturn(rc, rc);
721
722 rc = SSMR3PutU32(pSSM, pClient->conn->vMinor);
723 AssertRCReturn(rc, rc);
724
725 rc = SSMR3PutMem(pSSM, pClient, sizeof(*pClient));
726 AssertRCReturn(rc, rc);
727
728 if (pClient->currentCtx && pClient->currentContextNumber>=0)
729 {
730 b = crHashtableGetDataKey(cr_server.contextTable, pClient->currentCtx, &key);
731 CRASSERT(b);
732 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
733 AssertRCReturn(rc, rc);
734 }
735
736 if (pClient->currentMural && pClient->currentWindow>=0)
737 {
738 b = crHashtableGetDataKey(cr_server.muralTable, pClient->currentMural, &key);
739 CRASSERT(b);
740 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
741 AssertRCReturn(rc, rc);
742 }
743 }
744 }
745
746 cr_server.bIsInSavingState = GL_FALSE;
747
748 return VINF_SUCCESS;
749}
750
751DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM, uint32_t version)
752{
753 int32_t rc, i;
754 uint32_t ui, uiNumElems;
755 unsigned long key;
756
757 if (!cr_server.bIsInLoadingState)
758 {
759 /* AssertRCReturn(...) will leave us in loading state, but it doesn't matter as we'd be failing anyway */
760 cr_server.bIsInLoadingState = GL_TRUE;
761
762 /* Read number of clients */
763 rc = SSMR3GetU32(pSSM, &g_hackVBoxServerSaveLoadCallsLeft);
764 AssertRCReturn(rc, rc);
765 }
766
767 g_hackVBoxServerSaveLoadCallsLeft--;
768
769 /* Do nothing untill we're being called last time */
770 if (g_hackVBoxServerSaveLoadCallsLeft>0)
771 {
772 return VINF_SUCCESS;
773 }
774
775 /* Load and recreate rendering contexts */
776 rc = SSMR3GetU32(pSSM, &uiNumElems);
777 AssertRCReturn(rc, rc);
778 for (ui=0; ui<uiNumElems; ++ui)
779 {
780 CRCreateInfo_t createInfo;
781 char psz[200];
782 GLint ctxID;
783
784 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
785 AssertRCReturn(rc, rc);
786 rc = SSMR3GetMem(pSSM, &createInfo, sizeof(createInfo));
787 AssertRCReturn(rc, rc);
788
789 if (createInfo.pszDpyName)
790 {
791 rc = SSMR3GetStrZEx(pSSM, psz, 200, NULL);
792 AssertRCReturn(rc, rc);
793 createInfo.pszDpyName = psz;
794 }
795
796 ctxID = crServerDispatchCreateContextEx(createInfo.pszDpyName, createInfo.visualBits, 0, key, createInfo.internalID);
797 CRASSERT((int64_t)ctxID == (int64_t)key);
798 }
799
800 /* Restore context state data */
801 for (ui=0; ui<uiNumElems; ++ui)
802 {
803 CRContext *pContext;
804
805 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
806 AssertRCReturn(rc, rc);
807
808 pContext = (CRContext*) crHashtableSearch(cr_server.contextTable, key);
809 CRASSERT(pContext);
810
811 rc = crStateLoadContext(pContext, pSSM);
812 AssertRCReturn(rc, rc);
813 }
814
815 /* Load windows */
816 rc = SSMR3GetU32(pSSM, &uiNumElems);
817 AssertRCReturn(rc, rc);
818 for (ui=0; ui<uiNumElems; ++ui)
819 {
820 CRCreateInfo_t createInfo;
821 char psz[200];
822 GLint winID;
823 unsigned long key;
824
825 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
826 AssertRCReturn(rc, rc);
827 rc = SSMR3GetMem(pSSM, &createInfo, sizeof(createInfo));
828 AssertRCReturn(rc, rc);
829
830 if (createInfo.pszDpyName)
831 {
832 rc = SSMR3GetStrZEx(pSSM, psz, 200, NULL);
833 AssertRCReturn(rc, rc);
834 createInfo.pszDpyName = psz;
835 }
836
837 winID = crServerDispatchWindowCreateEx(createInfo.pszDpyName, createInfo.visualBits, key);
838 CRASSERT((int64_t)winID == (int64_t)key);
839 }
840
841 /* Load cr_server.muralTable */
842 rc = SSMR3GetU32(pSSM, &uiNumElems);
843 AssertRCReturn(rc, rc);
844 for (ui=0; ui<uiNumElems; ++ui)
845 {
846 CRMuralInfo muralInfo;
847
848 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
849 AssertRCReturn(rc, rc);
850 rc = SSMR3GetMem(pSSM, &muralInfo, sizeof(muralInfo));
851 AssertRCReturn(rc, rc);
852
853 /* Restore windows geometry info */
854 crServerDispatchWindowSize(key, muralInfo.underlyingDisplay[2], muralInfo.underlyingDisplay[3]);
855 crServerDispatchWindowPosition(key, muralInfo.underlyingDisplay[0], muralInfo.underlyingDisplay[1]);
856 }
857
858 /* Load starting free context and window IDs */
859 rc = SSMR3GetMem(pSSM, &cr_server.idsPool, sizeof(cr_server.idsPool));
860 CRASSERT(rc == VINF_SUCCESS);
861
862 /* Load clients info */
863 for (i = 0; i < cr_server.numClients; i++)
864 {
865 if (cr_server.clients[i] && cr_server.clients[i]->conn)
866 {
867 CRClient *pClient = cr_server.clients[i];
868 CRClient client;
869 unsigned long ctxID=-1, winID=-1;
870
871 rc = SSMR3GetU32(pSSM, &ui);
872 AssertRCReturn(rc, rc);
873 /* If this assert fires, then we should search correct client in the list first*/
874 CRASSERT(ui == pClient->conn->u32ClientID);
875
876 if (version>=4)
877 {
878 rc = SSMR3GetU32(pSSM, &pClient->conn->vMajor);
879 AssertRCReturn(rc, rc);
880
881 rc = SSMR3GetU32(pSSM, &pClient->conn->vMinor);
882 AssertRCReturn(rc, rc);
883 }
884
885 rc = SSMR3GetMem(pSSM, &client, sizeof(client));
886 CRASSERT(rc == VINF_SUCCESS);
887
888 client.conn = pClient->conn;
889 /* We can't reassign client number, as we'd get wrong results in TranslateTextureID
890 * and fail to bind old textures.
891 */
892 /*client.number = pClient->number;*/
893 *pClient = client;
894
895 pClient->currentContextNumber = -1;
896 pClient->currentCtx = cr_server.DummyContext;
897 pClient->currentMural = NULL;
898 pClient->currentWindow = -1;
899
900 cr_server.curClient = pClient;
901
902 if (client.currentCtx && client.currentContextNumber>=0)
903 {
904 rc = SSMR3GetMem(pSSM, &ctxID, sizeof(ctxID));
905 AssertRCReturn(rc, rc);
906 client.currentCtx = (CRContext*) crHashtableSearch(cr_server.contextTable, ctxID);
907 CRASSERT(client.currentCtx);
908 //pClient->currentCtx = client.currentCtx;
909 //pClient->currentContextNumber = ctxID;
910 }
911
912 if (client.currentMural && client.currentWindow>=0)
913 {
914 rc = SSMR3GetMem(pSSM, &winID, sizeof(winID));
915 AssertRCReturn(rc, rc);
916 client.currentMural = (CRMuralInfo*) crHashtableSearch(cr_server.muralTable, winID);
917 CRASSERT(client.currentMural);
918 //pClient->currentMural = client.currentMural;
919 //pClient->currentWindow = winID;
920 }
921
922 /* Restore client active context and window */
923 crServerDispatchMakeCurrent(winID, 0, ctxID);
924
925 if (0)
926 {
927 CRContext *tmpCtx;
928 CRCreateInfo_t *createInfo;
929 GLfloat one[4] = { 1, 1, 1, 1 };
930 GLfloat amb[4] = { 0.4f, 0.4f, 0.4f, 1.0f };
931
932 crServerDispatchMakeCurrent(winID, 0, ctxID);
933
934 crHashtableWalk(client.currentCtx->shared->textureTable, crVBoxServerSyncTextureCB, client.currentCtx);
935
936 crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.base1D, GL_TRUE);
937 crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.base2D, GL_TRUE);
938 crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.base3D, GL_TRUE);
939#ifdef CR_ARB_texture_cube_map
940 crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.baseCubeMap, GL_TRUE);
941#endif
942#ifdef CR_NV_texture_rectangle
943 //@todo this doesn't work as expected
944 //crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.baseRect, GL_TRUE);
945#endif
946 /*cr_server.head_spu->dispatch_table.Materialfv(GL_FRONT_AND_BACK, GL_AMBIENT, amb);
947 cr_server.head_spu->dispatch_table.LightModelfv(GL_LIGHT_MODEL_AMBIENT, amb);
948 cr_server.head_spu->dispatch_table.Lightfv(GL_LIGHT1, GL_DIFFUSE, one);
949
950 cr_server.head_spu->dispatch_table.Enable(GL_LIGHTING);
951 cr_server.head_spu->dispatch_table.Enable(GL_LIGHT0);
952 cr_server.head_spu->dispatch_table.Enable(GL_LIGHT1);
953
954 cr_server.head_spu->dispatch_table.Enable(GL_CULL_FACE);
955 cr_server.head_spu->dispatch_table.Enable(GL_TEXTURE_2D);*/
956
957 //crStateViewport( 0, 0, 600, 600 );
958 //pClient->currentMural->viewportValidated = GL_FALSE;
959 //cr_server.head_spu->dispatch_table.Viewport( 0, 0, 600, 600 );
960
961 //crStateMatrixMode(GL_PROJECTION);
962 //cr_server.head_spu->dispatch_table.MatrixMode(GL_PROJECTION);
963
964 //crStateLoadIdentity();
965 //cr_server.head_spu->dispatch_table.LoadIdentity();
966
967 //crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
968 //cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
969
970 //crStateMatrixMode(GL_MODELVIEW);
971 //cr_server.head_spu->dispatch_table.MatrixMode(GL_MODELVIEW);
972 //crServerDispatchLoadIdentity();
973 //crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
974 //cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
975 //crServerDispatchLoadIdentity();
976
977 /*createInfo = (CRCreateInfo_t *) crHashtableSearch(cr_server.pContextCreateInfoTable, ctxID);
978 CRASSERT(createInfo);
979 tmpCtx = crStateCreateContext(NULL, createInfo->visualBits, NULL);
980 CRASSERT(tmpCtx);
981 crStateDiffContext(tmpCtx, client.currentCtx);
982 crStateDestroyContext(tmpCtx);*/
983 }
984 }
985 }
986
987 //crServerDispatchMakeCurrent(-1, 0, -1);
988
989 cr_server.curClient = NULL;
990
991 {
992 GLenum err = crServerDispatchGetError();
993
994 if (err != GL_NO_ERROR)
995 {
996 crWarning("crServer: glGetError %d after loading snapshot", err);
997 }
998 }
999
1000 cr_server.bIsInLoadingState = GL_FALSE;
1001
1002 return VINF_SUCCESS;
1003}
1004
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