VirtualBox

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

Last change on this file since 18255 was 17964, checked in by vboxsync, 16 years ago

crOpenGL: fix client dissconection handling

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