VirtualBox

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

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

crOpenGL: glGetError fixes

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Id
檔案大小: 58.8 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 "cr_environment.h"
16#include "server_dispatch.h"
17#include "state/cr_texture.h"
18#include "render/renderspu.h"
19#include <signal.h>
20#include <stdlib.h>
21#define DEBUG_FP_EXCEPTIONS 0
22#if DEBUG_FP_EXCEPTIONS
23#include <fpu_control.h>
24#include <math.h>
25#endif
26#include <iprt/assert.h>
27#include <VBox/err.h>
28
29#ifdef VBOXCR_LOGFPS
30#include <iprt/timer.h>
31#endif
32
33#ifdef VBOX_WITH_CRHGSMI
34# include <VBox/HostServices/VBoxCrOpenGLSvc.h>
35uint8_t* g_pvVRamBase = NULL;
36uint32_t g_cbVRam = 0;
37HCRHGSMICMDCOMPLETION g_hCrHgsmiCompletion = NULL;
38PFNCRHGSMICMDCOMPLETION g_pfnCrHgsmiCompletion = NULL;
39#endif
40
41/**
42 * \mainpage CrServerLib
43 *
44 * \section CrServerLibIntroduction Introduction
45 *
46 * Chromium consists of all the top-level files in the cr
47 * directory. The core module basically takes care of API dispatch,
48 * and OpenGL state management.
49 */
50
51
52/**
53 * CRServer global data
54 */
55CRServer cr_server;
56
57int tearingdown = 0; /* can't be static */
58
59DECLINLINE(int32_t) crVBoxServerClientGet(uint32_t u32ClientID, CRClient **ppClient)
60{
61 CRClient *pClient = NULL;
62 int32_t i;
63
64 *ppClient = NULL;
65
66 for (i = 0; i < cr_server.numClients; i++)
67 {
68 if (cr_server.clients[i] && cr_server.clients[i]->conn
69 && cr_server.clients[i]->conn->u32ClientID==u32ClientID)
70 {
71 pClient = cr_server.clients[i];
72 break;
73 }
74 }
75 if (!pClient)
76 {
77 crWarning("client not found!");
78 return VERR_INVALID_PARAMETER;
79 }
80
81 if (!pClient->conn->vMajor)
82 {
83 crWarning("no major version specified for client!");
84 return VERR_NOT_SUPPORTED;
85 }
86
87 *ppClient = pClient;
88
89 return VINF_SUCCESS;
90}
91
92
93/**
94 * Return pointer to server's first SPU.
95 */
96SPU*
97crServerHeadSPU(void)
98{
99 return cr_server.head_spu;
100}
101
102
103
104static void DeleteBarrierCallback( void *data )
105{
106 CRServerBarrier *barrier = (CRServerBarrier *) data;
107 crFree(barrier->waiting);
108 crFree(barrier);
109}
110
111
112static void deleteContextInfoCallback( void *data )
113{
114 CRContextInfo *c = (CRContextInfo *) data;
115 crStateDestroyContext(c->pContext);
116 if (c->CreateInfo.pszDpyName)
117 crFree(c->CreateInfo.pszDpyName);
118 crFree(c);
119}
120
121
122static void crServerTearDown( void )
123{
124 GLint i;
125 CRClientNode *pNode, *pNext;
126
127 /* avoid a race condition */
128 if (tearingdown)
129 return;
130
131 tearingdown = 1;
132
133 crStateSetCurrent( NULL );
134
135 cr_server.curClient = NULL;
136 cr_server.run_queue = NULL;
137
138 crFree( cr_server.overlap_intens );
139 cr_server.overlap_intens = NULL;
140
141 /* Deallocate all semaphores */
142 crFreeHashtable(cr_server.semaphores, crFree);
143 cr_server.semaphores = NULL;
144
145 /* Deallocate all barriers */
146 crFreeHashtable(cr_server.barriers, DeleteBarrierCallback);
147 cr_server.barriers = NULL;
148
149 /* Free all context info */
150 crFreeHashtable(cr_server.contextTable, deleteContextInfoCallback);
151
152 /* Free vertex programs */
153 crFreeHashtable(cr_server.programTable, crFree);
154
155 for (i = 0; i < cr_server.numClients; i++) {
156 if (cr_server.clients[i]) {
157 CRConnection *conn = cr_server.clients[i]->conn;
158 crNetFreeConnection(conn);
159 crFree(cr_server.clients[i]);
160 }
161 }
162 cr_server.numClients = 0;
163
164 pNode = cr_server.pCleanupClient;
165 while (pNode)
166 {
167 pNext=pNode->next;
168 crFree(pNode->pClient);
169 crFree(pNode);
170 pNode=pNext;
171 }
172 cr_server.pCleanupClient = NULL;
173
174#if 1
175 /* disable these two lines if trying to get stack traces with valgrind */
176 crSPUUnloadChain(cr_server.head_spu);
177 cr_server.head_spu = NULL;
178#endif
179
180 crStateDestroy();
181
182 crNetTearDown();
183}
184
185static void crServerClose( unsigned int id )
186{
187 crError( "Client disconnected!" );
188 (void) id;
189}
190
191static void crServerCleanup( int sigio )
192{
193 crServerTearDown();
194
195 tearingdown = 0;
196}
197
198
199void
200crServerSetPort(int port)
201{
202 cr_server.tcpip_port = port;
203}
204
205
206
207static void
208crPrintHelp(void)
209{
210 printf("Usage: crserver [OPTIONS]\n");
211 printf("Options:\n");
212 printf(" -mothership URL Specifies URL for contacting the mothership.\n");
213 printf(" URL is of the form [protocol://]hostname[:port]\n");
214 printf(" -port N Specifies the port number this server will listen to.\n");
215 printf(" -help Prints this information.\n");
216}
217
218
219/**
220 * Do CRServer initializations. After this, we can begin servicing clients.
221 */
222void
223crServerInit(int argc, char *argv[])
224{
225 int i;
226 char *mothership = NULL;
227 CRMuralInfo *defaultMural;
228
229 for (i = 1 ; i < argc ; i++)
230 {
231 if (!crStrcmp( argv[i], "-mothership" ))
232 {
233 if (i == argc - 1)
234 {
235 crError( "-mothership requires an argument" );
236 }
237 mothership = argv[i+1];
238 i++;
239 }
240 else if (!crStrcmp( argv[i], "-port" ))
241 {
242 /* This is the port on which we'll accept client connections */
243 if (i == argc - 1)
244 {
245 crError( "-port requires an argument" );
246 }
247 cr_server.tcpip_port = crStrToInt(argv[i+1]);
248 i++;
249 }
250 else if (!crStrcmp( argv[i], "-vncmode" ))
251 {
252 cr_server.vncMode = 1;
253 }
254 else if (!crStrcmp( argv[i], "-help" ))
255 {
256 crPrintHelp();
257 exit(0);
258 }
259 }
260
261 signal( SIGTERM, crServerCleanup );
262 signal( SIGINT, crServerCleanup );
263#ifndef WINDOWS
264 signal( SIGPIPE, SIG_IGN );
265#endif
266
267#if DEBUG_FP_EXCEPTIONS
268 {
269 fpu_control_t mask;
270 _FPU_GETCW(mask);
271 mask &= ~(_FPU_MASK_IM | _FPU_MASK_DM | _FPU_MASK_ZM
272 | _FPU_MASK_OM | _FPU_MASK_UM);
273 _FPU_SETCW(mask);
274 }
275#endif
276
277 cr_server.bUseMultipleContexts = (crGetenv( "CR_SERVER_ENABLE_MULTIPLE_CONTEXTS" ) != NULL);
278
279 if (cr_server.bUseMultipleContexts)
280 {
281 crInfo("Info: using multiple contexts!");
282 crDebug("Debug: using multiple contexts!");
283 }
284
285 cr_server.firstCallCreateContext = GL_TRUE;
286 cr_server.firstCallMakeCurrent = GL_TRUE;
287 cr_server.bForceMakeCurrentOnClientSwitch = GL_FALSE;
288
289 /*
290 * Create default mural info and hash table.
291 */
292 cr_server.muralTable = crAllocHashtable();
293 defaultMural = (CRMuralInfo *) crCalloc(sizeof(CRMuralInfo));
294 crHashtableAdd(cr_server.muralTable, 0, defaultMural);
295
296 cr_server.programTable = crAllocHashtable();
297
298 crNetInit(crServerRecv, crServerClose);
299 crStateInit();
300
301 crServerSetVBoxConfiguration();
302
303 crStateLimitsInit( &(cr_server.limits) );
304
305 /*
306 * Default context
307 */
308 cr_server.contextTable = crAllocHashtable();
309 cr_server.curClient->currentCtxInfo = &cr_server.MainContextInfo;
310
311 crServerInitDispatch();
312 crStateDiffAPI( &(cr_server.head_spu->dispatch_table) );
313
314 crUnpackSetReturnPointer( &(cr_server.return_ptr) );
315 crUnpackSetWritebackPointer( &(cr_server.writeback_ptr) );
316
317 cr_server.barriers = crAllocHashtable();
318 cr_server.semaphores = crAllocHashtable();
319}
320
321void crVBoxServerTearDown(void)
322{
323 crServerTearDown();
324}
325
326/**
327 * Do CRServer initializations. After this, we can begin servicing clients.
328 */
329GLboolean crVBoxServerInit(void)
330{
331 CRMuralInfo *defaultMural;
332
333#if DEBUG_FP_EXCEPTIONS
334 {
335 fpu_control_t mask;
336 _FPU_GETCW(mask);
337 mask &= ~(_FPU_MASK_IM | _FPU_MASK_DM | _FPU_MASK_ZM
338 | _FPU_MASK_OM | _FPU_MASK_UM);
339 _FPU_SETCW(mask);
340 }
341#endif
342
343 cr_server.bUseMultipleContexts = (crGetenv( "CR_SERVER_ENABLE_MULTIPLE_CONTEXTS" ) != NULL);
344
345 if (cr_server.bUseMultipleContexts)
346 {
347 crInfo("Info: using multiple contexts!");
348 crDebug("Debug: using multiple contexts!");
349 }
350
351 crNetInit(crServerRecv, crServerClose);
352
353 cr_server.firstCallCreateContext = GL_TRUE;
354 cr_server.firstCallMakeCurrent = GL_TRUE;
355
356 cr_server.bIsInLoadingState = GL_FALSE;
357 cr_server.bIsInSavingState = GL_FALSE;
358 cr_server.bForceMakeCurrentOnClientSwitch = GL_FALSE;
359
360 cr_server.pCleanupClient = NULL;
361
362 /*
363 * Create default mural info and hash table.
364 */
365 cr_server.muralTable = crAllocHashtable();
366 defaultMural = (CRMuralInfo *) crCalloc(sizeof(CRMuralInfo));
367 crHashtableAdd(cr_server.muralTable, 0, defaultMural);
368
369 cr_server.programTable = crAllocHashtable();
370
371 crStateInit();
372
373 crStateLimitsInit( &(cr_server.limits) );
374
375 cr_server.barriers = crAllocHashtable();
376 cr_server.semaphores = crAllocHashtable();
377
378 crUnpackSetReturnPointer( &(cr_server.return_ptr) );
379 crUnpackSetWritebackPointer( &(cr_server.writeback_ptr) );
380
381 /*
382 * Default context
383 */
384 cr_server.contextTable = crAllocHashtable();
385
386 crServerSetVBoxConfigurationHGCM();
387
388 if (!cr_server.head_spu)
389 return GL_FALSE;
390
391 crServerInitDispatch();
392 crStateDiffAPI( &(cr_server.head_spu->dispatch_table) );
393
394 /*Check for PBO support*/
395 if (crStateGetCurrent()->extensions.ARB_pixel_buffer_object)
396 {
397 cr_server.bUsePBOForReadback=GL_TRUE;
398 }
399
400 return GL_TRUE;
401}
402
403int32_t crVBoxServerAddClient(uint32_t u32ClientID)
404{
405 CRClient *newClient;
406
407 if (cr_server.numClients>=CR_MAX_CLIENTS)
408 {
409 return VERR_MAX_THRDS_REACHED;
410 }
411
412 newClient = (CRClient *) crCalloc(sizeof(CRClient));
413 crDebug("crServer: AddClient u32ClientID=%d", u32ClientID);
414
415 newClient->spu_id = 0;
416 newClient->currentCtxInfo = &cr_server.MainContextInfo;
417 newClient->currentContextNumber = -1;
418 newClient->conn = crNetAcceptClient(cr_server.protocol, NULL,
419 cr_server.tcpip_port,
420 cr_server.mtu, 0);
421 newClient->conn->u32ClientID = u32ClientID;
422
423 cr_server.clients[cr_server.numClients++] = newClient;
424
425 crServerAddToRunQueue(newClient);
426
427 return VINF_SUCCESS;
428}
429
430void crVBoxServerRemoveClient(uint32_t u32ClientID)
431{
432 CRClient *pClient=NULL;
433 int32_t i;
434
435 crDebug("crServer: RemoveClient u32ClientID=%d", u32ClientID);
436
437 for (i = 0; i < cr_server.numClients; i++)
438 {
439 if (cr_server.clients[i] && cr_server.clients[i]->conn
440 && cr_server.clients[i]->conn->u32ClientID==u32ClientID)
441 {
442 pClient = cr_server.clients[i];
443 break;
444 }
445 }
446 //if (!pClient) return VERR_INVALID_PARAMETER;
447 if (!pClient)
448 {
449 crWarning("Invalid client id %u passed to crVBoxServerRemoveClient", u32ClientID);
450 return;
451 }
452
453#ifdef VBOX_WITH_CRHGSMI
454 CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
455#endif
456
457 /* Disconnect the client */
458 pClient->conn->Disconnect(pClient->conn);
459
460 /* Let server clear client from the queue */
461 crServerDeleteClient(pClient);
462}
463
464static int32_t crVBoxServerInternalClientWriteRead(CRClient *pClient)
465{
466#ifdef VBOXCR_LOGFPS
467 uint64_t tstart, tend;
468#endif
469
470 /*crDebug("=>crServer: ClientWrite u32ClientID=%d", u32ClientID);*/
471
472
473#ifdef VBOXCR_LOGFPS
474 tstart = RTTimeNanoTS();
475#endif
476
477 /* This should be setup already */
478 CRASSERT(pClient->conn->pBuffer);
479 CRASSERT(pClient->conn->cbBuffer);
480#ifdef VBOX_WITH_CRHGSMI
481 CRVBOXHGSMI_CMDDATA_ASSERT_CONSISTENT(&pClient->conn->CmdData);
482#endif
483
484 if (
485#ifdef VBOX_WITH_CRHGSMI
486 !CRVBOXHGSMI_CMDDATA_IS_SET(&pClient->conn->CmdData) &&
487#endif
488 cr_server.run_queue->client != pClient
489 && crServerClientInBeginEnd(cr_server.run_queue->client))
490 {
491 crDebug("crServer: client %d blocked, allow_redir_ptr = 0", pClient->conn->u32ClientID);
492 pClient->conn->allow_redir_ptr = 0;
493 }
494 else
495 {
496 pClient->conn->allow_redir_ptr = 1;
497 }
498
499 crNetRecv();
500 CRASSERT(pClient->conn->pBuffer==NULL && pClient->conn->cbBuffer==0);
501 CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
502
503 crServerServiceClients();
504
505#if 0
506 if (pClient->currentMural) {
507 crStateViewport( 0, 0, 500, 500 );
508 pClient->currentMural->viewportValidated = GL_FALSE;
509 cr_server.head_spu->dispatch_table.Viewport( 0, 0, 500, 500 );
510 crStateViewport( 0, 0, 600, 600 );
511 pClient->currentMural->viewportValidated = GL_FALSE;
512 cr_server.head_spu->dispatch_table.Viewport( 0, 0, 600, 600 );
513
514 crStateMatrixMode(GL_PROJECTION);
515 cr_server.head_spu->dispatch_table.MatrixMode(GL_PROJECTION);
516 crServerDispatchLoadIdentity();
517 crStateFrustum(-0.6, 0.6, -0.5, 0.5, 1.5, 150.0);
518 cr_server.head_spu->dispatch_table.Frustum(-0.6, 0.6, -0.5, 0.5, 1.5, 150.0);
519 crServerDispatchLoadIdentity();
520 crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
521 cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
522
523 crStateMatrixMode(GL_MODELVIEW);
524 cr_server.head_spu->dispatch_table.MatrixMode(GL_MODELVIEW);
525 crServerDispatchLoadIdentity();
526 crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
527 cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
528 crServerDispatchLoadIdentity();
529 }
530#endif
531
532 crStateResetCurrentPointers(&cr_server.current);
533
534#ifndef VBOX_WITH_CRHGSMI
535 CRASSERT(!pClient->conn->allow_redir_ptr || crNetNumMessages(pClient->conn)==0);
536#endif
537
538#ifdef VBOXCR_LOGFPS
539 tend = RTTimeNanoTS();
540 pClient->timeUsed += tend-tstart;
541#endif
542 /*crDebug("<=crServer: ClientWrite u32ClientID=%d", u32ClientID);*/
543
544 return VINF_SUCCESS;
545}
546
547
548int32_t crVBoxServerClientWrite(uint32_t u32ClientID, uint8_t *pBuffer, uint32_t cbBuffer)
549{
550 CRClient *pClient=NULL;
551 int32_t rc = crVBoxServerClientGet(u32ClientID, &pClient);
552
553 if (RT_FAILURE(rc))
554 return rc;
555
556
557 CRASSERT(pBuffer);
558
559 /* This should never fire unless we start to multithread */
560 CRASSERT(pClient->conn->pBuffer==NULL && pClient->conn->cbBuffer==0);
561
562 pClient->conn->pBuffer = pBuffer;
563 pClient->conn->cbBuffer = cbBuffer;
564#ifdef VBOX_WITH_CRHGSMI
565 CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
566#endif
567
568 return crVBoxServerInternalClientWriteRead(pClient);
569}
570
571int32_t crVBoxServerInternalClientRead(CRClient *pClient, uint8_t *pBuffer, uint32_t *pcbBuffer)
572{
573 if (pClient->conn->cbHostBuffer > *pcbBuffer)
574 {
575 crDebug("crServer: [%lx] ClientRead u32ClientID=%d FAIL, host buffer too small %d of %d",
576 crThreadID(), pClient->conn->u32ClientID, *pcbBuffer, pClient->conn->cbHostBuffer);
577
578 /* Return the size of needed buffer */
579 *pcbBuffer = pClient->conn->cbHostBuffer;
580
581 return VERR_BUFFER_OVERFLOW;
582 }
583
584 *pcbBuffer = pClient->conn->cbHostBuffer;
585
586 if (*pcbBuffer)
587 {
588 CRASSERT(pClient->conn->pHostBuffer);
589
590 crMemcpy(pBuffer, pClient->conn->pHostBuffer, *pcbBuffer);
591 pClient->conn->cbHostBuffer = 0;
592 }
593
594 return VINF_SUCCESS;
595}
596
597int32_t crVBoxServerClientRead(uint32_t u32ClientID, uint8_t *pBuffer, uint32_t *pcbBuffer)
598{
599 CRClient *pClient=NULL;
600 int32_t rc = crVBoxServerClientGet(u32ClientID, &pClient);
601
602 if (RT_FAILURE(rc))
603 return rc;
604
605#ifdef VBOX_WITH_CRHGSMI
606 CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
607#endif
608
609 return crVBoxServerInternalClientRead(pClient, pBuffer, pcbBuffer);
610}
611
612int32_t crVBoxServerClientSetVersion(uint32_t u32ClientID, uint32_t vMajor, uint32_t vMinor)
613{
614 CRClient *pClient=NULL;
615 int32_t i;
616
617 for (i = 0; i < cr_server.numClients; i++)
618 {
619 if (cr_server.clients[i] && cr_server.clients[i]->conn
620 && cr_server.clients[i]->conn->u32ClientID==u32ClientID)
621 {
622 pClient = cr_server.clients[i];
623 break;
624 }
625 }
626 if (!pClient) return VERR_INVALID_PARAMETER;
627
628 pClient->conn->vMajor = vMajor;
629 pClient->conn->vMinor = vMinor;
630
631 if (vMajor != CR_PROTOCOL_VERSION_MAJOR
632 || vMinor != CR_PROTOCOL_VERSION_MINOR)
633 {
634 return VERR_NOT_SUPPORTED;
635 }
636 else return VINF_SUCCESS;
637}
638
639int32_t crVBoxServerClientSetPID(uint32_t u32ClientID, uint64_t pid)
640{
641 CRClient *pClient=NULL;
642 int32_t i;
643
644 for (i = 0; i < cr_server.numClients; i++)
645 {
646 if (cr_server.clients[i] && cr_server.clients[i]->conn
647 && cr_server.clients[i]->conn->u32ClientID==u32ClientID)
648 {
649 pClient = cr_server.clients[i];
650 break;
651 }
652 }
653 if (!pClient) return VERR_INVALID_PARAMETER;
654
655 pClient->pid = pid;
656
657 return VINF_SUCCESS;
658}
659
660int
661CRServerMain(int argc, char *argv[])
662{
663 crServerInit(argc, argv);
664
665 crServerSerializeRemoteStreams();
666
667 crServerTearDown();
668
669 tearingdown = 0;
670
671 return 0;
672}
673
674static void crVBoxServerSaveMuralCB(unsigned long key, void *data1, void *data2)
675{
676 CRMuralInfo *pMI = (CRMuralInfo*) data1;
677 PSSMHANDLE pSSM = (PSSMHANDLE) data2;
678 int32_t rc;
679
680 CRASSERT(pMI && pSSM);
681
682 /* Don't store default mural */
683 if (!key) return;
684
685 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
686 CRASSERT(rc == VINF_SUCCESS);
687
688 rc = SSMR3PutMem(pSSM, pMI, RT_OFFSETOF(CRMuralInfo, CreateInfo));
689 CRASSERT(rc == VINF_SUCCESS);
690
691 if (pMI->pVisibleRects)
692 {
693 rc = SSMR3PutMem(pSSM, pMI->pVisibleRects, 4*sizeof(GLint)*pMI->cVisibleRects);
694 }
695}
696
697/* @todo add hashtable walker with result info and intermediate abort */
698static void crVBoxServerSaveCreateInfoCB(unsigned long key, void *data1, void *data2)
699{
700 CRCreateInfo_t *pCreateInfo = (CRCreateInfo_t *)data1;
701 PSSMHANDLE pSSM = (PSSMHANDLE) data2;
702 int32_t rc;
703
704 CRASSERT(pCreateInfo && pSSM);
705
706 /* Don't store default mural create info */
707 if (!key) return;
708
709 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
710 CRASSERT(rc == VINF_SUCCESS);
711
712 rc = SSMR3PutMem(pSSM, pCreateInfo, sizeof(*pCreateInfo));
713 CRASSERT(rc == VINF_SUCCESS);
714
715 if (pCreateInfo->pszDpyName)
716 {
717 rc = SSMR3PutStrZ(pSSM, pCreateInfo->pszDpyName);
718 CRASSERT(rc == VINF_SUCCESS);
719 }
720}
721
722static void crVBoxServerSaveCreateInfoFromMuralInfoCB(unsigned long key, void *data1, void *data2)
723{
724 CRMuralInfo *pMural = (CRMuralInfo *)data1;
725 CRCreateInfo_t *pCreateInfo = &pMural->CreateInfo;
726 crVBoxServerSaveCreateInfoCB(key, pCreateInfo, data2);
727}
728
729static void crVBoxServerSaveCreateInfoFromCtxInfoCB(unsigned long key, void *data1, void *data2)
730{
731 CRContextInfo *pContextInfo = (CRContextInfo *)data1;
732 CRCreateInfo_t CreateInfo = pContextInfo->CreateInfo;
733 /* saved state contains internal id */
734 CreateInfo.externalID = pContextInfo->pContext->id;
735 crVBoxServerSaveCreateInfoCB(key, &CreateInfo, data2);
736}
737
738static void crVBoxServerSyncTextureCB(unsigned long key, void *data1, void *data2)
739{
740 CRTextureObj *pTexture = (CRTextureObj *) data1;
741 CRContext *pContext = (CRContext *) data2;
742
743 CRASSERT(pTexture && pContext);
744 crStateTextureObjectDiff(pContext, NULL, NULL, pTexture, GL_TRUE);
745}
746
747static void crVBoxServerSaveContextStateCB(unsigned long key, void *data1, void *data2)
748{
749 CRContextInfo *pContextInfo = (CRContextInfo *) data1;
750 CRContext *pContext = pContextInfo->pContext;
751 PSSMHANDLE pSSM = (PSSMHANDLE) data2;
752 int32_t rc;
753
754 CRASSERT(pContext && pSSM);
755
756 /* We could have skipped saving the key and use similar callback to load context states back,
757 * but there's no guarantee we'd traverse hashtable in same order after loading.
758 */
759 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
760 CRASSERT(rc == VINF_SUCCESS);
761
762#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
763 CRASSERT(cr_server.curClient);
764 if (cr_server.curClient)
765 {
766# ifdef DEBUG_misha
767 {
768 unsigned long id;
769 if (!crHashtableGetDataKey(cr_server.contextTable, pContextInfo, &id))
770 crWarning("No client id for server ctx %d", pContext->id);
771 else
772 CRASSERT(id == key);
773 }
774# endif
775 crServerDispatchMakeCurrent(cr_server.curClient->currentWindow, 0, key);
776 }
777#endif
778
779 rc = crStateSaveContext(pContext, pSSM);
780 CRASSERT(rc == VINF_SUCCESS);
781}
782
783#if 0
784typedef struct CR_SERVER_CHECK_BUFFERS
785{
786 CRBufferObject *obj;
787 CRContext *ctx;
788}CR_SERVER_CHECK_BUFFERS, *PCR_SERVER_CHECK_BUFFERS;
789
790static void crVBoxServerCheckConsistencyContextBuffersCB(unsigned long key, void *data1, void *data2)
791{
792 CRContextInfo* pContextInfo = (CRContextInfo*)data1;
793 CRContext *ctx = pContextInfo->pContext;
794 PCR_SERVER_CHECK_BUFFERS pBuffers = (PCR_SERVER_CHECK_BUFFERS)data2;
795 CRBufferObject *obj = pBuffers->obj;
796 CRBufferObjectState *b = &(ctx->bufferobject);
797 int j, k;
798
799 if (obj == b->arrayBuffer)
800 {
801 Assert(!pBuffers->ctx || pBuffers->ctx == ctx);
802 pBuffers->ctx = ctx;
803 }
804 if (obj == b->elementsBuffer)
805 {
806 Assert(!pBuffers->ctx || pBuffers->ctx == ctx);
807 pBuffers->ctx = ctx;
808 }
809#ifdef CR_ARB_pixel_buffer_object
810 if (obj == b->packBuffer)
811 {
812 Assert(!pBuffers->ctx || pBuffers->ctx == ctx);
813 pBuffers->ctx = ctx;
814 }
815 if (obj == b->unpackBuffer)
816 {
817 Assert(!pBuffers->ctx || pBuffers->ctx == ctx);
818 pBuffers->ctx = ctx;
819 }
820#endif
821
822#ifdef CR_ARB_vertex_buffer_object
823 for (j=0; j<CRSTATECLIENT_MAX_VERTEXARRAYS; ++j)
824 {
825 CRClientPointer *cp = crStateGetClientPointerByIndex(j, &ctx->client.array);
826 if (obj == cp->buffer)
827 {
828 Assert(!pBuffers->ctx || pBuffers->ctx == ctx);
829 pBuffers->ctx = ctx;
830 }
831 }
832
833 for (k=0; k<ctx->client.vertexArrayStackDepth; ++k)
834 {
835 CRVertexArrays *pArray = &ctx->client.vertexArrayStack[k];
836 for (j=0; j<CRSTATECLIENT_MAX_VERTEXARRAYS; ++j)
837 {
838 CRClientPointer *cp = crStateGetClientPointerByIndex(j, pArray);
839 if (obj == cp->buffer)
840 {
841 Assert(!pBuffers->ctx || pBuffers->ctx == ctx);
842 pBuffers->ctx = ctx;
843 }
844 }
845 }
846#endif
847}
848
849static void crVBoxServerCheckConsistencyBuffersCB(unsigned long key, void *data1, void *data2)
850{
851 CRBufferObject *obj = (CRBufferObject *)data1;
852 CR_SERVER_CHECK_BUFFERS Buffers = {0};
853 Buffers.obj = obj;
854 crHashtableWalk(cr_server.contextTable, crVBoxServerCheckConsistencyContextBuffersCB, (void*)&Buffers);
855}
856
857//static void crVBoxServerCheckConsistency2CB(unsigned long key, void *data1, void *data2)
858//{
859// CRContextInfo* pContextInfo1 = (CRContextInfo*)data1;
860// CRContextInfo* pContextInfo2 = (CRContextInfo*)data2;
861//
862// CRASSERT(pContextInfo1->pContext);
863// CRASSERT(pContextInfo2->pContext);
864//
865// if (pContextInfo1 == pContextInfo2)
866// {
867// CRASSERT(pContextInfo1->pContext == pContextInfo2->pContext);
868// return;
869// }
870//
871// CRASSERT(pContextInfo1->pContext != pContextInfo2->pContext);
872// CRASSERT(pContextInfo1->pContext->shared);
873// CRASSERT(pContextInfo2->pContext->shared);
874// CRASSERT(pContextInfo1->pContext->shared == pContextInfo2->pContext->shared);
875// if (pContextInfo1->pContext->shared != pContextInfo2->pContext->shared)
876// return;
877//
878// crHashtableWalk(pContextInfo1->pContext->shared->buffersTable, crVBoxServerCheckConsistencyBuffersCB, pContextInfo2);
879//}
880static void crVBoxServerCheckSharedCB(unsigned long key, void *data1, void *data2)
881{
882 CRContextInfo* pContextInfo = (CRContextInfo*)data1;
883 void **ppShared = (void**)data2;
884 if (!*ppShared)
885 *ppShared = pContextInfo->pContext->shared;
886 else
887 Assert(pContextInfo->pContext->shared == *ppShared);
888}
889
890static void crVBoxServerCheckConsistency()
891{
892 CRSharedState *pShared = NULL;
893 crHashtableWalk(cr_server.contextTable, crVBoxServerCheckSharedCB, (void*)&pShared);
894 Assert(pShared);
895 if (pShared)
896 {
897 crHashtableWalk(pShared->buffersTable, crVBoxServerCheckConsistencyBuffersCB, NULL);
898 }
899}
900#endif
901
902static uint32_t g_hackVBoxServerSaveLoadCallsLeft = 0;
903
904DECLEXPORT(int32_t) crVBoxServerSaveState(PSSMHANDLE pSSM)
905{
906 int32_t rc, i;
907 uint32_t ui32;
908 GLboolean b;
909 unsigned long key;
910 GLenum err;
911#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
912 unsigned long ctxID=-1, winID=-1;
913#endif
914
915#if 0
916 crVBoxServerCheckConsistency();
917#endif
918
919 /* We shouldn't be called if there's no clients at all*/
920 CRASSERT(cr_server.numClients>0);
921
922 /* @todo it's hack atm */
923 /* We want to be called only once to save server state but atm we're being called from svcSaveState
924 * for every connected client (e.g. guest opengl application)
925 */
926 if (!cr_server.bIsInSavingState) /* It's first call */
927 {
928 cr_server.bIsInSavingState = GL_TRUE;
929
930 /* Store number of clients */
931 rc = SSMR3PutU32(pSSM, (uint32_t) cr_server.numClients);
932 AssertRCReturn(rc, rc);
933
934 g_hackVBoxServerSaveLoadCallsLeft = cr_server.numClients;
935 }
936
937 g_hackVBoxServerSaveLoadCallsLeft--;
938
939 /* Do nothing until we're being called last time */
940 if (g_hackVBoxServerSaveLoadCallsLeft>0)
941 {
942 return VINF_SUCCESS;
943 }
944
945 /* Save rendering contexts creation info */
946 ui32 = crHashtableNumElements(cr_server.contextTable);
947 rc = SSMR3PutU32(pSSM, (uint32_t) ui32);
948 AssertRCReturn(rc, rc);
949 crHashtableWalk(cr_server.contextTable, crVBoxServerSaveCreateInfoFromCtxInfoCB, pSSM);
950
951#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
952 /* Save current win and ctx IDs, as we'd rebind contexts when saving textures */
953 if (cr_server.curClient)
954 {
955 ctxID = cr_server.curClient->currentContextNumber;
956 winID = cr_server.curClient->currentWindow;
957 }
958#endif
959
960 /* Save contexts state tracker data */
961 /* @todo For now just some blind data dumps,
962 * but I've a feeling those should be saved/restored in a very strict sequence to
963 * allow diff_api to work correctly.
964 * Should be tested more with multiply guest opengl apps working when saving VM snapshot.
965 */
966 crHashtableWalk(cr_server.contextTable, crVBoxServerSaveContextStateCB, pSSM);
967
968#ifdef CR_STATE_NO_TEXTURE_IMAGE_STORE
969 /* Restore original win and ctx IDs*/
970 if (cr_server.curClient)
971 {
972 crServerDispatchMakeCurrent(winID, 0, ctxID);
973 }
974#endif
975
976 /* Save windows creation info */
977 ui32 = crHashtableNumElements(cr_server.muralTable);
978 /* There should be default mural always */
979 CRASSERT(ui32>=1);
980 rc = SSMR3PutU32(pSSM, (uint32_t) ui32-1);
981 AssertRCReturn(rc, rc);
982 crHashtableWalk(cr_server.muralTable, crVBoxServerSaveCreateInfoFromMuralInfoCB, pSSM);
983
984 /* Save cr_server.muralTable
985 * @todo we don't need it all, just geometry info actually
986 */
987 rc = SSMR3PutU32(pSSM, (uint32_t) ui32-1);
988 AssertRCReturn(rc, rc);
989 crHashtableWalk(cr_server.muralTable, crVBoxServerSaveMuralCB, pSSM);
990
991 /* Save starting free context and window IDs */
992 rc = SSMR3PutMem(pSSM, &cr_server.idsPool, sizeof(cr_server.idsPool));
993 AssertRCReturn(rc, rc);
994
995 /* Save clients info */
996 for (i = 0; i < cr_server.numClients; i++)
997 {
998 if (cr_server.clients[i] && cr_server.clients[i]->conn)
999 {
1000 CRClient *pClient = cr_server.clients[i];
1001
1002 rc = SSMR3PutU32(pSSM, pClient->conn->u32ClientID);
1003 AssertRCReturn(rc, rc);
1004
1005 rc = SSMR3PutU32(pSSM, pClient->conn->vMajor);
1006 AssertRCReturn(rc, rc);
1007
1008 rc = SSMR3PutU32(pSSM, pClient->conn->vMinor);
1009 AssertRCReturn(rc, rc);
1010
1011 rc = SSMR3PutMem(pSSM, pClient, sizeof(*pClient));
1012 AssertRCReturn(rc, rc);
1013
1014 if (pClient->currentCtxInfo && pClient->currentCtxInfo->pContext && pClient->currentContextNumber>=0)
1015 {
1016 b = crHashtableGetDataKey(cr_server.contextTable, pClient->currentCtxInfo, &key);
1017 CRASSERT(b);
1018 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
1019 AssertRCReturn(rc, rc);
1020 }
1021
1022 if (pClient->currentMural && pClient->currentWindow>=0)
1023 {
1024 b = crHashtableGetDataKey(cr_server.muralTable, pClient->currentMural, &key);
1025 CRASSERT(b);
1026 rc = SSMR3PutMem(pSSM, &key, sizeof(key));
1027 AssertRCReturn(rc, rc);
1028 }
1029 }
1030 }
1031
1032 /* all context gl error states should have now be synced with chromium erro states,
1033 * reset the error if any */
1034 while ((err = cr_server.head_spu->dispatch_table.GetError()) != GL_NO_ERROR)
1035 crWarning("crServer: glGetError %d after saving snapshot", err);
1036
1037 cr_server.bIsInSavingState = GL_FALSE;
1038
1039 return VINF_SUCCESS;
1040}
1041
1042static DECLCALLBACK(CRContext*) crVBoxServerGetContextCB(void* pvData)
1043{
1044 CRContextInfo* pContextInfo = (CRContextInfo*)pvData;
1045 CRASSERT(pContextInfo);
1046 CRASSERT(pContextInfo->pContext);
1047 return pContextInfo->pContext;
1048}
1049
1050DECLEXPORT(int32_t) crVBoxServerLoadState(PSSMHANDLE pSSM, uint32_t version)
1051{
1052 int32_t rc, i;
1053 uint32_t ui, uiNumElems;
1054 unsigned long key;
1055 GLenum err;
1056
1057 if (!cr_server.bIsInLoadingState)
1058 {
1059 /* AssertRCReturn(...) will leave us in loading state, but it doesn't matter as we'd be failing anyway */
1060 cr_server.bIsInLoadingState = GL_TRUE;
1061
1062 /* Read number of clients */
1063 rc = SSMR3GetU32(pSSM, &g_hackVBoxServerSaveLoadCallsLeft);
1064 AssertRCReturn(rc, rc);
1065 }
1066
1067 g_hackVBoxServerSaveLoadCallsLeft--;
1068
1069 /* Do nothing until we're being called last time */
1070 if (g_hackVBoxServerSaveLoadCallsLeft>0)
1071 {
1072 return VINF_SUCCESS;
1073 }
1074
1075 if (version < SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS)
1076 {
1077 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;
1078 }
1079
1080 /* Load and recreate rendering contexts */
1081 rc = SSMR3GetU32(pSSM, &uiNumElems);
1082 AssertRCReturn(rc, rc);
1083 for (ui=0; ui<uiNumElems; ++ui)
1084 {
1085 CRCreateInfo_t createInfo;
1086 char psz[200];
1087 GLint ctxID;
1088 CRContextInfo* pContextInfo;
1089 CRContext* pContext;
1090
1091 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
1092 AssertRCReturn(rc, rc);
1093 rc = SSMR3GetMem(pSSM, &createInfo, sizeof(createInfo));
1094 AssertRCReturn(rc, rc);
1095
1096 if (createInfo.pszDpyName)
1097 {
1098 rc = SSMR3GetStrZEx(pSSM, psz, 200, NULL);
1099 AssertRCReturn(rc, rc);
1100 createInfo.pszDpyName = psz;
1101 }
1102
1103 ctxID = crServerDispatchCreateContextEx(createInfo.pszDpyName, createInfo.visualBits, 0, key, createInfo.externalID /* <-saved state stores internal id here*/);
1104 CRASSERT((int64_t)ctxID == (int64_t)key);
1105
1106 pContextInfo = (CRContextInfo*) crHashtableSearch(cr_server.contextTable, key);
1107 CRASSERT(pContextInfo);
1108 CRASSERT(pContextInfo->pContext);
1109 pContext = pContextInfo->pContext;
1110 pContext->shared->id=-1;
1111 }
1112
1113 /* Restore context state data */
1114 for (ui=0; ui<uiNumElems; ++ui)
1115 {
1116 CRContextInfo* pContextInfo;
1117 CRContext *pContext;
1118
1119 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
1120 AssertRCReturn(rc, rc);
1121
1122 pContextInfo = (CRContextInfo*) crHashtableSearch(cr_server.contextTable, key);
1123 CRASSERT(pContextInfo);
1124 CRASSERT(pContextInfo->pContext);
1125 pContext = pContextInfo->pContext;
1126
1127 rc = crStateLoadContext(pContext, cr_server.contextTable, crVBoxServerGetContextCB, pSSM, version);
1128 AssertRCReturn(rc, rc);
1129 }
1130
1131 /* Load windows */
1132 rc = SSMR3GetU32(pSSM, &uiNumElems);
1133 AssertRCReturn(rc, rc);
1134 for (ui=0; ui<uiNumElems; ++ui)
1135 {
1136 CRCreateInfo_t createInfo;
1137 char psz[200];
1138 GLint winID;
1139 unsigned long key;
1140
1141 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
1142 AssertRCReturn(rc, rc);
1143 rc = SSMR3GetMem(pSSM, &createInfo, sizeof(createInfo));
1144 AssertRCReturn(rc, rc);
1145
1146 if (createInfo.pszDpyName)
1147 {
1148 rc = SSMR3GetStrZEx(pSSM, psz, 200, NULL);
1149 AssertRCReturn(rc, rc);
1150 createInfo.pszDpyName = psz;
1151 }
1152
1153 winID = crServerDispatchWindowCreateEx(createInfo.pszDpyName, createInfo.visualBits, key);
1154 CRASSERT((int64_t)winID == (int64_t)key);
1155 }
1156
1157 /* Load cr_server.muralTable */
1158 rc = SSMR3GetU32(pSSM, &uiNumElems);
1159 AssertRCReturn(rc, rc);
1160 for (ui=0; ui<uiNumElems; ++ui)
1161 {
1162 CRMuralInfo muralInfo;
1163
1164 rc = SSMR3GetMem(pSSM, &key, sizeof(key));
1165 AssertRCReturn(rc, rc);
1166 rc = SSMR3GetMem(pSSM, &muralInfo, RT_OFFSETOF(CRMuralInfo, CreateInfo));
1167 AssertRCReturn(rc, rc);
1168
1169 if (version <= SHCROGL_SSM_VERSION_BEFORE_FRONT_DRAW_TRACKING)
1170 muralInfo.bFbDraw = GL_TRUE;
1171
1172 if (muralInfo.pVisibleRects)
1173 {
1174 muralInfo.pVisibleRects = crAlloc(4*sizeof(GLint)*muralInfo.cVisibleRects);
1175 if (!muralInfo.pVisibleRects)
1176 {
1177 return VERR_NO_MEMORY;
1178 }
1179
1180 rc = SSMR3GetMem(pSSM, muralInfo.pVisibleRects, 4*sizeof(GLint)*muralInfo.cVisibleRects);
1181 AssertRCReturn(rc, rc);
1182 }
1183
1184 /* Restore windows geometry info */
1185 crServerDispatchWindowSize(key, muralInfo.width, muralInfo.height);
1186 crServerDispatchWindowPosition(key, muralInfo.gX, muralInfo.gY);
1187 /* Same workaround as described in stub.c:stubUpdateWindowVisibileRegions for compiz on a freshly booted VM*/
1188 if (muralInfo.bReceivedRects)
1189 {
1190 crServerDispatchWindowVisibleRegion(key, muralInfo.cVisibleRects, muralInfo.pVisibleRects);
1191 }
1192 crServerDispatchWindowShow(key, muralInfo.bVisible);
1193
1194 if (muralInfo.pVisibleRects)
1195 {
1196 crFree(muralInfo.pVisibleRects);
1197 }
1198 }
1199
1200 /* Load starting free context and window IDs */
1201 rc = SSMR3GetMem(pSSM, &cr_server.idsPool, sizeof(cr_server.idsPool));
1202 CRASSERT(rc == VINF_SUCCESS);
1203
1204 /* Load clients info */
1205 for (i = 0; i < cr_server.numClients; i++)
1206 {
1207 if (cr_server.clients[i] && cr_server.clients[i]->conn)
1208 {
1209 CRClient *pClient = cr_server.clients[i];
1210 CRClient client;
1211 unsigned long ctxID=-1, winID=-1;
1212
1213 rc = SSMR3GetU32(pSSM, &ui);
1214 AssertRCReturn(rc, rc);
1215 /* If this assert fires, then we should search correct client in the list first*/
1216 CRASSERT(ui == pClient->conn->u32ClientID);
1217
1218 if (version>=4)
1219 {
1220 rc = SSMR3GetU32(pSSM, &pClient->conn->vMajor);
1221 AssertRCReturn(rc, rc);
1222
1223 rc = SSMR3GetU32(pSSM, &pClient->conn->vMinor);
1224 AssertRCReturn(rc, rc);
1225 }
1226
1227 rc = SSMR3GetMem(pSSM, &client, sizeof(client));
1228 CRASSERT(rc == VINF_SUCCESS);
1229
1230 client.conn = pClient->conn;
1231 /* We can't reassign client number, as we'd get wrong results in TranslateTextureID
1232 * and fail to bind old textures.
1233 */
1234 /*client.number = pClient->number;*/
1235 *pClient = client;
1236
1237 pClient->currentContextNumber = -1;
1238 pClient->currentCtxInfo = &cr_server.MainContextInfo;
1239 pClient->currentMural = NULL;
1240 pClient->currentWindow = -1;
1241
1242 cr_server.curClient = pClient;
1243
1244 if (client.currentCtxInfo && client.currentContextNumber>=0)
1245 {
1246 rc = SSMR3GetMem(pSSM, &ctxID, sizeof(ctxID));
1247 AssertRCReturn(rc, rc);
1248 client.currentCtxInfo = (CRContextInfo*) crHashtableSearch(cr_server.contextTable, ctxID);
1249 CRASSERT(client.currentCtxInfo);
1250 CRASSERT(client.currentCtxInfo->pContext);
1251 //pClient->currentCtx = client.currentCtx;
1252 //pClient->currentContextNumber = ctxID;
1253 }
1254
1255 if (client.currentMural && client.currentWindow>=0)
1256 {
1257 rc = SSMR3GetMem(pSSM, &winID, sizeof(winID));
1258 AssertRCReturn(rc, rc);
1259 client.currentMural = (CRMuralInfo*) crHashtableSearch(cr_server.muralTable, winID);
1260 CRASSERT(client.currentMural);
1261 //pClient->currentMural = client.currentMural;
1262 //pClient->currentWindow = winID;
1263 }
1264
1265 /* Restore client active context and window */
1266 crServerDispatchMakeCurrent(winID, 0, ctxID);
1267
1268 if (0)
1269 {
1270// CRContext *tmpCtx;
1271// CRCreateInfo_t *createInfo;
1272 GLfloat one[4] = { 1, 1, 1, 1 };
1273 GLfloat amb[4] = { 0.4f, 0.4f, 0.4f, 1.0f };
1274
1275 crServerDispatchMakeCurrent(winID, 0, ctxID);
1276
1277 crHashtableWalk(client.currentCtxInfo->pContext->shared->textureTable, crVBoxServerSyncTextureCB, client.currentCtxInfo->pContext);
1278
1279 crStateTextureObjectDiff(client.currentCtxInfo->pContext, NULL, NULL, &client.currentCtxInfo->pContext->texture.base1D, GL_TRUE);
1280 crStateTextureObjectDiff(client.currentCtxInfo->pContext, NULL, NULL, &client.currentCtxInfo->pContext->texture.base2D, GL_TRUE);
1281 crStateTextureObjectDiff(client.currentCtxInfo->pContext, NULL, NULL, &client.currentCtxInfo->pContext->texture.base3D, GL_TRUE);
1282#ifdef CR_ARB_texture_cube_map
1283 crStateTextureObjectDiff(client.currentCtxInfo->pContext, NULL, NULL, &client.currentCtxInfo->pContext->texture.baseCubeMap, GL_TRUE);
1284#endif
1285#ifdef CR_NV_texture_rectangle
1286 //@todo this doesn't work as expected
1287 //crStateTextureObjectDiff(client.currentCtxInfo->pContext, NULL, NULL, &client.currentCtxInfo->pContext->texture.baseRect, GL_TRUE);
1288#endif
1289 /*cr_server.head_spu->dispatch_table.Materialfv(GL_FRONT_AND_BACK, GL_AMBIENT, amb);
1290 cr_server.head_spu->dispatch_table.LightModelfv(GL_LIGHT_MODEL_AMBIENT, amb);
1291 cr_server.head_spu->dispatch_table.Lightfv(GL_LIGHT1, GL_DIFFUSE, one);
1292
1293 cr_server.head_spu->dispatch_table.Enable(GL_LIGHTING);
1294 cr_server.head_spu->dispatch_table.Enable(GL_LIGHT0);
1295 cr_server.head_spu->dispatch_table.Enable(GL_LIGHT1);
1296
1297 cr_server.head_spu->dispatch_table.Enable(GL_CULL_FACE);
1298 cr_server.head_spu->dispatch_table.Enable(GL_TEXTURE_2D);*/
1299
1300 //crStateViewport( 0, 0, 600, 600 );
1301 //pClient->currentMural->viewportValidated = GL_FALSE;
1302 //cr_server.head_spu->dispatch_table.Viewport( 0, 0, 600, 600 );
1303
1304 //crStateMatrixMode(GL_PROJECTION);
1305 //cr_server.head_spu->dispatch_table.MatrixMode(GL_PROJECTION);
1306
1307 //crStateLoadIdentity();
1308 //cr_server.head_spu->dispatch_table.LoadIdentity();
1309
1310 //crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
1311 //cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
1312
1313 //crStateMatrixMode(GL_MODELVIEW);
1314 //cr_server.head_spu->dispatch_table.MatrixMode(GL_MODELVIEW);
1315 //crServerDispatchLoadIdentity();
1316 //crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
1317 //cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
1318 //crServerDispatchLoadIdentity();
1319
1320 /*createInfo = (CRCreateInfo_t *) crHashtableSearch(cr_server.pContextCreateInfoTable, ctxID);
1321 CRASSERT(createInfo);
1322 tmpCtx = crStateCreateContext(NULL, createInfo->visualBits, NULL);
1323 CRASSERT(tmpCtx);
1324 crStateDiffContext(tmpCtx, client.currentCtxInfo->pContext);
1325 crStateDestroyContext(tmpCtx);*/
1326 }
1327 }
1328 }
1329
1330 //crServerDispatchMakeCurrent(-1, 0, -1);
1331
1332 cr_server.curClient = NULL;
1333
1334 while ((err = cr_server.head_spu->dispatch_table.GetError()) != GL_NO_ERROR)
1335 crWarning("crServer: glGetError %d after loading snapshot", err);
1336
1337 cr_server.bIsInLoadingState = GL_FALSE;
1338
1339#if 0
1340 crVBoxServerCheckConsistency();
1341#endif
1342
1343 return VINF_SUCCESS;
1344}
1345
1346#define SCREEN(i) (cr_server.screen[i])
1347#define MAPPED(screen) ((screen).winID != 0)
1348
1349static void crVBoxServerReparentMuralCB(unsigned long key, void *data1, void *data2)
1350{
1351 CRMuralInfo *pMI = (CRMuralInfo*) data1;
1352 int *sIndex = (int*) data2;
1353
1354 if (pMI->screenId == *sIndex)
1355 {
1356 renderspuReparentWindow(pMI->spuWindow);
1357 }
1358}
1359
1360static void crVBoxServerCheckMuralCB(unsigned long key, void *data1, void *data2)
1361{
1362 CRMuralInfo *pMI = (CRMuralInfo*) data1;
1363 (void) data2;
1364
1365 crServerCheckMuralGeometry(pMI);
1366}
1367
1368DECLEXPORT(int32_t) crVBoxServerSetScreenCount(int sCount)
1369{
1370 int i;
1371
1372 if (sCount>CR_MAX_GUEST_MONITORS)
1373 return VERR_INVALID_PARAMETER;
1374
1375 /*Shouldn't happen yet, but to be safe in future*/
1376 for (i=0; i<cr_server.screenCount; ++i)
1377 {
1378 if (MAPPED(SCREEN(i)))
1379 crWarning("Screen count is changing, but screen[%i] is still mapped", i);
1380 return VERR_NOT_IMPLEMENTED;
1381 }
1382
1383 cr_server.screenCount = sCount;
1384
1385 for (i=0; i<sCount; ++i)
1386 {
1387 SCREEN(i).winID = 0;
1388 }
1389
1390 return VINF_SUCCESS;
1391}
1392
1393DECLEXPORT(int32_t) crVBoxServerUnmapScreen(int sIndex)
1394{
1395 crDebug("crVBoxServerUnmapScreen(%i)", sIndex);
1396
1397 if (sIndex<0 || sIndex>=cr_server.screenCount)
1398 return VERR_INVALID_PARAMETER;
1399
1400 if (MAPPED(SCREEN(sIndex)))
1401 {
1402 SCREEN(sIndex).winID = 0;
1403 renderspuSetWindowId(0);
1404
1405 crHashtableWalk(cr_server.muralTable, crVBoxServerReparentMuralCB, &sIndex);
1406 }
1407
1408 renderspuSetWindowId(SCREEN(0).winID);
1409 return VINF_SUCCESS;
1410}
1411
1412DECLEXPORT(int32_t) crVBoxServerMapScreen(int sIndex, int32_t x, int32_t y, uint32_t w, uint32_t h, uint64_t winID)
1413{
1414 crDebug("crVBoxServerMapScreen(%i) [%i,%i:%u,%u %x]", sIndex, x, y, w, h, winID);
1415
1416 if (sIndex<0 || sIndex>=cr_server.screenCount)
1417 return VERR_INVALID_PARAMETER;
1418
1419 if (MAPPED(SCREEN(sIndex)) && SCREEN(sIndex).winID!=winID)
1420 {
1421 crDebug("Mapped screen[%i] is being remapped.", sIndex);
1422 crVBoxServerUnmapScreen(sIndex);
1423 }
1424
1425 SCREEN(sIndex).winID = winID;
1426 SCREEN(sIndex).x = x;
1427 SCREEN(sIndex).y = y;
1428 SCREEN(sIndex).w = w;
1429 SCREEN(sIndex).h = h;
1430
1431 renderspuSetWindowId(SCREEN(sIndex).winID);
1432 crHashtableWalk(cr_server.muralTable, crVBoxServerReparentMuralCB, &sIndex);
1433 renderspuSetWindowId(SCREEN(0).winID);
1434
1435 crHashtableWalk(cr_server.muralTable, crVBoxServerCheckMuralCB, NULL);
1436
1437#ifndef WINDOWS
1438 /*Restore FB content for clients, which have current window on a screen being remapped*/
1439 {
1440 GLint i;
1441
1442 for (i = 0; i < cr_server.numClients; i++)
1443 {
1444 cr_server.curClient = cr_server.clients[i];
1445 if (cr_server.curClient->currentCtxInfo
1446 && cr_server.curClient->currentCtxInfo->pContext
1447 && (cr_server.curClient->currentCtxInfo->pContext->buffer.pFrontImg || cr_server.curClient->currentCtxInfo->pContext->buffer.pBackImg)
1448 && cr_server.curClient->currentMural
1449 && cr_server.curClient->currentMural->screenId == sIndex
1450 && cr_server.curClient->currentCtxInfo->pContext->buffer.storedHeight == h
1451 && cr_server.curClient->currentCtxInfo->pContext->buffer.storedWidth == w)
1452 {
1453 int clientWindow = cr_server.curClient->currentWindow;
1454 int clientContext = cr_server.curClient->currentContextNumber;
1455
1456 if (clientWindow && clientWindow != cr_server.currentWindow)
1457 {
1458 crServerDispatchMakeCurrent(clientWindow, 0, clientContext);
1459 }
1460
1461 crStateApplyFBImage(cr_server.curClient->currentCtxInfo->pContext);
1462 }
1463 }
1464 cr_server.curClient = NULL;
1465 }
1466#endif
1467
1468 {
1469 PCR_DISPLAY pDisplay = crServerDisplayGetInitialized(sIndex);
1470 if (pDisplay)
1471 CrDpResize(pDisplay, w, h, w, h);
1472 }
1473
1474 return VINF_SUCCESS;
1475}
1476
1477DECLEXPORT(int32_t) crVBoxServerSetRootVisibleRegion(GLint cRects, GLint *pRects)
1478{
1479 renderspuSetRootVisibleRegion(cRects, pRects);
1480
1481 return VINF_SUCCESS;
1482}
1483
1484DECLEXPORT(void) crVBoxServerSetPresentFBOCB(PFNCRSERVERPRESENTFBO pfnPresentFBO)
1485{
1486 cr_server.pfnPresentFBO = pfnPresentFBO;
1487}
1488
1489int32_t crServerSetOffscreenRenderingMode(GLubyte value)
1490{
1491 if (cr_server.bForceOffscreenRendering==value)
1492 {
1493 return VINF_SUCCESS;
1494 }
1495
1496 if (value > CR_SERVER_REDIR_MAXVAL)
1497 {
1498 crWarning("crServerSetOffscreenRenderingMode: invalid arg: %d", value);
1499 return VERR_INVALID_PARAMETER;
1500 }
1501
1502 if (value && !crServerSupportRedirMuralFBO())
1503 {
1504 return VERR_NOT_SUPPORTED;
1505 }
1506
1507 cr_server.bForceOffscreenRendering=value;
1508
1509 crHashtableWalk(cr_server.muralTable, crVBoxServerCheckMuralCB, NULL);
1510
1511 return VINF_SUCCESS;
1512}
1513
1514DECLEXPORT(int32_t) crVBoxServerSetOffscreenRendering(GLboolean value)
1515{
1516 return crServerSetOffscreenRenderingMode(value ? CR_SERVER_REDIR_FBO_RAM : cr_server.bOffscreenRenderingDefault);
1517}
1518
1519DECLEXPORT(int32_t) crVBoxServerOutputRedirectSet(const CROutputRedirect *pCallbacks)
1520{
1521 /* No need for a synchronization as this is single threaded. */
1522 if (pCallbacks)
1523 {
1524 cr_server.outputRedirect = *pCallbacks;
1525 cr_server.bUseOutputRedirect = true;
1526 }
1527 else
1528 {
1529 cr_server.bUseOutputRedirect = false;
1530 }
1531
1532 // @todo dynamically intercept already existing output:
1533 // crHashtableWalk(cr_server.muralTable, crVBoxServerOutputRedirectCB, NULL);
1534
1535 return VINF_SUCCESS;
1536}
1537
1538static void crVBoxServerUpdateScreenViewportCB(unsigned long key, void *data1, void *data2)
1539{
1540 CRMuralInfo *mural = (CRMuralInfo*) data1;
1541 int *sIndex = (int*) data2;
1542
1543 if (mural->screenId != *sIndex)
1544 return;
1545
1546 crServerCheckMuralGeometry(mural);
1547}
1548
1549
1550DECLEXPORT(int32_t) crVBoxServerSetScreenViewport(int sIndex, int32_t x, int32_t y, uint32_t w, uint32_t h)
1551{
1552 CRScreenViewportInfo *pVieport;
1553 GLboolean fPosChanged, fSizeChanged;
1554
1555 crDebug("crVBoxServerSetScreenViewport(%i)", sIndex);
1556
1557 if (sIndex<0 || sIndex>=cr_server.screenCount)
1558 {
1559 crWarning("crVBoxServerSetScreenViewport: invalid screen id %d", sIndex);
1560 return VERR_INVALID_PARAMETER;
1561 }
1562
1563 pVieport = &cr_server.screenVieport[sIndex];
1564 fPosChanged = (pVieport->x != x || pVieport->y != y);
1565 fSizeChanged = (pVieport->w != w || pVieport->h != h);
1566
1567 if (!fPosChanged && !fSizeChanged)
1568 {
1569 crDebug("crVBoxServerSetScreenViewport: no changes");
1570 return VINF_SUCCESS;
1571 }
1572
1573 if (fPosChanged)
1574 {
1575 pVieport->x = x;
1576 pVieport->y = y;
1577
1578 crHashtableWalk(cr_server.muralTable, crVBoxServerUpdateScreenViewportCB, &sIndex);
1579 }
1580
1581 if (fSizeChanged)
1582 {
1583 pVieport->w = w;
1584 pVieport->h = h;
1585
1586 /* no need to do anything here actually */
1587 }
1588 return VINF_SUCCESS;
1589}
1590
1591
1592#ifdef VBOX_WITH_CRHGSMI
1593/* We moved all CrHgsmi command processing to crserverlib to keep the logic of dealing with CrHgsmi commands in one place.
1594 *
1595 * For now we need the notion of CrHgdmi commands in the crserver_lib to be able to complete it asynchronously once it is really processed.
1596 * This help avoiding the "blocked-client" issues. The client is blocked if another client is doing begin-end stuff.
1597 * For now we eliminated polling that could occur on block, which caused a higher-priority thread (in guest) polling for the blocked command complition
1598 * to block the lower-priority thread trying to complete the blocking command.
1599 * And removed extra memcpy done on blocked command arrival.
1600 *
1601 * In the future we will extend CrHgsmi functionality to maintain texture data directly in CrHgsmi allocation to avoid extra memcpy-ing with PBO,
1602 * implement command completion and stuff necessary for GPU scheduling to work properly for WDDM Windows guests, etc.
1603 *
1604 * NOTE: it is ALWAYS responsibility of the crVBoxServerCrHgsmiCmd to complete the command!
1605 * */
1606int32_t crVBoxServerCrHgsmiCmd(struct VBOXVDMACMD_CHROMIUM_CMD *pCmd, uint32_t cbCmd)
1607{
1608 int32_t rc;
1609 uint32_t cBuffers = pCmd->cBuffers;
1610 uint32_t cParams;
1611 uint32_t cbHdr;
1612 CRVBOXHGSMIHDR *pHdr;
1613 uint32_t u32Function;
1614 uint32_t u32ClientID;
1615 CRClient *pClient;
1616
1617 if (!g_pvVRamBase)
1618 {
1619 crWarning("g_pvVRamBase is not initialized");
1620 crServerCrHgsmiCmdComplete(pCmd, VERR_INVALID_STATE);
1621 return VINF_SUCCESS;
1622 }
1623
1624 if (!cBuffers)
1625 {
1626 crWarning("zero buffers passed in!");
1627 crServerCrHgsmiCmdComplete(pCmd, VERR_INVALID_PARAMETER);
1628 return VINF_SUCCESS;
1629 }
1630
1631 cParams = cBuffers-1;
1632
1633 cbHdr = pCmd->aBuffers[0].cbBuffer;
1634 pHdr = VBOXCRHGSMI_PTR_SAFE(pCmd->aBuffers[0].offBuffer, cbHdr, CRVBOXHGSMIHDR);
1635 if (!pHdr)
1636 {
1637 crWarning("invalid header buffer!");
1638 crServerCrHgsmiCmdComplete(pCmd, VERR_INVALID_PARAMETER);
1639 return VINF_SUCCESS;
1640 }
1641
1642 if (cbHdr < sizeof (*pHdr))
1643 {
1644 crWarning("invalid header buffer size!");
1645 crServerCrHgsmiCmdComplete(pCmd, VERR_INVALID_PARAMETER);
1646 return VINF_SUCCESS;
1647 }
1648
1649 u32Function = pHdr->u32Function;
1650 u32ClientID = pHdr->u32ClientID;
1651
1652 switch (u32Function)
1653 {
1654 case SHCRGL_GUEST_FN_WRITE:
1655 {
1656 crDebug(("svcCall: SHCRGL_GUEST_FN_WRITE\n"));
1657
1658 /* @todo: Verify */
1659 if (cParams == 1)
1660 {
1661 CRVBOXHGSMIWRITE* pFnCmd = (CRVBOXHGSMIWRITE*)pHdr;
1662 VBOXVDMACMD_CHROMIUM_BUFFER *pBuf = &pCmd->aBuffers[1];
1663 /* Fetch parameters. */
1664 uint32_t cbBuffer = pBuf->cbBuffer;
1665 uint8_t *pBuffer = VBOXCRHGSMI_PTR_SAFE(pBuf->offBuffer, cbBuffer, uint8_t);
1666
1667 if (cbHdr < sizeof (*pFnCmd))
1668 {
1669 crWarning("invalid write cmd buffer size!");
1670 rc = VERR_INVALID_PARAMETER;
1671 break;
1672 }
1673
1674 CRASSERT(cbBuffer);
1675 if (!pBuffer)
1676 {
1677 crWarning("invalid buffer data received from guest!");
1678 rc = VERR_INVALID_PARAMETER;
1679 break;
1680 }
1681
1682 rc = crVBoxServerClientGet(u32ClientID, &pClient);
1683 if (RT_FAILURE(rc))
1684 {
1685 break;
1686 }
1687
1688 /* This should never fire unless we start to multithread */
1689 CRASSERT(pClient->conn->pBuffer==NULL && pClient->conn->cbBuffer==0);
1690 CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
1691
1692 pClient->conn->pBuffer = pBuffer;
1693 pClient->conn->cbBuffer = cbBuffer;
1694 CRVBOXHGSMI_CMDDATA_SET(&pClient->conn->CmdData, pCmd, pHdr);
1695 rc = crVBoxServerInternalClientWriteRead(pClient);
1696 CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
1697 return rc;
1698 }
1699 else
1700 {
1701 crWarning("invalid number of args");
1702 rc = VERR_INVALID_PARAMETER;
1703 break;
1704 }
1705 break;
1706 }
1707
1708 case SHCRGL_GUEST_FN_INJECT:
1709 {
1710 crDebug(("svcCall: SHCRGL_GUEST_FN_INJECT\n"));
1711
1712 /* @todo: Verify */
1713 if (cParams == 1)
1714 {
1715 CRVBOXHGSMIINJECT *pFnCmd = (CRVBOXHGSMIINJECT*)pHdr;
1716 /* Fetch parameters. */
1717 uint32_t u32InjectClientID = pFnCmd->u32ClientID;
1718 VBOXVDMACMD_CHROMIUM_BUFFER *pBuf = &pCmd->aBuffers[1];
1719 uint32_t cbBuffer = pBuf->cbBuffer;
1720 uint8_t *pBuffer = VBOXCRHGSMI_PTR_SAFE(pBuf->offBuffer, cbBuffer, uint8_t);
1721
1722 if (cbHdr < sizeof (*pFnCmd))
1723 {
1724 crWarning("invalid inject cmd buffer size!");
1725 rc = VERR_INVALID_PARAMETER;
1726 break;
1727 }
1728
1729 CRASSERT(cbBuffer);
1730 if (!pBuffer)
1731 {
1732 crWarning("invalid buffer data received from guest!");
1733 rc = VERR_INVALID_PARAMETER;
1734 break;
1735 }
1736
1737 rc = crVBoxServerClientGet(u32InjectClientID, &pClient);
1738 if (RT_FAILURE(rc))
1739 {
1740 break;
1741 }
1742
1743 /* This should never fire unless we start to multithread */
1744 CRASSERT(pClient->conn->pBuffer==NULL && pClient->conn->cbBuffer==0);
1745 CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
1746
1747 pClient->conn->pBuffer = pBuffer;
1748 pClient->conn->cbBuffer = cbBuffer;
1749 CRVBOXHGSMI_CMDDATA_SET(&pClient->conn->CmdData, pCmd, pHdr);
1750 rc = crVBoxServerInternalClientWriteRead(pClient);
1751 CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
1752 return rc;
1753 }
1754
1755 crWarning("invalid number of args");
1756 rc = VERR_INVALID_PARAMETER;
1757 break;
1758 }
1759
1760 case SHCRGL_GUEST_FN_READ:
1761 {
1762 crDebug(("svcCall: SHCRGL_GUEST_FN_READ\n"));
1763
1764 /* @todo: Verify */
1765 if (cParams == 1)
1766 {
1767 CRVBOXHGSMIREAD *pFnCmd = (CRVBOXHGSMIREAD*)pHdr;
1768 VBOXVDMACMD_CHROMIUM_BUFFER *pBuf = &pCmd->aBuffers[1];
1769 /* Fetch parameters. */
1770 uint32_t cbBuffer = pBuf->cbBuffer;
1771 uint8_t *pBuffer = VBOXCRHGSMI_PTR_SAFE(pBuf->offBuffer, cbBuffer, uint8_t);
1772
1773 if (cbHdr < sizeof (*pFnCmd))
1774 {
1775 crWarning("invalid read cmd buffer size!");
1776 rc = VERR_INVALID_PARAMETER;
1777 break;
1778 }
1779
1780
1781 if (!pBuffer)
1782 {
1783 crWarning("invalid buffer data received from guest!");
1784 rc = VERR_INVALID_PARAMETER;
1785 break;
1786 }
1787
1788 rc = crVBoxServerClientGet(u32ClientID, &pClient);
1789 if (RT_FAILURE(rc))
1790 {
1791 break;
1792 }
1793
1794 CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
1795
1796 rc = crVBoxServerInternalClientRead(pClient, pBuffer, &cbBuffer);
1797
1798 /* Return the required buffer size always */
1799 pFnCmd->cbBuffer = cbBuffer;
1800
1801 CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
1802
1803 /* the read command is never pended, complete it right away */
1804 pHdr->result = rc;
1805 crServerCrHgsmiCmdComplete(pCmd, VINF_SUCCESS);
1806 return VINF_SUCCESS;
1807 }
1808
1809 crWarning("invalid number of args");
1810 rc = VERR_INVALID_PARAMETER;
1811 break;
1812 }
1813
1814 case SHCRGL_GUEST_FN_WRITE_READ:
1815 {
1816 crDebug(("svcCall: SHCRGL_GUEST_FN_WRITE_READ\n"));
1817
1818 /* @todo: Verify */
1819 if (cParams == 2)
1820 {
1821 CRVBOXHGSMIWRITEREAD *pFnCmd = (CRVBOXHGSMIWRITEREAD*)pHdr;
1822 VBOXVDMACMD_CHROMIUM_BUFFER *pBuf = &pCmd->aBuffers[1];
1823 VBOXVDMACMD_CHROMIUM_BUFFER *pWbBuf = &pCmd->aBuffers[2];
1824
1825 /* Fetch parameters. */
1826 uint32_t cbBuffer = pBuf->cbBuffer;
1827 uint8_t *pBuffer = VBOXCRHGSMI_PTR_SAFE(pBuf->offBuffer, cbBuffer, uint8_t);
1828
1829 uint32_t cbWriteback = pWbBuf->cbBuffer;
1830 char *pWriteback = VBOXCRHGSMI_PTR_SAFE(pWbBuf->offBuffer, cbWriteback, char);
1831
1832 if (cbHdr < sizeof (*pFnCmd))
1833 {
1834 crWarning("invalid write_read cmd buffer size!");
1835 rc = VERR_INVALID_PARAMETER;
1836 break;
1837 }
1838
1839
1840 CRASSERT(cbBuffer);
1841 if (!pBuffer)
1842 {
1843 crWarning("invalid write buffer data received from guest!");
1844 rc = VERR_INVALID_PARAMETER;
1845 break;
1846 }
1847
1848 CRASSERT(cbWriteback);
1849 if (!pWriteback)
1850 {
1851 crWarning("invalid writeback buffer data received from guest!");
1852 rc = VERR_INVALID_PARAMETER;
1853 break;
1854 }
1855 rc = crVBoxServerClientGet(u32ClientID, &pClient);
1856 if (RT_FAILURE(rc))
1857 {
1858 pHdr->result = rc;
1859 crServerCrHgsmiCmdComplete(pCmd, VINF_SUCCESS);
1860 return rc;
1861 }
1862
1863 /* This should never fire unless we start to multithread */
1864 CRASSERT(pClient->conn->pBuffer==NULL && pClient->conn->cbBuffer==0);
1865 CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
1866
1867 pClient->conn->pBuffer = pBuffer;
1868 pClient->conn->cbBuffer = cbBuffer;
1869 CRVBOXHGSMI_CMDDATA_SETWB(&pClient->conn->CmdData, pCmd, pHdr, pWriteback, cbWriteback, &pFnCmd->cbWriteback);
1870 rc = crVBoxServerInternalClientWriteRead(pClient);
1871 CRVBOXHGSMI_CMDDATA_ASSERT_CLEANED(&pClient->conn->CmdData);
1872 return rc;
1873 }
1874
1875 crWarning("invalid number of args");
1876 rc = VERR_INVALID_PARAMETER;
1877 break;
1878 }
1879
1880 case SHCRGL_GUEST_FN_SET_VERSION:
1881 {
1882 crWarning("invalid function");
1883 rc = VERR_NOT_IMPLEMENTED;
1884 break;
1885 }
1886
1887 case SHCRGL_GUEST_FN_SET_PID:
1888 {
1889 crWarning("invalid function");
1890 rc = VERR_NOT_IMPLEMENTED;
1891 break;
1892 }
1893
1894 default:
1895 {
1896 crWarning("invalid function");
1897 rc = VERR_NOT_IMPLEMENTED;
1898 break;
1899 }
1900
1901 }
1902
1903 /* we can be on fail only here */
1904 CRASSERT(RT_FAILURE(rc));
1905 pHdr->result = rc;
1906 crServerCrHgsmiCmdComplete(pCmd, VINF_SUCCESS);
1907 return rc;
1908}
1909
1910int32_t crVBoxServerCrHgsmiCtl(struct VBOXVDMACMD_CHROMIUM_CTL *pCtl, uint32_t cbCtl)
1911{
1912 int rc = VINF_SUCCESS;
1913
1914 switch (pCtl->enmType)
1915 {
1916 case VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP:
1917 {
1918 PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP pSetup = (PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP)pCtl;
1919 g_pvVRamBase = (uint8_t*)pSetup->pvVRamBase;
1920 g_cbVRam = pSetup->cbVRam;
1921 rc = VINF_SUCCESS;
1922 break;
1923 }
1924 case VBOXVDMACMD_CHROMIUM_CTL_TYPE_SAVESTATE_BEGIN:
1925 case VBOXVDMACMD_CHROMIUM_CTL_TYPE_SAVESTATE_END:
1926 rc = VINF_SUCCESS;
1927 break;
1928 case VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP_COMPLETION:
1929 {
1930 PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_COMPLETION pSetup = (PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_COMPLETION)pCtl;
1931 g_hCrHgsmiCompletion = pSetup->hCompletion;
1932 g_pfnCrHgsmiCompletion = pSetup->pfnCompletion;
1933 rc = VINF_SUCCESS;
1934 break;
1935 }
1936 default:
1937 AssertMsgFailed(("invalid param %d", pCtl->enmType));
1938 rc = VERR_INVALID_PARAMETER;
1939 }
1940
1941 /* NOTE: Control commands can NEVER be pended here, this is why its a task of a caller (Main)
1942 * to complete them accordingly.
1943 * This approach allows using host->host and host->guest commands in the same way here
1944 * making the command completion to be the responsibility of the command originator.
1945 * E.g. ctl commands can be both Hgcm Host synchronous commands that do not require completion at all,
1946 * or Hgcm Host Fast Call commands that do require completion. All this details are hidden here */
1947 return rc;
1948}
1949#endif
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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