VirtualBox

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

Last change on this file since 16420 was 15707, checked in by vboxsync, 16 years ago

crOpenGL: make host buffer dynamic in size, fix for 3443

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 27.1 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 <signal.h>
17#include <stdlib.h>
18#define DEBUG_FP_EXCEPTIONS 0
19#if DEBUG_FP_EXCEPTIONS
20#include <fpu_control.h>
21#include <math.h>
22#endif
23#include <iprt/assert.h>
24
25/**
26 * \mainpage CrServerLib
27 *
28 * \section CrServerLibIntroduction Introduction
29 *
30 * Chromium consists of all the top-level files in the cr
31 * directory. The core module basically takes care of API dispatch,
32 * and OpenGL state management.
33 */
34
35
36/**
37 * CRServer global data
38 */
39CRServer cr_server;
40
41int tearingdown = 0; /* can't be static */
42
43
44/**
45 * Return pointer to server's first SPU.
46 */
47SPU*
48crServerHeadSPU(void)
49{
50 return cr_server.head_spu;
51}
52
53
54
55static void DeleteBarrierCallback( void *data )
56{
57 CRServerBarrier *barrier = (CRServerBarrier *) data;
58 crFree(barrier->waiting);
59 crFree(barrier);
60}
61
62
63static void deleteContextCallback( void *data )
64{
65 CRContext *c = (CRContext *) data;
66 crStateDestroyContext(c);
67}
68
69
70static void crServerTearDown( void )
71{
72 GLint i;
73
74 /* avoid a race condition */
75 if (tearingdown)
76 return;
77
78 tearingdown = 1;
79
80 crStateSetCurrent( NULL );
81
82 cr_server.curClient = NULL;
83 cr_server.run_queue = NULL;
84
85 crFree( cr_server.overlap_intens );
86 cr_server.overlap_intens = NULL;
87
88 /* Deallocate all semaphores */
89 crFreeHashtable(cr_server.semaphores, crFree);
90 cr_server.semaphores = NULL;
91
92 /* Deallocate all barriers */
93 crFreeHashtable(cr_server.barriers, DeleteBarrierCallback);
94 cr_server.barriers = NULL;
95
96 /* Free all context info */
97 crFreeHashtable(cr_server.contextTable, deleteContextCallback);
98
99 /* Free context/window creation info */
100 crFreeHashtable(cr_server.pContextCreateInfoTable, crServerCreateInfoDeleteCB);
101 crFreeHashtable(cr_server.pWindowCreateInfoTable, crServerCreateInfoDeleteCB);
102
103 /* Free vertex programs */
104 crFreeHashtable(cr_server.programTable, crFree);
105
106 for (i = 0; i < cr_server.numClients; i++) {
107 if (cr_server.clients[i]) {
108 CRConnection *conn = cr_server.clients[i]->conn;
109 crNetFreeConnection(conn);
110 crFree(cr_server.clients[i]);
111 }
112 }
113 cr_server.numClients = 0;
114
115#if 1
116 /* disable these two lines if trying to get stack traces with valgrind */
117 crSPUUnloadChain(cr_server.head_spu);
118 cr_server.head_spu = NULL;
119#endif
120
121 crUnloadOpenGL();
122}
123
124static void crServerClose( unsigned int id )
125{
126 crError( "Client disconnected!" );
127 (void) id;
128}
129
130static void crServerCleanup( int sigio )
131{
132 crServerTearDown();
133
134 tearingdown = 0;
135}
136
137
138void
139crServerSetPort(int port)
140{
141 cr_server.tcpip_port = port;
142}
143
144
145
146static void
147crPrintHelp(void)
148{
149 printf("Usage: crserver [OPTIONS]\n");
150 printf("Options:\n");
151 printf(" -mothership URL Specifies URL for contacting the mothership.\n");
152 printf(" URL is of the form [protocol://]hostname[:port]\n");
153 printf(" -port N Specifies the port number this server will listen to.\n");
154 printf(" -help Prints this information.\n");
155}
156
157
158/**
159 * Do CRServer initializations. After this, we can begin servicing clients.
160 */
161void
162crServerInit(int argc, char *argv[])
163{
164 int i;
165 char *mothership = NULL;
166 CRMuralInfo *defaultMural;
167
168 for (i = 1 ; i < argc ; i++)
169 {
170 if (!crStrcmp( argv[i], "-mothership" ))
171 {
172 if (i == argc - 1)
173 {
174 crError( "-mothership requires an argument" );
175 }
176 mothership = argv[i+1];
177 i++;
178 }
179 else if (!crStrcmp( argv[i], "-port" ))
180 {
181 /* This is the port on which we'll accept client connections */
182 if (i == argc - 1)
183 {
184 crError( "-port requires an argument" );
185 }
186 cr_server.tcpip_port = crStrToInt(argv[i+1]);
187 i++;
188 }
189 else if (!crStrcmp( argv[i], "-vncmode" ))
190 {
191 cr_server.vncMode = 1;
192 }
193 else if (!crStrcmp( argv[i], "-help" ))
194 {
195 crPrintHelp();
196 exit(0);
197 }
198 }
199
200 signal( SIGTERM, crServerCleanup );
201 signal( SIGINT, crServerCleanup );
202#ifndef WINDOWS
203 signal( SIGPIPE, SIG_IGN );
204#endif
205
206#if DEBUG_FP_EXCEPTIONS
207 {
208 fpu_control_t mask;
209 _FPU_GETCW(mask);
210 mask &= ~(_FPU_MASK_IM | _FPU_MASK_DM | _FPU_MASK_ZM
211 | _FPU_MASK_OM | _FPU_MASK_UM);
212 _FPU_SETCW(mask);
213 }
214#endif
215
216 cr_server.firstCallCreateContext = GL_TRUE;
217 cr_server.firstCallMakeCurrent = GL_TRUE;
218
219 /*
220 * Create default mural info and hash table.
221 */
222 cr_server.muralTable = crAllocHashtable();
223 defaultMural = (CRMuralInfo *) crCalloc(sizeof(CRMuralInfo));
224 crHashtableAdd(cr_server.muralTable, 0, defaultMural);
225
226 cr_server.programTable = crAllocHashtable();
227
228 crNetInit(crServerRecv, crServerClose);
229 crStateInit();
230
231 crServerSetVBoxConfiguration();
232
233 crStateLimitsInit( &(cr_server.limits) );
234
235 /*
236 * Default context
237 */
238 cr_server.contextTable = crAllocHashtable();
239 cr_server.DummyContext = crStateCreateContext( &cr_server.limits,
240 CR_RGB_BIT | CR_DEPTH_BIT, NULL );
241 cr_server.curClient->currentCtx = cr_server.DummyContext;
242
243 crServerInitDispatch();
244 crStateDiffAPI( &(cr_server.head_spu->dispatch_table) );
245
246 crUnpackSetReturnPointer( &(cr_server.return_ptr) );
247 crUnpackSetWritebackPointer( &(cr_server.writeback_ptr) );
248
249 cr_server.barriers = crAllocHashtable();
250 cr_server.semaphores = crAllocHashtable();
251}
252
253void crVBoxServerTearDown(void)
254{
255 crServerTearDown();
256}
257
258/**
259 * Do CRServer initializations. After this, we can begin servicing clients.
260 */
261GLboolean crVBoxServerInit(void)
262{
263 CRMuralInfo *defaultMural;
264
265#if DEBUG_FP_EXCEPTIONS
266 {
267 fpu_control_t mask;
268 _FPU_GETCW(mask);
269 mask &= ~(_FPU_MASK_IM | _FPU_MASK_DM | _FPU_MASK_ZM
270 | _FPU_MASK_OM | _FPU_MASK_UM);
271 _FPU_SETCW(mask);
272 }
273#endif
274
275 crNetInit(crServerRecv, crServerClose);
276
277 cr_server.firstCallCreateContext = GL_TRUE;
278 cr_server.firstCallMakeCurrent = GL_TRUE;
279
280 cr_server.bIsInLoadingState = GL_FALSE;
281 cr_server.bIsInSavingState = GL_FALSE;
282
283 /*
284 * Create default mural info and hash table.
285 */
286 cr_server.muralTable = crAllocHashtable();
287 defaultMural = (CRMuralInfo *) crCalloc(sizeof(CRMuralInfo));
288 crHashtableAdd(cr_server.muralTable, 0, defaultMural);
289
290 cr_server.programTable = crAllocHashtable();
291
292 crStateInit();
293
294 crStateLimitsInit( &(cr_server.limits) );
295
296 cr_server.barriers = crAllocHashtable();
297 cr_server.semaphores = crAllocHashtable();
298
299 crUnpackSetReturnPointer( &(cr_server.return_ptr) );
300 crUnpackSetWritebackPointer( &(cr_server.writeback_ptr) );
301
302 /*
303 * Default context
304 */
305 cr_server.contextTable = crAllocHashtable();
306 cr_server.DummyContext = crStateCreateContext( &cr_server.limits,
307 CR_RGB_BIT | CR_DEPTH_BIT, NULL );
308 cr_server.pContextCreateInfoTable = crAllocHashtable();
309 cr_server.pWindowCreateInfoTable = crAllocHashtable();
310
311 crServerSetVBoxConfigurationHGCM();
312
313 if (!cr_server.head_spu)
314 return GL_FALSE;
315
316 crServerInitDispatch();
317 crStateDiffAPI( &(cr_server.head_spu->dispatch_table) );
318
319 return GL_TRUE;
320}
321
322void crVBoxServerAddClient(uint32_t u32ClientID)
323{
324 CRClient *newClient = (CRClient *) crCalloc(sizeof(CRClient));
325
326 crDebug("crServer: AddClient u32ClientID=%d", u32ClientID);
327
328 newClient->spu_id = 0;
329 newClient->currentCtx = cr_server.DummyContext;
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 crServerServiceClients();
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 rc = crStateSaveContext(pContext, pSSM);
560 CRASSERT(rc == VINF_SUCCESS);
561}
562
563static uint32_t g_hackVBoxServerSaveLoadCallsLeft = 0;
564
565DECLEXPORT(int32_t) crVBoxServerSaveState(PSSMHANDLE pSSM)
566{
567 int32_t rc, i;
568 uint32_t ui32;
569 GLboolean b;
570 unsigned long key;
571
572 /* We shouldn't be called if there's no clients at all*/
573 CRASSERT(cr_server.numClients>0);
574
575 /* @todo it's hack atm */
576 /* We want to be called only once to save server state but atm we're being called from svcSaveState
577 * for every connected client (e.g. guest opengl application)
578 */
579 if (!cr_server.bIsInSavingState) /* It's first call */
580 {
581 cr_server.bIsInSavingState = GL_TRUE;
582
583 /* Store number of clients */
584 rc = SSMR3PutU32(pSSM, (uint32_t) cr_server.numClients);
585 AssertRCReturn(rc, rc);
586
587 g_hackVBoxServerSaveLoadCallsLeft = cr_server.numClients;
588 }
589
590 g_hackVBoxServerSaveLoadCallsLeft--;
591
592 /* Do nothing untill we're being called last time */
593 if (g_hackVBoxServerSaveLoadCallsLeft>0)
594 {
595 return VINF_SUCCESS;
596 }
597
598 /* Save rendering contexts creation info */
599 ui32 = crHashtableNumElements(cr_server.pContextCreateInfoTable);
600 rc = SSMR3PutU32(pSSM, (uint32_t) ui32);
601 AssertRCReturn(rc, rc);
602 crHashtableWalk(cr_server.pContextCreateInfoTable, crVBoxServerSaveCreateInfoCB, pSSM);
603
604 /* Save contexts state tracker data */
605 /* @todo For now just some blind data dumps,
606 * but I've a feeling those should be saved/restored in a very strict sequence to
607 * allow diff_api to work correctly.
608 * Should be tested more with multiply guest opengl apps working when saving VM snapshot.
609 */
610 crHashtableWalk(cr_server.contextTable, crVBoxServerSaveContextStateCB, pSSM);
611
612 /* Save windows creation info */
613 ui32 = crHashtableNumElements(cr_server.pWindowCreateInfoTable);
614 rc = SSMR3PutU32(pSSM, (uint32_t) ui32);
615 AssertRCReturn(rc, rc);
616 crHashtableWalk(cr_server.pWindowCreateInfoTable, crVBoxServerSaveCreateInfoCB, pSSM);
617
618 /* Save cr_server.muralTable
619 * @todo we don't need it all, just geometry info actually
620 * @todo store visible regions as well
621 */
622 ui32 = crHashtableNumElements(cr_server.muralTable);
623 /* There should be default mural always */
624 CRASSERT(ui32>=1);
625 rc = SSMR3PutU32(pSSM, (uint32_t) ui32-1);
626 AssertRCReturn(rc, rc);
627 crHashtableWalk(cr_server.muralTable, crVBoxServerSaveMuralCB, pSSM);
628
629 /* Save starting free context and window IDs */
630 rc = SSMR3PutMem(pSSM, &cr_server.idsPool, sizeof(cr_server.idsPool));
631 AssertRCReturn(rc, rc);
632
633 /* Save clients info */
634 for (i = 0; i < cr_server.numClients; i++)
635 {
636 if (cr_server.clients[i] && cr_server.clients[i]->conn)
637 {
638 CRClient *pClient = cr_server.clients[i];
639
640 rc = SSMR3PutU32(pSSM, pClient->conn->u32ClientID);
641 AssertRCReturn(rc, rc);
642
643 rc = SSMR3PutMem(pSSM, pClient, sizeof(*pClient));
644 AssertRCReturn(rc, rc);
645
646 if (pClient->currentCtx && pClient->currentContextNumber>=0)
647 {
648 b = crHashtableGetDataKey(cr_server.contextTable, pClient->currentCtx, &key);
649 CRASSERT(b);
650 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
651 AssertRCReturn(rc, rc);
652 }
653
654 if (pClient->currentMural && pClient->currentWindow>=0)
655 {
656 b = crHashtableGetDataKey(cr_server.muralTable, pClient->currentMural, &key);
657 CRASSERT(b);
658 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
659 AssertRCReturn(rc, rc);
660 }
661 }
662 }
663
664 cr_server.bIsInSavingState = GL_FALSE;
665
666 return VINF_SUCCESS;
667}
668
669DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM)
670{
671 int32_t rc, i;
672 uint32_t ui, uiNumElems;
673 unsigned long key;
674
675 if (!cr_server.bIsInLoadingState)
676 {
677 /* AssertRCReturn(...) will leave us in loading state, but it doesn't matter as we'd be failing anyway */
678 cr_server.bIsInLoadingState = GL_TRUE;
679
680 /* Read number of clients */
681 rc = SSMR3GetU32(pSSM, &g_hackVBoxServerSaveLoadCallsLeft);
682 AssertRCReturn(rc, rc);
683 }
684
685 g_hackVBoxServerSaveLoadCallsLeft--;
686
687 /* Do nothing untill we're being called last time */
688 if (g_hackVBoxServerSaveLoadCallsLeft>0)
689 {
690 return VINF_SUCCESS;
691 }
692
693 /* Load and recreate rendering contexts */
694 rc = SSMR3GetU32(pSSM, &uiNumElems);
695 AssertRCReturn(rc, rc);
696 for (ui=0; ui<uiNumElems; ++ui)
697 {
698 CRCreateInfo_t createInfo;
699 char psz[200];
700 GLint ctxID;
701
702 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
703 AssertRCReturn(rc, rc);
704 rc = SSMR3GetMem(pSSM, &createInfo, sizeof(createInfo));
705 AssertRCReturn(rc, rc);
706
707 if (createInfo.pszDpyName)
708 {
709 rc = SSMR3GetStrZEx(pSSM, psz, 200, NULL);
710 AssertRCReturn(rc, rc);
711 createInfo.pszDpyName = psz;
712 }
713
714 ctxID = crServerDispatchCreateContextEx(createInfo.pszDpyName, createInfo.visualBits, 0, key, createInfo.internalID);
715 CRASSERT((int64_t)ctxID == (int64_t)key);
716 }
717
718 /* Restore context state data */
719 for (ui=0; ui<uiNumElems; ++ui)
720 {
721 CRContext *pContext;
722
723 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
724 AssertRCReturn(rc, rc);
725
726 pContext = (CRContext*) crHashtableSearch(cr_server.contextTable, key);
727 CRASSERT(pContext);
728
729 rc = crStateLoadContext(pContext, pSSM);
730 AssertRCReturn(rc, rc);
731 }
732
733 /* Load windows */
734 rc = SSMR3GetU32(pSSM, &uiNumElems);
735 AssertRCReturn(rc, rc);
736 for (ui=0; ui<uiNumElems; ++ui)
737 {
738 CRCreateInfo_t createInfo;
739 char psz[200];
740 GLint winID;
741 unsigned long key;
742
743 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
744 AssertRCReturn(rc, rc);
745 rc = SSMR3GetMem(pSSM, &createInfo, sizeof(createInfo));
746 AssertRCReturn(rc, rc);
747
748 if (createInfo.pszDpyName)
749 {
750 rc = SSMR3GetStrZEx(pSSM, psz, 200, NULL);
751 AssertRCReturn(rc, rc);
752 createInfo.pszDpyName = psz;
753 }
754
755 winID = crServerDispatchWindowCreateEx(createInfo.pszDpyName, createInfo.visualBits, key);
756 CRASSERT((int64_t)winID == (int64_t)key);
757 }
758
759 /* Load cr_server.muralTable */
760 rc = SSMR3GetU32(pSSM, &uiNumElems);
761 AssertRCReturn(rc, rc);
762 for (ui=0; ui<uiNumElems; ++ui)
763 {
764 CRMuralInfo muralInfo;
765
766 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
767 AssertRCReturn(rc, rc);
768 rc = SSMR3GetMem(pSSM, &muralInfo, sizeof(muralInfo));
769 AssertRCReturn(rc, rc);
770
771 /* Restore windows geometry info */
772 crServerDispatchWindowSize(key, muralInfo.underlyingDisplay[2], muralInfo.underlyingDisplay[3]);
773 crServerDispatchWindowPosition(key, muralInfo.underlyingDisplay[0], muralInfo.underlyingDisplay[1]);
774 }
775
776 /* Load starting free context and window IDs */
777 rc = SSMR3GetMem(pSSM, &cr_server.idsPool, sizeof(cr_server.idsPool));
778 CRASSERT(rc == VINF_SUCCESS);
779
780 /* Load clients info */
781 for (i = 0; i < cr_server.numClients; i++)
782 {
783 if (cr_server.clients[i] && cr_server.clients[i]->conn)
784 {
785 CRClient *pClient = cr_server.clients[i];
786 CRClient client;
787 unsigned long ctxID=-1, winID=-1;
788
789 rc = SSMR3GetU32(pSSM, &ui);
790 AssertRCReturn(rc, rc);
791 /* If this assert fires, then we should search correct client in the list first*/
792 CRASSERT(ui == pClient->conn->u32ClientID);
793
794 rc = SSMR3GetMem(pSSM, &client, sizeof(client));
795 CRASSERT(rc == VINF_SUCCESS);
796
797 client.conn = pClient->conn;
798 /* We can't reassign client number, as we'd get wrong results in TranslateTextureID
799 * and fail to bind old textures.
800 */
801 /*client.number = pClient->number;*/
802 *pClient = client;
803
804 pClient->currentContextNumber = -1;
805 pClient->currentCtx = cr_server.DummyContext;
806 pClient->currentMural = NULL;
807 pClient->currentWindow = -1;
808
809 cr_server.curClient = pClient;
810
811 if (client.currentCtx && client.currentContextNumber>=0)
812 {
813 rc = SSMR3GetMem(pSSM, &ctxID, sizeof(ctxID));
814 AssertRCReturn(rc, rc);
815 client.currentCtx = (CRContext*) crHashtableSearch(cr_server.contextTable, ctxID);
816 CRASSERT(client.currentCtx);
817 //pClient->currentCtx = client.currentCtx;
818 //pClient->currentContextNumber = ctxID;
819 }
820
821 if (client.currentMural && client.currentWindow>=0)
822 {
823 rc = SSMR3GetMem(pSSM, &winID, sizeof(winID));
824 AssertRCReturn(rc, rc);
825 client.currentMural = (CRMuralInfo*) crHashtableSearch(cr_server.muralTable, winID);
826 CRASSERT(client.currentMural);
827 //pClient->currentMural = client.currentMural;
828 //pClient->currentWindow = winID;
829 }
830
831 /* Restore client active context and window */
832 crServerDispatchMakeCurrent(winID, 0, ctxID);
833
834 if (0)
835 {
836 CRContext *tmpCtx;
837 CRCreateInfo_t *createInfo;
838 GLfloat one[4] = { 1, 1, 1, 1 };
839 GLfloat amb[4] = { 0.4f, 0.4f, 0.4f, 1.0f };
840
841 crServerDispatchMakeCurrent(winID, 0, ctxID);
842
843 crHashtableWalk(client.currentCtx->shared->textureTable, crVBoxServerSyncTextureCB, client.currentCtx);
844
845 crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.base1D, GL_TRUE);
846 crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.base2D, GL_TRUE);
847 crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.base3D, GL_TRUE);
848#ifdef CR_ARB_texture_cube_map
849 crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.baseCubeMap, GL_TRUE);
850#endif
851#ifdef CR_NV_texture_rectangle
852 //@todo this doesn't work as expected
853 //crStateTextureObjectDiff(client.currentCtx, NULL, NULL, &client.currentCtx->texture.baseRect, GL_TRUE);
854#endif
855 /*cr_server.head_spu->dispatch_table.Materialfv(GL_FRONT_AND_BACK, GL_AMBIENT, amb);
856 cr_server.head_spu->dispatch_table.LightModelfv(GL_LIGHT_MODEL_AMBIENT, amb);
857 cr_server.head_spu->dispatch_table.Lightfv(GL_LIGHT1, GL_DIFFUSE, one);
858
859 cr_server.head_spu->dispatch_table.Enable(GL_LIGHTING);
860 cr_server.head_spu->dispatch_table.Enable(GL_LIGHT0);
861 cr_server.head_spu->dispatch_table.Enable(GL_LIGHT1);
862
863 cr_server.head_spu->dispatch_table.Enable(GL_CULL_FACE);
864 cr_server.head_spu->dispatch_table.Enable(GL_TEXTURE_2D);*/
865
866 //crStateViewport( 0, 0, 600, 600 );
867 //pClient->currentMural->viewportValidated = GL_FALSE;
868 //cr_server.head_spu->dispatch_table.Viewport( 0, 0, 600, 600 );
869
870 //crStateMatrixMode(GL_PROJECTION);
871 //cr_server.head_spu->dispatch_table.MatrixMode(GL_PROJECTION);
872
873 //crStateLoadIdentity();
874 //cr_server.head_spu->dispatch_table.LoadIdentity();
875
876 //crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
877 //cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
878
879 //crStateMatrixMode(GL_MODELVIEW);
880 //cr_server.head_spu->dispatch_table.MatrixMode(GL_MODELVIEW);
881 //crServerDispatchLoadIdentity();
882 //crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
883 //cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
884 //crServerDispatchLoadIdentity();
885
886 /*createInfo = (CRCreateInfo_t *) crHashtableSearch(cr_server.pContextCreateInfoTable, ctxID);
887 CRASSERT(createInfo);
888 tmpCtx = crStateCreateContext(NULL, createInfo->visualBits, NULL);
889 CRASSERT(tmpCtx);
890 crStateDiffContext(tmpCtx, client.currentCtx);
891 crStateDestroyContext(tmpCtx);*/
892 }
893 }
894 }
895
896 //crServerDispatchMakeCurrent(-1, 0, -1);
897
898 cr_server.curClient = NULL;
899
900 {
901 GLenum err = crServerDispatchGetError();
902
903 if (err != GL_NO_ERROR)
904 {
905 crWarning("crServer: glGetError %d after loading snapshot", err);
906 }
907 }
908
909 cr_server.bIsInLoadingState = GL_FALSE;
910
911 return VINF_SUCCESS;
912}
913
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