VirtualBox

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

最後變更 在這個檔案從18262是 18262,由 vboxsync 提交於 16 年 前

crOpenGL: fix snapshots saving for opengl apps which doesn't make any opengl contexts (bug #3758)

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette