VirtualBox

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

Last change on this file since 20327 was 19879, checked in by vboxsync, 16 years ago

crOpenGL: fix bug with crashes in unloaded render_spu.dll (hopefully)

  • 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
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
321void crVBoxServerAddClient(uint32_t u32ClientID)
322{
323 CRClient *newClient = (CRClient *) crCalloc(sizeof(CRClient));
324
325 crDebug("crServer: AddClient u32ClientID=%d", u32ClientID);
326
327 newClient->spu_id = 0;
328 newClient->currentCtx = cr_server.DummyContext;
329 newClient->currentContextNumber = -1;
330 newClient->conn = crNetAcceptClient(cr_server.protocol, NULL,
331 cr_server.tcpip_port,
332 cr_server.mtu, 0);
333 newClient->conn->u32ClientID = u32ClientID;
334
335 cr_server.clients[cr_server.numClients++] = newClient;
336
337 crServerAddToRunQueue(newClient);
338}
339
340void crVBoxServerRemoveClient(uint32_t u32ClientID)
341{
342 CRClient *pClient;
343 int32_t i;
344
345 crDebug("crServer: RemoveClient u32ClientID=%d", u32ClientID);
346
347 for (i = 0; i < cr_server.numClients; i++)
348 {
349 if (cr_server.clients[i] && cr_server.clients[i]->conn
350 && cr_server.clients[i]->conn->u32ClientID==u32ClientID)
351 {
352 break;
353 }
354 }
355 pClient = cr_server.clients[i];
356 CRASSERT(pClient);
357
358 /* Disconnect the client */
359 pClient->conn->Disconnect(pClient->conn);
360
361 /* Let server clear client from the queue */
362 crServerDeleteClient(pClient);
363}
364
365void crVBoxServerClientWrite(uint32_t u32ClientID, uint8_t *pBuffer, uint32_t cbBuffer)
366{
367 CRClient *pClient;
368 int32_t i;
369
370 //crDebug("crServer: [%x] ClientWrite u32ClientID=%d", crThreadID(), u32ClientID);
371
372 for (i = 0; i < cr_server.numClients; i++)
373 {
374 if (cr_server.clients[i] && cr_server.clients[i]->conn
375 && cr_server.clients[i]->conn->u32ClientID==u32ClientID)
376 {
377 break;
378 }
379 }
380 pClient = cr_server.clients[i];
381 CRASSERT(pClient);
382
383 CRASSERT(pBuffer);
384
385 /* This should never fire unless we start to multithread */
386 CRASSERT(pClient->conn->pBuffer==NULL && pClient->conn->cbBuffer==0);
387
388 /* Check if there's a blocker in queue and it's not this client */
389 if (cr_server.run_queue->client != pClient
390 && crServerClientInBeginEnd(cr_server.run_queue->client))
391 {
392 crDebug("crServer: client %d blocked, allow_redir_ptr = 0", u32ClientID);
393 pClient->conn->allow_redir_ptr = 0;
394 }
395 else
396 {
397 pClient->conn->allow_redir_ptr = 1;
398 }
399
400 pClient->conn->pBuffer = pBuffer;
401 pClient->conn->cbBuffer = cbBuffer;
402
403 crNetRecv();
404 CRASSERT(pClient->conn->pBuffer==NULL && pClient->conn->cbBuffer==0);
405
406 crServerServiceClients();
407
408#if 0
409 if (pClient->currentMural) {
410 crStateViewport( 0, 0, 500, 500 );
411 pClient->currentMural->viewportValidated = GL_FALSE;
412 cr_server.head_spu->dispatch_table.Viewport( 0, 0, 500, 500 );
413 crStateViewport( 0, 0, 600, 600 );
414 pClient->currentMural->viewportValidated = GL_FALSE;
415 cr_server.head_spu->dispatch_table.Viewport( 0, 0, 600, 600 );
416
417 crStateMatrixMode(GL_PROJECTION);
418 cr_server.head_spu->dispatch_table.MatrixMode(GL_PROJECTION);
419 crServerDispatchLoadIdentity();
420 crStateFrustum(-0.6, 0.6, -0.5, 0.5, 1.5, 150.0);
421 cr_server.head_spu->dispatch_table.Frustum(-0.6, 0.6, -0.5, 0.5, 1.5, 150.0);
422 crServerDispatchLoadIdentity();
423 crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
424 cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
425
426 crStateMatrixMode(GL_MODELVIEW);
427 cr_server.head_spu->dispatch_table.MatrixMode(GL_MODELVIEW);
428 crServerDispatchLoadIdentity();
429 crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
430 cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
431 crServerDispatchLoadIdentity();
432 }
433#endif
434
435 crStateResetCurrentPointers(&cr_server.current);
436
437 CRASSERT(!pClient->conn->allow_redir_ptr || crNetNumMessages(pClient->conn)==0);
438}
439
440int32_t crVBoxServerClientRead(uint32_t u32ClientID, uint8_t *pBuffer, uint32_t *pcbBuffer)
441{
442 CRClient *pClient;
443 int32_t i;
444
445 //crDebug("crServer: [%x] ClientRead u32ClientID=%d", crThreadID(), u32ClientID);
446
447 for (i = 0; i < cr_server.numClients; i++)
448 {
449 if (cr_server.clients[i] && cr_server.clients[i]->conn
450 && cr_server.clients[i]->conn->u32ClientID==u32ClientID)
451 {
452 break;
453 }
454 }
455 pClient = cr_server.clients[i];
456 CRASSERT(pClient);
457
458 if (pClient->conn->cbHostBuffer > *pcbBuffer)
459 {
460 crWarning("crServer: [%lx] ClientRead u32ClientID=%d FAIL, host buffer too small %d of %d",
461 crThreadID(), u32ClientID, *pcbBuffer, pClient->conn->cbHostBuffer);
462
463 /* Return the size of needed buffer */
464 *pcbBuffer = pClient->conn->cbHostBuffer;
465
466 return VERR_BUFFER_OVERFLOW;
467 }
468
469 *pcbBuffer = pClient->conn->cbHostBuffer;
470
471 if (*pcbBuffer)
472 {
473 CRASSERT(pClient->conn->pHostBuffer);
474
475 crMemcpy(pBuffer, pClient->conn->pHostBuffer, *pcbBuffer);
476 pClient->conn->cbHostBuffer = 0;
477 }
478
479 return VINF_SUCCESS;
480}
481
482int
483CRServerMain(int argc, char *argv[])
484{
485 crServerInit(argc, argv);
486
487 crServerSerializeRemoteStreams();
488
489 crServerTearDown();
490
491 tearingdown = 0;
492
493 return 0;
494}
495
496static void crVBoxServerSaveMuralCB(unsigned long key, void *data1, void *data2)
497{
498 CRMuralInfo *pMI = (CRMuralInfo*) data1;
499 PSSMHANDLE pSSM = (PSSMHANDLE) data2;
500 int32_t rc;
501
502 CRASSERT(pMI && pSSM);
503
504 /* Don't store default mural */
505 if (!key) return;
506
507 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
508 CRASSERT(rc == VINF_SUCCESS);
509
510 rc = SSMR3PutMem(pSSM, pMI, sizeof(*pMI));
511 CRASSERT(rc == VINF_SUCCESS);
512}
513
514/* @todo add hashtable walker with result info and intermediate abort */
515static void crVBoxServerSaveCreateInfoCB(unsigned long key, void *data1, void *data2)
516{
517 CRCreateInfo_t *pCreateInfo = (CRCreateInfo_t *) data1;
518 PSSMHANDLE pSSM = (PSSMHANDLE) data2;
519 int32_t rc;
520
521 CRASSERT(pCreateInfo && pSSM);
522
523 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
524 CRASSERT(rc == VINF_SUCCESS);
525
526 rc = SSMR3PutMem(pSSM, pCreateInfo, sizeof(*pCreateInfo));
527 CRASSERT(rc == VINF_SUCCESS);
528
529 if (pCreateInfo->pszDpyName)
530 {
531 rc = SSMR3PutStrZ(pSSM, pCreateInfo->pszDpyName);
532 CRASSERT(rc == VINF_SUCCESS);
533 }
534}
535
536static void crVBoxServerSyncTextureCB(unsigned long key, void *data1, void *data2)
537{
538 CRTextureObj *pTexture = (CRTextureObj *) data1;
539 CRContext *pContext = (CRContext *) data2;
540
541 CRASSERT(pTexture && pContext);
542 crStateTextureObjectDiff(pContext, NULL, NULL, pTexture, GL_TRUE);
543}
544
545static void crVBoxServerSaveContextStateCB(unsigned long key, void *data1, void *data2)
546{
547 CRContext *pContext = (CRContext *) data1;
548 PSSMHANDLE pSSM = (PSSMHANDLE) data2;
549 int32_t rc;
550
551 CRASSERT(pContext && pSSM);
552
553 /* We could have skipped saving the key and use similar callback to load context states back,
554 * but there's no guarantee we'd traverse hashtable in same order after loading.
555 */
556 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
557 CRASSERT(rc == VINF_SUCCESS);
558
559#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
560 if (cr_server.curClient)
561 {
562 crServerDispatchMakeCurrent(cr_server.curClient->currentWindow, 0, pContext->id);
563 }
564#endif
565
566 rc = crStateSaveContext(pContext, pSSM);
567 CRASSERT(rc == VINF_SUCCESS);
568}
569
570static uint32_t g_hackVBoxServerSaveLoadCallsLeft = 0;
571
572DECLEXPORT(int32_t) crVBoxServerSaveState(PSSMHANDLE pSSM)
573{
574 int32_t rc, i;
575 uint32_t ui32;
576 GLboolean b;
577 unsigned long key;
578#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
579 unsigned long ctxID=-1, winID=-1;
580#endif
581
582 /* We shouldn't be called if there's no clients at all*/
583 CRASSERT(cr_server.numClients>0);
584
585 /* @todo it's hack atm */
586 /* We want to be called only once to save server state but atm we're being called from svcSaveState
587 * for every connected client (e.g. guest opengl application)
588 */
589 if (!cr_server.bIsInSavingState) /* It's first call */
590 {
591 cr_server.bIsInSavingState = GL_TRUE;
592
593 /* Store number of clients */
594 rc = SSMR3PutU32(pSSM, (uint32_t) cr_server.numClients);
595 AssertRCReturn(rc, rc);
596
597 g_hackVBoxServerSaveLoadCallsLeft = cr_server.numClients;
598 }
599
600 g_hackVBoxServerSaveLoadCallsLeft--;
601
602 /* Do nothing untill we're being called last time */
603 if (g_hackVBoxServerSaveLoadCallsLeft>0)
604 {
605 return VINF_SUCCESS;
606 }
607
608 /* Save rendering contexts creation info */
609 ui32 = crHashtableNumElements(cr_server.pContextCreateInfoTable);
610 rc = SSMR3PutU32(pSSM, (uint32_t) ui32);
611 AssertRCReturn(rc, rc);
612 crHashtableWalk(cr_server.pContextCreateInfoTable, crVBoxServerSaveCreateInfoCB, pSSM);
613
614#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
615 /* Save current win and ctx IDs, as we'd rebind contexts when saving textures */
616 if (cr_server.curClient)
617 {
618 ctxID = cr_server.curClient->currentContextNumber;
619 winID = cr_server.curClient->currentWindow;
620 }
621#endif
622
623 /* Save contexts state tracker data */
624 /* @todo For now just some blind data dumps,
625 * but I've a feeling those should be saved/restored in a very strict sequence to
626 * allow diff_api to work correctly.
627 * Should be tested more with multiply guest opengl apps working when saving VM snapshot.
628 */
629 crHashtableWalk(cr_server.contextTable, crVBoxServerSaveContextStateCB, pSSM);
630
631#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
632 /* Restore original win and ctx IDs*/
633 if (cr_server.curClient)
634 {
635 crServerDispatchMakeCurrent(winID, 0, ctxID);
636 }
637#endif
638
639 /* Save windows creation info */
640 ui32 = crHashtableNumElements(cr_server.pWindowCreateInfoTable);
641 rc = SSMR3PutU32(pSSM, (uint32_t) ui32);
642 AssertRCReturn(rc, rc);
643 crHashtableWalk(cr_server.pWindowCreateInfoTable, crVBoxServerSaveCreateInfoCB, pSSM);
644
645 /* Save cr_server.muralTable
646 * @todo we don't need it all, just geometry info actually
647 * @todo store visible regions as well
648 */
649 ui32 = crHashtableNumElements(cr_server.muralTable);
650 /* There should be default mural always */
651 CRASSERT(ui32>=1);
652 rc = SSMR3PutU32(pSSM, (uint32_t) ui32-1);
653 AssertRCReturn(rc, rc);
654 crHashtableWalk(cr_server.muralTable, crVBoxServerSaveMuralCB, pSSM);
655
656 /* Save starting free context and window IDs */
657 rc = SSMR3PutMem(pSSM, &cr_server.idsPool, sizeof(cr_server.idsPool));
658 AssertRCReturn(rc, rc);
659
660 /* Save clients info */
661 for (i = 0; i < cr_server.numClients; i++)
662 {
663 if (cr_server.clients[i] && cr_server.clients[i]->conn)
664 {
665 CRClient *pClient = cr_server.clients[i];
666
667 rc = SSMR3PutU32(pSSM, pClient->conn->u32ClientID);
668 AssertRCReturn(rc, rc);
669
670 rc = SSMR3PutMem(pSSM, pClient, sizeof(*pClient));
671 AssertRCReturn(rc, rc);
672
673 if (pClient->currentCtx && pClient->currentContextNumber>=0)
674 {
675 b = crHashtableGetDataKey(cr_server.contextTable, pClient->currentCtx, &key);
676 CRASSERT(b);
677 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
678 AssertRCReturn(rc, rc);
679 }
680
681 if (pClient->currentMural && pClient->currentWindow>=0)
682 {
683 b = crHashtableGetDataKey(cr_server.muralTable, pClient->currentMural, &key);
684 CRASSERT(b);
685 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
686 AssertRCReturn(rc, rc);
687 }
688 }
689 }
690
691 cr_server.bIsInSavingState = GL_FALSE;
692
693 return VINF_SUCCESS;
694}
695
696DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM)
697{
698 int32_t rc, i;
699 uint32_t ui, uiNumElems;
700 unsigned long key;
701
702 if (!cr_server.bIsInLoadingState)
703 {
704 /* AssertRCReturn(...) will leave us in loading state, but it doesn't matter as we'd be failing anyway */
705 cr_server.bIsInLoadingState = GL_TRUE;
706
707 /* Read number of clients */
708 rc = SSMR3GetU32(pSSM, &g_hackVBoxServerSaveLoadCallsLeft);
709 AssertRCReturn(rc, rc);
710 }
711
712 g_hackVBoxServerSaveLoadCallsLeft--;
713
714 /* Do nothing untill we're being called last time */
715 if (g_hackVBoxServerSaveLoadCallsLeft>0)
716 {
717 return VINF_SUCCESS;
718 }
719
720 /* Load and recreate rendering contexts */
721 rc = SSMR3GetU32(pSSM, &uiNumElems);
722 AssertRCReturn(rc, rc);
723 for (ui=0; ui<uiNumElems; ++ui)
724 {
725 CRCreateInfo_t createInfo;
726 char psz[200];
727 GLint ctxID;
728
729 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
730 AssertRCReturn(rc, rc);
731 rc = SSMR3GetMem(pSSM, &createInfo, sizeof(createInfo));
732 AssertRCReturn(rc, rc);
733
734 if (createInfo.pszDpyName)
735 {
736 rc = SSMR3GetStrZEx(pSSM, psz, 200, NULL);
737 AssertRCReturn(rc, rc);
738 createInfo.pszDpyName = psz;
739 }
740
741 ctxID = crServerDispatchCreateContextEx(createInfo.pszDpyName, createInfo.visualBits, 0, key, createInfo.internalID);
742 CRASSERT((int64_t)ctxID == (int64_t)key);
743 }
744
745 /* Restore context state data */
746 for (ui=0; ui<uiNumElems; ++ui)
747 {
748 CRContext *pContext;
749
750 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
751 AssertRCReturn(rc, rc);
752
753 pContext = (CRContext*) crHashtableSearch(cr_server.contextTable, key);
754 CRASSERT(pContext);
755
756 rc = crStateLoadContext(pContext, pSSM);
757 AssertRCReturn(rc, rc);
758 }
759
760 /* Load windows */
761 rc = SSMR3GetU32(pSSM, &uiNumElems);
762 AssertRCReturn(rc, rc);
763 for (ui=0; ui<uiNumElems; ++ui)
764 {
765 CRCreateInfo_t createInfo;
766 char psz[200];
767 GLint winID;
768 unsigned long key;
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 winID = crServerDispatchWindowCreateEx(createInfo.pszDpyName, createInfo.visualBits, key);
783 CRASSERT((int64_t)winID == (int64_t)key);
784 }
785
786 /* Load cr_server.muralTable */
787 rc = SSMR3GetU32(pSSM, &uiNumElems);
788 AssertRCReturn(rc, rc);
789 for (ui=0; ui<uiNumElems; ++ui)
790 {
791 CRMuralInfo muralInfo;
792
793 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
794 AssertRCReturn(rc, rc);
795 rc = SSMR3GetMem(pSSM, &muralInfo, sizeof(muralInfo));
796 AssertRCReturn(rc, rc);
797
798 /* Restore windows geometry info */
799 crServerDispatchWindowSize(key, muralInfo.underlyingDisplay[2], muralInfo.underlyingDisplay[3]);
800 crServerDispatchWindowPosition(key, muralInfo.underlyingDisplay[0], muralInfo.underlyingDisplay[1]);
801 }
802
803 /* Load starting free context and window IDs */
804 rc = SSMR3GetMem(pSSM, &cr_server.idsPool, sizeof(cr_server.idsPool));
805 CRASSERT(rc == VINF_SUCCESS);
806
807 /* Load clients info */
808 for (i = 0; i < cr_server.numClients; i++)
809 {
810 if (cr_server.clients[i] && cr_server.clients[i]->conn)
811 {
812 CRClient *pClient = cr_server.clients[i];
813 CRClient client;
814 unsigned long ctxID=-1, winID=-1;
815
816 rc = SSMR3GetU32(pSSM, &ui);
817 AssertRCReturn(rc, rc);
818 /* If this assert fires, then we should search correct client in the list first*/
819 CRASSERT(ui == pClient->conn->u32ClientID);
820
821 rc = SSMR3GetMem(pSSM, &client, sizeof(client));
822 CRASSERT(rc == VINF_SUCCESS);
823
824 client.conn = pClient->conn;
825 /* We can't reassign client number, as we'd get wrong results in TranslateTextureID
826 * and fail to bind old textures.
827 */
828 /*client.number = pClient->number;*/
829 *pClient = client;
830
831 pClient->currentContextNumber = -1;
832 pClient->currentCtx = cr_server.DummyContext;
833 pClient->currentMural = NULL;
834 pClient->currentWindow = -1;
835
836 cr_server.curClient = pClient;
837
838 if (client.currentCtx && client.currentContextNumber>=0)
839 {
840 rc = SSMR3GetMem(pSSM, &ctxID, sizeof(ctxID));
841 AssertRCReturn(rc, rc);
842 client.currentCtx = (CRContext*) crHashtableSearch(cr_server.contextTable, ctxID);
843 CRASSERT(client.currentCtx);
844 //pClient->currentCtx = client.currentCtx;
845 //pClient->currentContextNumber = ctxID;
846 }
847
848 if (client.currentMural && client.currentWindow>=0)
849 {
850 rc = SSMR3GetMem(pSSM, &winID, sizeof(winID));
851 AssertRCReturn(rc, rc);
852 client.currentMural = (CRMuralInfo*) crHashtableSearch(cr_server.muralTable, winID);
853 CRASSERT(client.currentMural);
854 //pClient->currentMural = client.currentMural;
855 //pClient->currentWindow = winID;
856 }
857
858 /* Restore client active context and window */
859 crServerDispatchMakeCurrent(winID, 0, ctxID);
860
861 if (0)
862 {
863 CRContext *tmpCtx;
864 CRCreateInfo_t *createInfo;
865 GLfloat one[4] = { 1, 1, 1, 1 };
866 GLfloat amb[4] = { 0.4f, 0.4f, 0.4f, 1.0f };
867
868 crServerDispatchMakeCurrent(winID, 0, ctxID);
869
870 crHashtableWalk(client.currentCtx->shared->textureTable, crVBoxServerSyncTextureCB, client.currentCtx);
871
872 crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.base1D, GL_TRUE);
873 crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.base2D, GL_TRUE);
874 crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.base3D, GL_TRUE);
875#ifdef CR_ARB_texture_cube_map
876 crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.baseCubeMap, GL_TRUE);
877#endif
878#ifdef CR_NV_texture_rectangle
879 //@todo this doesn't work as expected
880 //crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.baseRect, GL_TRUE);
881#endif
882 /*cr_server.head_spu->dispatch_table.Materialfv(GL_FRONT_AND_BACK, GL_AMBIENT, amb);
883 cr_server.head_spu->dispatch_table.LightModelfv(GL_LIGHT_MODEL_AMBIENT, amb);
884 cr_server.head_spu->dispatch_table.Lightfv(GL_LIGHT1, GL_DIFFUSE, one);
885
886 cr_server.head_spu->dispatch_table.Enable(GL_LIGHTING);
887 cr_server.head_spu->dispatch_table.Enable(GL_LIGHT0);
888 cr_server.head_spu->dispatch_table.Enable(GL_LIGHT1);
889
890 cr_server.head_spu->dispatch_table.Enable(GL_CULL_FACE);
891 cr_server.head_spu->dispatch_table.Enable(GL_TEXTURE_2D);*/
892
893 //crStateViewport( 0, 0, 600, 600 );
894 //pClient->currentMural->viewportValidated = GL_FALSE;
895 //cr_server.head_spu->dispatch_table.Viewport( 0, 0, 600, 600 );
896
897 //crStateMatrixMode(GL_PROJECTION);
898 //cr_server.head_spu->dispatch_table.MatrixMode(GL_PROJECTION);
899
900 //crStateLoadIdentity();
901 //cr_server.head_spu->dispatch_table.LoadIdentity();
902
903 //crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
904 //cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
905
906 //crStateMatrixMode(GL_MODELVIEW);
907 //cr_server.head_spu->dispatch_table.MatrixMode(GL_MODELVIEW);
908 //crServerDispatchLoadIdentity();
909 //crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
910 //cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
911 //crServerDispatchLoadIdentity();
912
913 /*createInfo = (CRCreateInfo_t *) crHashtableSearch(cr_server.pContextCreateInfoTable, ctxID);
914 CRASSERT(createInfo);
915 tmpCtx = crStateCreateContext(NULL, createInfo->visualBits, NULL);
916 CRASSERT(tmpCtx);
917 crStateDiffContext(tmpCtx, client.currentCtx);
918 crStateDestroyContext(tmpCtx);*/
919 }
920 }
921 }
922
923 //crServerDispatchMakeCurrent(-1, 0, -1);
924
925 cr_server.curClient = NULL;
926
927 {
928 GLenum err = crServerDispatchGetError();
929
930 if (err != GL_NO_ERROR)
931 {
932 crWarning("crServer: glGetError %d after loading snapshot", err);
933 }
934 }
935
936 cr_server.bIsInLoadingState = GL_FALSE;
937
938 return VINF_SUCCESS;
939}
940
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