VirtualBox

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

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

crOpenGL: add protocol version check(4108), add max connected clients check

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 28.8 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 = SSMR3PutMem(pSSM, pClient, sizeof(*pClient));
712 AssertRCReturn(rc, rc);
713
714 if (pClient->currentCtx && pClient->currentContextNumber>=0)
715 {
716 b = crHashtableGetDataKey(cr_server.contextTable, pClient->currentCtx, &key);
717 CRASSERT(b);
718 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
719 AssertRCReturn(rc, rc);
720 }
721
722 if (pClient->currentMural && pClient->currentWindow>=0)
723 {
724 b = crHashtableGetDataKey(cr_server.muralTable, pClient->currentMural, &key);
725 CRASSERT(b);
726 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
727 AssertRCReturn(rc, rc);
728 }
729 }
730 }
731
732 cr_server.bIsInSavingState = GL_FALSE;
733
734 return VINF_SUCCESS;
735}
736
737DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM)
738{
739 int32_t rc, i;
740 uint32_t ui, uiNumElems;
741 unsigned long key;
742
743 if (!cr_server.bIsInLoadingState)
744 {
745 /* AssertRCReturn(...) will leave us in loading state, but it doesn't matter as we'd be failing anyway */
746 cr_server.bIsInLoadingState = GL_TRUE;
747
748 /* Read number of clients */
749 rc = SSMR3GetU32(pSSM, &g_hackVBoxServerSaveLoadCallsLeft);
750 AssertRCReturn(rc, rc);
751 }
752
753 g_hackVBoxServerSaveLoadCallsLeft--;
754
755 /* Do nothing untill we're being called last time */
756 if (g_hackVBoxServerSaveLoadCallsLeft>0)
757 {
758 return VINF_SUCCESS;
759 }
760
761 /* Load and recreate rendering contexts */
762 rc = SSMR3GetU32(pSSM, &uiNumElems);
763 AssertRCReturn(rc, rc);
764 for (ui=0; ui<uiNumElems; ++ui)
765 {
766 CRCreateInfo_t createInfo;
767 char psz[200];
768 GLint ctxID;
769
770 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
771 AssertRCReturn(rc, rc);
772 rc = SSMR3GetMem(pSSM, &createInfo, sizeof(createInfo));
773 AssertRCReturn(rc, rc);
774
775 if (createInfo.pszDpyName)
776 {
777 rc = SSMR3GetStrZEx(pSSM, psz, 200, NULL);
778 AssertRCReturn(rc, rc);
779 createInfo.pszDpyName = psz;
780 }
781
782 ctxID = crServerDispatchCreateContextEx(createInfo.pszDpyName, createInfo.visualBits, 0, key, createInfo.internalID);
783 CRASSERT((int64_t)ctxID == (int64_t)key);
784 }
785
786 /* Restore context state data */
787 for (ui=0; ui<uiNumElems; ++ui)
788 {
789 CRContext *pContext;
790
791 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
792 AssertRCReturn(rc, rc);
793
794 pContext = (CRContext*) crHashtableSearch(cr_server.contextTable, key);
795 CRASSERT(pContext);
796
797 rc = crStateLoadContext(pContext, pSSM);
798 AssertRCReturn(rc, rc);
799 }
800
801 /* Load windows */
802 rc = SSMR3GetU32(pSSM, &uiNumElems);
803 AssertRCReturn(rc, rc);
804 for (ui=0; ui<uiNumElems; ++ui)
805 {
806 CRCreateInfo_t createInfo;
807 char psz[200];
808 GLint winID;
809 unsigned long key;
810
811 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
812 AssertRCReturn(rc, rc);
813 rc = SSMR3GetMem(pSSM, &createInfo, sizeof(createInfo));
814 AssertRCReturn(rc, rc);
815
816 if (createInfo.pszDpyName)
817 {
818 rc = SSMR3GetStrZEx(pSSM, psz, 200, NULL);
819 AssertRCReturn(rc, rc);
820 createInfo.pszDpyName = psz;
821 }
822
823 winID = crServerDispatchWindowCreateEx(createInfo.pszDpyName, createInfo.visualBits, key);
824 CRASSERT((int64_t)winID == (int64_t)key);
825 }
826
827 /* Load cr_server.muralTable */
828 rc = SSMR3GetU32(pSSM, &uiNumElems);
829 AssertRCReturn(rc, rc);
830 for (ui=0; ui<uiNumElems; ++ui)
831 {
832 CRMuralInfo muralInfo;
833
834 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
835 AssertRCReturn(rc, rc);
836 rc = SSMR3GetMem(pSSM, &muralInfo, sizeof(muralInfo));
837 AssertRCReturn(rc, rc);
838
839 /* Restore windows geometry info */
840 crServerDispatchWindowSize(key, muralInfo.underlyingDisplay[2], muralInfo.underlyingDisplay[3]);
841 crServerDispatchWindowPosition(key, muralInfo.underlyingDisplay[0], muralInfo.underlyingDisplay[1]);
842 }
843
844 /* Load starting free context and window IDs */
845 rc = SSMR3GetMem(pSSM, &cr_server.idsPool, sizeof(cr_server.idsPool));
846 CRASSERT(rc == VINF_SUCCESS);
847
848 /* Load clients info */
849 for (i = 0; i < cr_server.numClients; i++)
850 {
851 if (cr_server.clients[i] && cr_server.clients[i]->conn)
852 {
853 CRClient *pClient = cr_server.clients[i];
854 CRClient client;
855 unsigned long ctxID=-1, winID=-1;
856
857 rc = SSMR3GetU32(pSSM, &ui);
858 AssertRCReturn(rc, rc);
859 /* If this assert fires, then we should search correct client in the list first*/
860 CRASSERT(ui == pClient->conn->u32ClientID);
861
862 rc = SSMR3GetMem(pSSM, &client, sizeof(client));
863 CRASSERT(rc == VINF_SUCCESS);
864
865 client.conn = pClient->conn;
866 /* We can't reassign client number, as we'd get wrong results in TranslateTextureID
867 * and fail to bind old textures.
868 */
869 /*client.number = pClient->number;*/
870 *pClient = client;
871
872 pClient->currentContextNumber = -1;
873 pClient->currentCtx = cr_server.DummyContext;
874 pClient->currentMural = NULL;
875 pClient->currentWindow = -1;
876
877 cr_server.curClient = pClient;
878
879 if (client.currentCtx && client.currentContextNumber>=0)
880 {
881 rc = SSMR3GetMem(pSSM, &ctxID, sizeof(ctxID));
882 AssertRCReturn(rc, rc);
883 client.currentCtx = (CRContext*) crHashtableSearch(cr_server.contextTable, ctxID);
884 CRASSERT(client.currentCtx);
885 //pClient->currentCtx = client.currentCtx;
886 //pClient->currentContextNumber = ctxID;
887 }
888
889 if (client.currentMural && client.currentWindow>=0)
890 {
891 rc = SSMR3GetMem(pSSM, &winID, sizeof(winID));
892 AssertRCReturn(rc, rc);
893 client.currentMural = (CRMuralInfo*) crHashtableSearch(cr_server.muralTable, winID);
894 CRASSERT(client.currentMural);
895 //pClient->currentMural = client.currentMural;
896 //pClient->currentWindow = winID;
897 }
898
899 /* Restore client active context and window */
900 crServerDispatchMakeCurrent(winID, 0, ctxID);
901
902 if (0)
903 {
904 CRContext *tmpCtx;
905 CRCreateInfo_t *createInfo;
906 GLfloat one[4] = { 1, 1, 1, 1 };
907 GLfloat amb[4] = { 0.4f, 0.4f, 0.4f, 1.0f };
908
909 crServerDispatchMakeCurrent(winID, 0, ctxID);
910
911 crHashtableWalk(client.currentCtx->shared->textureTable, crVBoxServerSyncTextureCB, client.currentCtx);
912
913 crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.base1D, GL_TRUE);
914 crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.base2D, GL_TRUE);
915 crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.base3D, GL_TRUE);
916#ifdef CR_ARB_texture_cube_map
917 crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.baseCubeMap, GL_TRUE);
918#endif
919#ifdef CR_NV_texture_rectangle
920 //@todo this doesn't work as expected
921 //crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.baseRect, GL_TRUE);
922#endif
923 /*cr_server.head_spu->dispatch_table.Materialfv(GL_FRONT_AND_BACK, GL_AMBIENT, amb);
924 cr_server.head_spu->dispatch_table.LightModelfv(GL_LIGHT_MODEL_AMBIENT, amb);
925 cr_server.head_spu->dispatch_table.Lightfv(GL_LIGHT1, GL_DIFFUSE, one);
926
927 cr_server.head_spu->dispatch_table.Enable(GL_LIGHTING);
928 cr_server.head_spu->dispatch_table.Enable(GL_LIGHT0);
929 cr_server.head_spu->dispatch_table.Enable(GL_LIGHT1);
930
931 cr_server.head_spu->dispatch_table.Enable(GL_CULL_FACE);
932 cr_server.head_spu->dispatch_table.Enable(GL_TEXTURE_2D);*/
933
934 //crStateViewport( 0, 0, 600, 600 );
935 //pClient->currentMural->viewportValidated = GL_FALSE;
936 //cr_server.head_spu->dispatch_table.Viewport( 0, 0, 600, 600 );
937
938 //crStateMatrixMode(GL_PROJECTION);
939 //cr_server.head_spu->dispatch_table.MatrixMode(GL_PROJECTION);
940
941 //crStateLoadIdentity();
942 //cr_server.head_spu->dispatch_table.LoadIdentity();
943
944 //crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
945 //cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
946
947 //crStateMatrixMode(GL_MODELVIEW);
948 //cr_server.head_spu->dispatch_table.MatrixMode(GL_MODELVIEW);
949 //crServerDispatchLoadIdentity();
950 //crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
951 //cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
952 //crServerDispatchLoadIdentity();
953
954 /*createInfo = (CRCreateInfo_t *) crHashtableSearch(cr_server.pContextCreateInfoTable, ctxID);
955 CRASSERT(createInfo);
956 tmpCtx = crStateCreateContext(NULL, createInfo->visualBits, NULL);
957 CRASSERT(tmpCtx);
958 crStateDiffContext(tmpCtx, client.currentCtx);
959 crStateDestroyContext(tmpCtx);*/
960 }
961 }
962 }
963
964 //crServerDispatchMakeCurrent(-1, 0, -1);
965
966 cr_server.curClient = NULL;
967
968 {
969 GLenum err = crServerDispatchGetError();
970
971 if (err != GL_NO_ERROR)
972 {
973 crWarning("crServer: glGetError %d after loading snapshot", err);
974 }
975 }
976
977 cr_server.bIsInLoadingState = GL_FALSE;
978
979 return VINF_SUCCESS;
980}
981
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