VirtualBox

source: vbox/trunk/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp@ 49474

Last change on this file since 49474 was 49474, checked in by vboxsync, 11 years ago

crOpenGL: some host bits for buffer-based command submission

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 41.9 KB
Line 
1/* $Id: crservice.cpp 49474 2013-11-14 06:49:54Z vboxsync $ */
2
3/** @file
4 * VBox crOpenGL: Host service entry points.
5 */
6
7/*
8 * Copyright (C) 2006-2012 Oracle Corporation
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 */
18
19#define __STDC_CONSTANT_MACROS /* needed for a definition in iprt/string.h */
20
21#define LOG_GROUP LOG_GROUP_SHARED_CROPENGL
22
23#include <iprt/assert.h>
24#include <iprt/asm.h>
25#include <iprt/critsect.h>
26#include <iprt/mem.h>
27#include <iprt/semaphore.h>
28#include <iprt/stream.h>
29#include <iprt/string.h>
30#include <iprt/thread.h>
31
32#include <VBox/hgcmsvc.h>
33#include <VBox/log.h>
34#include <VBox/com/ErrorInfo.h>
35#include <VBox/com/VirtualBox.h>
36#include <VBox/com/errorprint.h>
37#include <VBox/HostServices/VBoxCrOpenGLSvc.h>
38#include <VBox/vmm/ssm.h>
39
40#include "cr_mem.h"
41#include "cr_server.h"
42
43PVBOXHGCMSVCHELPERS g_pHelpers;
44static IConsole* g_pConsole = NULL;
45static PVM g_pVM = NULL;
46
47#ifndef RT_OS_WINDOWS
48# define DWORD int
49# define WINAPI
50#endif
51
52static const char* gszVBoxOGLSSMMagic = "***OpenGL state data***";
53
54/* Used to process guest calls exceeding maximum allowed HGCM call size in a sequence of smaller calls */
55typedef struct _CRVBOXSVCBUFFER_t {
56 uint32_t uiId;
57 uint32_t uiSize;
58 void* pData;
59 _CRVBOXSVCBUFFER_t *pNext, *pPrev;
60} CRVBOXSVCBUFFER_t;
61
62static CRVBOXSVCBUFFER_t *g_pCRVBoxSVCBuffers = NULL;
63static uint32_t g_CRVBoxSVCBufferID = 0;
64
65/* svcPresentFBO related data */
66typedef struct _CRVBOXSVCPRESENTFBOCMD_t {
67 void *pData;
68 int32_t screenId, x, y, w, h;
69 _CRVBOXSVCPRESENTFBOCMD_t *pNext;
70} CRVBOXSVCPRESENTFBOCMD_t, *PCRVBOXSVCPRESENTFBOCMD_t;
71
72typedef struct _CRVBOXSVCPRESENTFBO_t {
73 PCRVBOXSVCPRESENTFBOCMD_t pQueueHead, pQueueTail; /* Head/Tail of FIFO cmds queue */
74 RTCRITSECT hQueueLock; /* Queue lock */
75 RTTHREAD hWorkerThread; /* Worker thread */
76 bool volatile bShutdownWorker; /* Shutdown flag */
77 RTSEMEVENT hEventProcess; /* Signalled when worker thread should process data or exit */
78} CRVBOXSVCPRESENTFBO_t;
79
80static CRVBOXSVCPRESENTFBO_t g_SvcPresentFBO;
81
82/* Schedule a call to a separate worker thread to avoid deadlock on EMT thread when the screen configuration changes
83 and we're processing crServerPresentFBO caused by guest application command.
84 To avoid unnecessary memcpy, worker thread frees the data passed.
85*/
86static DECLCALLBACK(void) svcPresentFBO(void *data, int32_t screenId, int32_t x, int32_t y, uint32_t w, uint32_t h)
87{
88 PCRVBOXSVCPRESENTFBOCMD_t pCmd;
89
90 pCmd = (PCRVBOXSVCPRESENTFBOCMD_t) RTMemAlloc(sizeof(CRVBOXSVCPRESENTFBOCMD_t));
91 if (!pCmd)
92 {
93 LogRel(("SHARED_CROPENGL svcPresentFBO: not enough memory (%d)\n", sizeof(CRVBOXSVCPRESENTFBOCMD_t)));
94 return;
95 }
96 pCmd->pData = data;
97 pCmd->screenId = screenId;
98 pCmd->x = x;
99 pCmd->y = y;
100 pCmd->w = w;
101 pCmd->h = h;
102 pCmd->pNext = NULL;
103
104 RTCritSectEnter(&g_SvcPresentFBO.hQueueLock);
105
106 if (g_SvcPresentFBO.pQueueTail)
107 {
108 g_SvcPresentFBO.pQueueTail->pNext = pCmd;
109 }
110 else
111 {
112 Assert(!g_SvcPresentFBO.pQueueHead);
113 g_SvcPresentFBO.pQueueHead = pCmd;
114 }
115 g_SvcPresentFBO.pQueueTail = pCmd;
116
117 RTCritSectLeave(&g_SvcPresentFBO.hQueueLock);
118
119 RTSemEventSignal(g_SvcPresentFBO.hEventProcess);
120}
121
122static DECLCALLBACK(int) svcPresentFBOWorkerThreadProc(RTTHREAD ThreadSelf, void *pvUser)
123{
124 int rc = VINF_SUCCESS;
125 PCRVBOXSVCPRESENTFBOCMD_t pCmd;
126
127 Log(("SHARED_CROPENGL svcPresentFBOWorkerThreadProc started\n"));
128
129 for (;;)
130 {
131 rc = RTSemEventWait(g_SvcPresentFBO.hEventProcess, RT_INDEFINITE_WAIT);
132 AssertRCReturn(rc, rc);
133
134 if (g_SvcPresentFBO.bShutdownWorker)
135 {
136 break;
137 }
138
139 // @todo use critsect only to fetch the list and update the g_SvcPresentFBO's pQueueHead and pQueueTail.
140 rc = RTCritSectEnter(&g_SvcPresentFBO.hQueueLock);
141 AssertRCReturn(rc, rc);
142
143 pCmd = g_SvcPresentFBO.pQueueHead;
144 while (pCmd)
145 {
146 ComPtr<IDisplay> pDisplay;
147
148 /*remove from queue*/
149 g_SvcPresentFBO.pQueueHead = pCmd->pNext;
150 if (!g_SvcPresentFBO.pQueueHead)
151 {
152 g_SvcPresentFBO.pQueueTail = NULL;
153 }
154
155 CHECK_ERROR_RET(g_pConsole, COMGETTER(Display)(pDisplay.asOutParam()), rc);
156
157 RTCritSectLeave(&g_SvcPresentFBO.hQueueLock);
158
159 CHECK_ERROR_RET(pDisplay, DrawToScreen(pCmd->screenId, (BYTE*)pCmd->pData, pCmd->x, pCmd->y, pCmd->w, pCmd->h), rc);
160
161 crFree(pCmd->pData);
162 RTMemFree(pCmd);
163
164 rc = RTCritSectEnter(&g_SvcPresentFBO.hQueueLock);
165 AssertRCReturn(rc, rc);
166 pCmd = g_SvcPresentFBO.pQueueHead;
167 }
168
169 RTCritSectLeave(&g_SvcPresentFBO.hQueueLock);
170 }
171
172 Log(("SHARED_CROPENGL svcPresentFBOWorkerThreadProc finished\n"));
173
174 return rc;
175}
176
177static int svcPresentFBOInit(void)
178{
179 int rc = VINF_SUCCESS;
180
181 g_SvcPresentFBO.pQueueHead = NULL;
182 g_SvcPresentFBO.pQueueTail = NULL;
183 g_SvcPresentFBO.bShutdownWorker = false;
184
185 rc = RTCritSectInit(&g_SvcPresentFBO.hQueueLock);
186 AssertRCReturn(rc, rc);
187
188 rc = RTSemEventCreate(&g_SvcPresentFBO.hEventProcess);
189 AssertRCReturn(rc, rc);
190
191 rc = RTThreadCreate(&g_SvcPresentFBO.hWorkerThread, svcPresentFBOWorkerThreadProc, NULL, 0,
192 RTTHREADTYPE_IO, RTTHREADFLAGS_WAITABLE, "OpenGLWorker");
193 AssertRCReturn(rc, rc);
194
195 crVBoxServerSetPresentFBOCB(svcPresentFBO);
196
197 return rc;
198}
199
200static int svcPresentFBOTearDown(void)
201{
202 int rc = VINF_SUCCESS;
203 PCRVBOXSVCPRESENTFBOCMD_t pQueue, pTmp;
204
205 ASMAtomicWriteBool(&g_SvcPresentFBO.bShutdownWorker, true);
206 RTSemEventSignal(g_SvcPresentFBO.hEventProcess);
207 rc = RTThreadWait(g_SvcPresentFBO.hWorkerThread, 5000, NULL);
208 AssertRCReturn(rc, rc);
209
210 RTCritSectDelete(&g_SvcPresentFBO.hQueueLock);
211 RTSemEventDestroy(g_SvcPresentFBO.hEventProcess);
212
213 pQueue = g_SvcPresentFBO.pQueueHead;
214 while (pQueue)
215 {
216 pTmp = pQueue->pNext;
217 crFree(pQueue->pData);
218 RTMemFree(pQueue);
219 pQueue = pTmp;
220 }
221 g_SvcPresentFBO.pQueueHead = NULL;
222 g_SvcPresentFBO.pQueueTail = NULL;
223
224 return rc;
225}
226
227static DECLCALLBACK(void) svcNotifyEventCB(int32_t screenId, uint32_t uEvent, void*pvData)
228{
229 ComPtr<IDisplay> pDisplay;
230 ComPtr<IFramebuffer> pFramebuffer;
231 LONG xo, yo;
232
233 if (!g_pConsole)
234 {
235 crWarning("Console not defined!");
236 return;
237 }
238
239 CHECK_ERROR2_STMT(g_pConsole, COMGETTER(Display)(pDisplay.asOutParam()), return);
240
241 CHECK_ERROR2_STMT(pDisplay, GetFramebuffer(screenId, pFramebuffer.asOutParam(), &xo, &yo), return);
242
243 if (!pFramebuffer)
244 return;
245
246 pFramebuffer->Notify3DEvent(uEvent, (BYTE*)pvData);
247}
248
249
250static DECLCALLBACK(int) svcUnload (void *)
251{
252 int rc = VINF_SUCCESS;
253
254 Log(("SHARED_CROPENGL svcUnload\n"));
255
256 crVBoxServerTearDown();
257
258 svcPresentFBOTearDown();
259
260 return rc;
261}
262
263static DECLCALLBACK(int) svcConnect (void *, uint32_t u32ClientID, void *pvClient)
264{
265 int rc = VINF_SUCCESS;
266
267 NOREF(pvClient);
268
269 Log(("SHARED_CROPENGL svcConnect: u32ClientID = %d\n", u32ClientID));
270
271 rc = crVBoxServerAddClient(u32ClientID);
272
273 return rc;
274}
275
276static DECLCALLBACK(int) svcDisconnect (void *, uint32_t u32ClientID, void *pvClient)
277{
278 int rc = VINF_SUCCESS;
279
280 NOREF(pvClient);
281
282 Log(("SHARED_CROPENGL svcDisconnect: u32ClientID = %d\n", u32ClientID));
283
284 crVBoxServerRemoveClient(u32ClientID);
285
286 return rc;
287}
288
289static DECLCALLBACK(int) svcSaveState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
290{
291 int rc = VINF_SUCCESS;
292
293 NOREF(pvClient);
294
295 Log(("SHARED_CROPENGL svcSaveState: u32ClientID = %d\n", u32ClientID));
296
297 /* Start*/
298 rc = SSMR3PutStrZ(pSSM, gszVBoxOGLSSMMagic);
299 AssertRCReturn(rc, rc);
300
301 /* Version */
302 rc = SSMR3PutU32(pSSM, (uint32_t) SHCROGL_SSM_VERSION);
303 AssertRCReturn(rc, rc);
304
305 /* The state itself */
306 rc = crVBoxServerSaveState(pSSM);
307 AssertRCReturn(rc, rc);
308
309 /* Save svc buffers info */
310 {
311 CRVBOXSVCBUFFER_t *pBuffer = g_pCRVBoxSVCBuffers;
312
313 rc = SSMR3PutU32(pSSM, g_CRVBoxSVCBufferID);
314 AssertRCReturn(rc, rc);
315
316 while (pBuffer)
317 {
318 rc = SSMR3PutU32(pSSM, pBuffer->uiId);
319 AssertRCReturn(rc, rc);
320
321 rc = SSMR3PutU32(pSSM, pBuffer->uiSize);
322 AssertRCReturn(rc, rc);
323
324 rc = SSMR3PutMem(pSSM, pBuffer->pData, pBuffer->uiSize);
325 AssertRCReturn(rc, rc);
326
327 pBuffer = pBuffer->pNext;
328 }
329
330 rc = SSMR3PutU32(pSSM, 0);
331 AssertRCReturn(rc, rc);
332 }
333
334 /* End */
335 rc = SSMR3PutStrZ(pSSM, gszVBoxOGLSSMMagic);
336 AssertRCReturn(rc, rc);
337
338 return VINF_SUCCESS;
339}
340
341static DECLCALLBACK(int) svcLoadState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
342{
343 int rc = VINF_SUCCESS;
344
345 NOREF(pvClient);
346
347 Log(("SHARED_CROPENGL svcLoadState: u32ClientID = %d\n", u32ClientID));
348
349 char psz[2000];
350 uint32_t ui32;
351
352 /* Start of data */
353 rc = SSMR3GetStrZEx(pSSM, psz, 2000, NULL);
354 AssertRCReturn(rc, rc);
355 if (strcmp(gszVBoxOGLSSMMagic, psz))
356 return VERR_SSM_UNEXPECTED_DATA;
357
358 /* Version */
359 rc = SSMR3GetU32(pSSM, &ui32);
360 AssertRCReturn(rc, rc);
361
362 /* The state itself */
363 rc = crVBoxServerLoadState(pSSM, ui32);
364
365 if (rc==VERR_SSM_DATA_UNIT_FORMAT_CHANGED && ui32!=SHCROGL_SSM_VERSION)
366 {
367 LogRel(("SHARED_CROPENGL svcLoadState: unsupported save state version %d\n", ui32));
368
369 /*@todo ugly hack, as we don't know size of stored opengl data try to read untill end of opengl data marker*/
370 /*VboxSharedCrOpenGL isn't last hgcm service now, so can't use SSMR3SkipToEndOfUnit*/
371 {
372 const char *pMatch = &gszVBoxOGLSSMMagic[0];
373 char current;
374
375 while (*pMatch)
376 {
377 rc = SSMR3GetS8(pSSM, (int8_t*)&current);
378 AssertRCReturn(rc, rc);
379
380 if (current==*pMatch)
381 {
382 pMatch++;
383 }
384 else
385 {
386 pMatch = &gszVBoxOGLSSMMagic[0];
387 }
388 }
389 }
390
391 return VINF_SUCCESS;
392 }
393 AssertRCReturn(rc, rc);
394
395 /* Load svc buffers info */
396 if (ui32>=24)
397 {
398 uint32_t uiId;
399
400 rc = SSMR3GetU32(pSSM, &g_CRVBoxSVCBufferID);
401 AssertRCReturn(rc, rc);
402
403 rc = SSMR3GetU32(pSSM, &uiId);
404 AssertRCReturn(rc, rc);
405
406 while (uiId)
407 {
408 CRVBOXSVCBUFFER_t *pBuffer = (CRVBOXSVCBUFFER_t *) RTMemAlloc(sizeof(CRVBOXSVCBUFFER_t));
409 if (!pBuffer)
410 {
411 return VERR_NO_MEMORY;
412 }
413 pBuffer->uiId = uiId;
414
415 rc = SSMR3GetU32(pSSM, &pBuffer->uiSize);
416 AssertRCReturn(rc, rc);
417
418 pBuffer->pData = RTMemAlloc(pBuffer->uiSize);
419 if (!pBuffer->pData)
420 {
421 RTMemFree(pBuffer);
422 return VERR_NO_MEMORY;
423 }
424
425 rc = SSMR3GetMem(pSSM, pBuffer->pData, pBuffer->uiSize);
426 AssertRCReturn(rc, rc);
427
428 pBuffer->pNext = g_pCRVBoxSVCBuffers;
429 pBuffer->pPrev = NULL;
430 if (g_pCRVBoxSVCBuffers)
431 {
432 g_pCRVBoxSVCBuffers->pPrev = pBuffer;
433 }
434 g_pCRVBoxSVCBuffers = pBuffer;
435
436 rc = SSMR3GetU32(pSSM, &uiId);
437 AssertRCReturn(rc, rc);
438 }
439 }
440
441 /* End of data */
442 rc = SSMR3GetStrZEx(pSSM, psz, 2000, NULL);
443 AssertRCReturn(rc, rc);
444 if (strcmp(gszVBoxOGLSSMMagic, psz))
445 return VERR_SSM_UNEXPECTED_DATA;
446
447 return VINF_SUCCESS;
448}
449
450static void svcClientVersionUnsupported(uint32_t minor, uint32_t major)
451{
452 LogRel(("SHARED_CROPENGL: unsupported client version %d.%d\n", minor, major));
453
454 /*MS's opengl32 tries to load our ICD around 30 times on failure...this is to prevent unnecessary spam*/
455 static int shown = 0;
456
457 if (g_pVM && !shown)
458 {
459 VMSetRuntimeError(g_pVM, VMSETRTERR_FLAGS_NO_WAIT, "3DSupportIncompatibleAdditions",
460 "An attempt by the virtual machine to use hardware 3D acceleration failed. "
461 "The version of the Guest Additions installed in the virtual machine does not match the "
462 "version of VirtualBox on the host. Please install appropriate Guest Additions to fix this issue");
463 shown = 1;
464 }
465}
466
467static CRVBOXSVCBUFFER_t* svcGetBuffer(uint32_t iBuffer, uint32_t cbBufferSize)
468{
469 CRVBOXSVCBUFFER_t* pBuffer;
470
471 if (iBuffer)
472 {
473 pBuffer = g_pCRVBoxSVCBuffers;
474 while (pBuffer)
475 {
476 if (pBuffer->uiId == iBuffer)
477 {
478 if (cbBufferSize && pBuffer->uiSize!=cbBufferSize)
479 {
480 static int shown=0;
481
482 if (shown<20)
483 {
484 shown++;
485 LogRel(("SHARED_CROPENGL svcGetBuffer: invalid buffer(%i) size %i instead of %i\n",
486 iBuffer, pBuffer->uiSize, cbBufferSize));
487 }
488 return NULL;
489 }
490 return pBuffer;
491 }
492 pBuffer = pBuffer->pNext;
493 }
494 return NULL;
495 }
496 else /*allocate new buffer*/
497 {
498 pBuffer = (CRVBOXSVCBUFFER_t*) RTMemAlloc(sizeof(CRVBOXSVCBUFFER_t));
499 if (pBuffer)
500 {
501 pBuffer->pData = RTMemAlloc(cbBufferSize);
502 if (!pBuffer->pData)
503 {
504 LogRel(("SHARED_CROPENGL svcGetBuffer: not enough memory (%d)\n", cbBufferSize));
505 RTMemFree(pBuffer);
506 return NULL;
507 }
508 pBuffer->uiId = ++g_CRVBoxSVCBufferID;
509 if (!pBuffer->uiId)
510 {
511 pBuffer->uiId = ++g_CRVBoxSVCBufferID;
512 }
513 Assert(pBuffer->uiId);
514 pBuffer->uiSize = cbBufferSize;
515 pBuffer->pPrev = NULL;
516 pBuffer->pNext = g_pCRVBoxSVCBuffers;
517 if (g_pCRVBoxSVCBuffers)
518 {
519 g_pCRVBoxSVCBuffers->pPrev = pBuffer;
520 }
521 g_pCRVBoxSVCBuffers = pBuffer;
522 }
523 else
524 {
525 LogRel(("SHARED_CROPENGL svcGetBuffer: not enough memory (%d)\n", sizeof(CRVBOXSVCBUFFER_t)));
526 }
527 return pBuffer;
528 }
529}
530
531static void svcFreeBuffer(CRVBOXSVCBUFFER_t* pBuffer)
532{
533 Assert(pBuffer);
534
535 if (pBuffer->pPrev)
536 {
537 pBuffer->pPrev->pNext = pBuffer->pNext;
538 }
539 else
540 {
541 Assert(pBuffer==g_pCRVBoxSVCBuffers);
542 g_pCRVBoxSVCBuffers = pBuffer->pNext;
543 }
544
545 if (pBuffer->pNext)
546 {
547 pBuffer->pNext->pPrev = pBuffer->pPrev;
548 }
549
550 RTMemFree(pBuffer->pData);
551 RTMemFree(pBuffer);
552}
553
554static DECLCALLBACK(void) svcCall (void *, VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, void *pvClient, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
555{
556 int rc = VINF_SUCCESS;
557
558 NOREF(pvClient);
559
560 Log(("SHARED_CROPENGL svcCall: u32ClientID = %d, fn = %d, cParms = %d, pparms = %d\n", u32ClientID, u32Function, cParms, paParms));
561
562#ifdef DEBUG
563 uint32_t i;
564
565 for (i = 0; i < cParms; i++)
566 {
567 /** @todo parameters other than 32 bit */
568 Log((" pparms[%d]: type %d value %d\n", i, paParms[i].type, paParms[i].u.uint32));
569 }
570#endif
571
572 switch (u32Function)
573 {
574 case SHCRGL_GUEST_FN_WRITE:
575 {
576 Log(("svcCall: SHCRGL_GUEST_FN_WRITE\n"));
577
578 /* Verify parameter count and types. */
579 if (cParms != SHCRGL_CPARMS_WRITE)
580 {
581 rc = VERR_INVALID_PARAMETER;
582 }
583 else
584 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* pBuffer */
585 )
586 {
587 rc = VERR_INVALID_PARAMETER;
588 }
589 else
590 {
591 /* Fetch parameters. */
592 uint8_t *pBuffer = (uint8_t *)paParms[0].u.pointer.addr;
593 uint32_t cbBuffer = paParms[0].u.pointer.size;
594
595 /* Execute the function. */
596 rc = crVBoxServerClientWrite(u32ClientID, pBuffer, cbBuffer);
597 if (!RT_SUCCESS(rc))
598 {
599 Assert(VERR_NOT_SUPPORTED==rc);
600 svcClientVersionUnsupported(0, 0);
601 }
602
603 }
604 break;
605 }
606
607 case SHCRGL_GUEST_FN_INJECT:
608 {
609 Log(("svcCall: SHCRGL_GUEST_FN_INJECT\n"));
610
611 /* Verify parameter count and types. */
612 if (cParms != SHCRGL_CPARMS_INJECT)
613 {
614 rc = VERR_INVALID_PARAMETER;
615 }
616 else
617 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* u32ClientID */
618 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* pBuffer */
619 )
620 {
621 rc = VERR_INVALID_PARAMETER;
622 }
623 else
624 {
625 /* Fetch parameters. */
626 uint32_t u32InjectClientID = paParms[0].u.uint32;
627 uint8_t *pBuffer = (uint8_t *)paParms[1].u.pointer.addr;
628 uint32_t cbBuffer = paParms[1].u.pointer.size;
629
630 /* Execute the function. */
631 rc = crVBoxServerClientWrite(u32InjectClientID, pBuffer, cbBuffer);
632 if (!RT_SUCCESS(rc))
633 {
634 if (VERR_NOT_SUPPORTED==rc)
635 {
636 svcClientVersionUnsupported(0, 0);
637 }
638 else
639 {
640 crWarning("SHCRGL_GUEST_FN_INJECT failed to inject for %i from %i", u32InjectClientID, u32ClientID);
641 }
642 }
643 }
644 break;
645 }
646
647 case SHCRGL_GUEST_FN_READ:
648 {
649 Log(("svcCall: SHCRGL_GUEST_FN_READ\n"));
650
651 /* Verify parameter count and types. */
652 if (cParms != SHCRGL_CPARMS_READ)
653 {
654 rc = VERR_INVALID_PARAMETER;
655 }
656 else
657 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* pBuffer */
658 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* cbBuffer */
659 )
660 {
661 rc = VERR_INVALID_PARAMETER;
662 }
663
664 /* Fetch parameters. */
665 uint8_t *pBuffer = (uint8_t *)paParms[0].u.pointer.addr;
666 uint32_t cbBuffer = paParms[0].u.pointer.size;
667
668 /* Execute the function. */
669 rc = crVBoxServerClientRead(u32ClientID, pBuffer, &cbBuffer);
670
671 if (RT_SUCCESS(rc))
672 {
673 /* Update parameters.*/
674 paParms[0].u.pointer.size = cbBuffer; //@todo guest doesn't see this change somehow?
675 } else if (VERR_NOT_SUPPORTED==rc)
676 {
677 svcClientVersionUnsupported(0, 0);
678 }
679
680 /* Return the required buffer size always */
681 paParms[1].u.uint32 = cbBuffer;
682
683 break;
684 }
685
686 case SHCRGL_GUEST_FN_WRITE_READ:
687 {
688 Log(("svcCall: SHCRGL_GUEST_FN_WRITE_READ\n"));
689
690 /* Verify parameter count and types. */
691 if (cParms != SHCRGL_CPARMS_WRITE_READ)
692 {
693 rc = VERR_INVALID_PARAMETER;
694 }
695 else
696 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* pBuffer */
697 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* pWriteback */
698 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* cbWriteback */
699 )
700 {
701 rc = VERR_INVALID_PARAMETER;
702 }
703 else
704 {
705 /* Fetch parameters. */
706 uint8_t *pBuffer = (uint8_t *)paParms[0].u.pointer.addr;
707 uint32_t cbBuffer = paParms[0].u.pointer.size;
708
709 uint8_t *pWriteback = (uint8_t *)paParms[1].u.pointer.addr;
710 uint32_t cbWriteback = paParms[1].u.pointer.size;
711
712 /* Execute the function. */
713 rc = crVBoxServerClientWrite(u32ClientID, pBuffer, cbBuffer);
714 if (!RT_SUCCESS(rc))
715 {
716 Assert(VERR_NOT_SUPPORTED==rc);
717 svcClientVersionUnsupported(0, 0);
718 }
719
720 rc = crVBoxServerClientRead(u32ClientID, pWriteback, &cbWriteback);
721
722 if (RT_SUCCESS(rc))
723 {
724 /* Update parameters.*/
725 paParms[1].u.pointer.size = cbWriteback;
726 }
727 /* Return the required buffer size always */
728 paParms[2].u.uint32 = cbWriteback;
729 }
730
731 break;
732 }
733
734 case SHCRGL_GUEST_FN_SET_VERSION:
735 {
736 Log(("svcCall: SHCRGL_GUEST_FN_SET_VERSION\n"));
737
738 /* Verify parameter count and types. */
739 if (cParms != SHCRGL_CPARMS_SET_VERSION)
740 {
741 rc = VERR_INVALID_PARAMETER;
742 }
743 else
744 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* vMajor */
745 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* vMinor */
746 )
747 {
748 rc = VERR_INVALID_PARAMETER;
749 }
750 else
751 {
752 /* Fetch parameters. */
753 uint32_t vMajor = paParms[0].u.uint32;
754 uint32_t vMinor = paParms[1].u.uint32;
755
756 /* Execute the function. */
757 rc = crVBoxServerClientSetVersion(u32ClientID, vMajor, vMinor);
758
759 if (!RT_SUCCESS(rc))
760 {
761 svcClientVersionUnsupported(vMajor, vMinor);
762 }
763 }
764
765 break;
766 }
767
768 case SHCRGL_GUEST_FN_SET_PID:
769 {
770 Log(("svcCall: SHCRGL_GUEST_FN_SET_PID\n"));
771
772 /* Verify parameter count and types. */
773 if (cParms != SHCRGL_CPARMS_SET_PID)
774 {
775 rc = VERR_INVALID_PARAMETER;
776 }
777 else
778 if (paParms[0].type != VBOX_HGCM_SVC_PARM_64BIT)
779 {
780 rc = VERR_INVALID_PARAMETER;
781 }
782 else
783 {
784 /* Fetch parameters. */
785 uint64_t pid = paParms[0].u.uint64;
786
787 /* Execute the function. */
788 rc = crVBoxServerClientSetPID(u32ClientID, pid);
789 }
790
791 break;
792 }
793
794 case SHCRGL_GUEST_FN_WRITE_BUFFER:
795 {
796 Log(("svcCall: SHCRGL_GUEST_FN_WRITE_BUFFER\n"));
797 /* Verify parameter count and types. */
798 if (cParms != SHCRGL_CPARMS_WRITE_BUFFER)
799 {
800 rc = VERR_INVALID_PARAMETER;
801 }
802 else
803 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /*iBufferID*/
804 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /*cbBufferSize*/
805 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /*ui32Offset*/
806 || paParms[3].type != VBOX_HGCM_SVC_PARM_PTR /*pBuffer*/
807 )
808 {
809 rc = VERR_INVALID_PARAMETER;
810 }
811 else
812 {
813 /* Fetch parameters. */
814 uint32_t iBuffer = paParms[0].u.uint32;
815 uint32_t cbBufferSize = paParms[1].u.uint32;
816 uint32_t ui32Offset = paParms[2].u.uint32;
817 uint8_t *pBuffer = (uint8_t *)paParms[3].u.pointer.addr;
818 uint32_t cbBuffer = paParms[3].u.pointer.size;
819
820 /* Execute the function. */
821 CRVBOXSVCBUFFER_t *pSvcBuffer = svcGetBuffer(iBuffer, cbBufferSize);
822 if (!pSvcBuffer || ((uint64_t)ui32Offset+cbBuffer)>cbBufferSize)
823 {
824 rc = VERR_INVALID_PARAMETER;
825 }
826 else
827 {
828 memcpy((void*)((uintptr_t)pSvcBuffer->pData+ui32Offset), pBuffer, cbBuffer);
829
830 /* Return the buffer id */
831 paParms[0].u.uint32 = pSvcBuffer->uiId;
832 }
833 }
834
835 break;
836 }
837
838 case SHCRGL_GUEST_FN_WRITE_READ_BUFFERED:
839 {
840 Log(("svcCall: SHCRGL_GUEST_FN_WRITE_READ_BUFFERED\n"));
841
842 /* Verify parameter count and types. */
843 if (cParms != SHCRGL_CPARMS_WRITE_READ_BUFFERED)
844 {
845 rc = VERR_INVALID_PARAMETER;
846 }
847 else
848 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* iBufferID */
849 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* pWriteback */
850 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* cbWriteback */
851 || !paParms[0].u.uint32 /*iBufferID can't be 0 here*/
852 )
853 {
854 rc = VERR_INVALID_PARAMETER;
855 }
856 else
857 {
858 /* Fetch parameters. */
859 uint32_t iBuffer = paParms[0].u.uint32;
860 uint8_t *pWriteback = (uint8_t *)paParms[1].u.pointer.addr;
861 uint32_t cbWriteback = paParms[1].u.pointer.size;
862
863 CRVBOXSVCBUFFER_t *pSvcBuffer = svcGetBuffer(iBuffer, 0);
864 if (!pSvcBuffer)
865 {
866 LogRel(("SHARED_CROPENGL svcCall(WRITE_READ_BUFFERED): invalid buffer (%d)\n", iBuffer));
867 rc = VERR_INVALID_PARAMETER;
868 break;
869 }
870
871 uint8_t *pBuffer = (uint8_t *)pSvcBuffer->pData;
872 uint32_t cbBuffer = pSvcBuffer->uiSize;
873
874 /* Execute the function. */
875 rc = crVBoxServerClientWrite(u32ClientID, pBuffer, cbBuffer);
876 if (!RT_SUCCESS(rc))
877 {
878 Assert(VERR_NOT_SUPPORTED==rc);
879 svcClientVersionUnsupported(0, 0);
880 }
881
882 rc = crVBoxServerClientRead(u32ClientID, pWriteback, &cbWriteback);
883
884 if (RT_SUCCESS(rc))
885 {
886 /* Update parameters.*/
887 paParms[1].u.pointer.size = cbWriteback;
888 }
889 /* Return the required buffer size always */
890 paParms[2].u.uint32 = cbWriteback;
891
892 svcFreeBuffer(pSvcBuffer);
893 }
894
895 break;
896 }
897
898 case SHCRGL_GUEST_FN_GET_CAPS:
899 {
900 Log(("svcCall: SHCRGL_GUEST_FN_GET_CAPS\n"));
901
902 /* Verify parameter count and types. */
903 if (cParms != SHCRGL_CPARMS_GET_CAPS)
904 {
905 rc = VERR_INVALID_PARAMETER;
906 }
907 else
908 if (paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT)
909 {
910 rc = VERR_INVALID_PARAMETER;
911 }
912 else
913 {
914 /* Execute the function. */
915 rc = crVBoxServerClientGetCaps(u32ClientID, &paParms[0].u.uint32);
916 AssertRC(rc);
917 }
918
919 break;
920 }
921
922 default:
923 {
924 rc = VERR_NOT_IMPLEMENTED;
925 }
926 }
927
928
929 LogFlow(("svcCall: rc = %Rrc\n", rc));
930
931 g_pHelpers->pfnCallComplete (callHandle, rc);
932}
933
934/*
935 * We differentiate between a function handler for the guest and one for the host.
936 */
937static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
938{
939 int rc = VINF_SUCCESS;
940
941 Log(("SHARED_CROPENGL svcHostCall: fn = %d, cParms = %d, pparms = %d\n", u32Function, cParms, paParms));
942
943#ifdef DEBUG
944 uint32_t i;
945
946 for (i = 0; i < cParms; i++)
947 {
948 /** @todo parameters other than 32 bit */
949 Log((" pparms[%d]: type %d value %d\n", i, paParms[i].type, paParms[i].u.uint32));
950 }
951#endif
952
953 switch (u32Function)
954 {
955 case SHCRGL_HOST_FN_CRCMD_NOTIFY_CMDS:
956 {
957 rc = crVBoxServerCrCmdNotifyCmds();
958 } break;
959#ifdef VBOX_WITH_CRHGSMI
960 case SHCRGL_HOST_FN_CRHGSMI_CMD:
961 {
962 Assert(cParms == 1 && paParms[0].type == VBOX_HGCM_SVC_PARM_PTR);
963 if (cParms == 1 && paParms[0].type == VBOX_HGCM_SVC_PARM_PTR)
964 {
965 rc = crVBoxServerCrHgsmiCmd((PVBOXVDMACMD_CHROMIUM_CMD)paParms[0].u.pointer.addr, paParms[0].u.pointer.size);
966 if (VERR_NOT_SUPPORTED == rc)
967 {
968 svcClientVersionUnsupported(0, 0);
969 }
970 }
971 else
972 rc = VERR_INVALID_PARAMETER;
973 } break;
974 case SHCRGL_HOST_FN_CRHGSMI_CTL:
975 {
976 Assert(cParms == 1 && paParms[0].type == VBOX_HGCM_SVC_PARM_PTR);
977 if (cParms == 1 && paParms[0].type == VBOX_HGCM_SVC_PARM_PTR)
978 rc = crVBoxServerCrHgsmiCtl((PVBOXVDMACMD_CHROMIUM_CTL)paParms[0].u.pointer.addr, paParms[0].u.pointer.size);
979 else
980 rc = VERR_INVALID_PARAMETER;
981 } break;
982#endif
983 case SHCRGL_HOST_FN_SET_CONSOLE:
984 {
985 Log(("svcCall: SHCRGL_HOST_FN_SET_DISPLAY\n"));
986
987 /* Verify parameter count and types. */
988 if (cParms != SHCRGL_CPARMS_SET_CONSOLE)
989 {
990 rc = VERR_INVALID_PARAMETER;
991 }
992 else if (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)
993 {
994 rc = VERR_INVALID_PARAMETER;
995 }
996 else
997 {
998 /* Fetch parameters. */
999 IConsole* pConsole = (IConsole*)paParms[0].u.pointer.addr;
1000 uint32_t cbData = paParms[0].u.pointer.size;
1001
1002 /* Verify parameters values. */
1003 if (cbData != sizeof (IConsole*))
1004 {
1005 rc = VERR_INVALID_PARAMETER;
1006 }
1007 else if (!pConsole)
1008 {
1009 rc = VERR_INVALID_PARAMETER;
1010 }
1011 else /* Execute the function. */
1012 {
1013 ComPtr<IMachine> pMachine;
1014 ComPtr<IDisplay> pDisplay;
1015 ComPtr<IFramebuffer> pFramebuffer;
1016 LONG xo, yo;
1017 LONG64 winId = 0;
1018 ULONG monitorCount, i, w, h;
1019
1020 CHECK_ERROR_BREAK(pConsole, COMGETTER(Machine)(pMachine.asOutParam()));
1021 CHECK_ERROR_BREAK(pMachine, COMGETTER(MonitorCount)(&monitorCount));
1022 CHECK_ERROR_BREAK(pConsole, COMGETTER(Display)(pDisplay.asOutParam()));
1023
1024 crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE);
1025
1026 g_pConsole = pConsole;
1027
1028 rc = crVBoxServerSetScreenCount(monitorCount);
1029 AssertRCReturn(rc, rc);
1030
1031 for (i=0; i<monitorCount; ++i)
1032 {
1033 CHECK_ERROR_RET(pDisplay, GetFramebuffer(i, pFramebuffer.asOutParam(), &xo, &yo), rc);
1034
1035 if (!pFramebuffer)
1036 {
1037 rc = crVBoxServerUnmapScreen(i);
1038 AssertRCReturn(rc, rc);
1039 }
1040 else
1041 {
1042 CHECK_ERROR_RET(pFramebuffer, COMGETTER(WinId)(&winId), rc);
1043 CHECK_ERROR_RET(pFramebuffer, COMGETTER(Width)(&w), rc);
1044 CHECK_ERROR_RET(pFramebuffer, COMGETTER(Height)(&h), rc);
1045
1046 rc = crVBoxServerMapScreen(i, xo, yo, w, h, winId);
1047 AssertRCReturn(rc, rc);
1048 }
1049 }
1050
1051 crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE);
1052
1053 rc = VINF_SUCCESS;
1054 }
1055 }
1056 break;
1057 }
1058 case SHCRGL_HOST_FN_SET_VM:
1059 {
1060 Log(("svcCall: SHCRGL_HOST_FN_SET_VM\n"));
1061
1062 /* Verify parameter count and types. */
1063 if (cParms != SHCRGL_CPARMS_SET_VM)
1064 {
1065 rc = VERR_INVALID_PARAMETER;
1066 }
1067 else if (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)
1068 {
1069 rc = VERR_INVALID_PARAMETER;
1070 }
1071 else
1072 {
1073 /* Fetch parameters. */
1074 PVM pVM = (PVM)paParms[0].u.pointer.addr;
1075 uint32_t cbData = paParms[0].u.pointer.size;
1076
1077 /* Verify parameters values. */
1078 if (cbData != sizeof (PVM))
1079 {
1080 rc = VERR_INVALID_PARAMETER;
1081 }
1082 else
1083 {
1084 /* Execute the function. */
1085 g_pVM = pVM;
1086 rc = VINF_SUCCESS;
1087 }
1088 }
1089 break;
1090 }
1091 case SHCRGL_HOST_FN_SET_VISIBLE_REGION:
1092 {
1093 Log(("svcCall: SHCRGL_HOST_FN_SET_VISIBLE_REGION\n"));
1094
1095 if (cParms != SHCRGL_CPARMS_SET_VISIBLE_REGION)
1096 {
1097 rc = VERR_INVALID_PARAMETER;
1098 break;
1099 }
1100
1101 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* pRects */
1102 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* cRects */
1103 )
1104 {
1105 rc = VERR_INVALID_PARAMETER;
1106 break;
1107 }
1108
1109 Assert(sizeof(RTRECT)==4*sizeof(GLint));
1110
1111 rc = crVBoxServerSetRootVisibleRegion(paParms[1].u.uint32, (const RTRECT*)paParms[0].u.pointer.addr);
1112 break;
1113 }
1114 case SHCRGL_HOST_FN_SCREEN_CHANGED:
1115 {
1116 Log(("svcCall: SHCRGL_HOST_FN_SCREEN_CHANGED\n"));
1117
1118 /* Verify parameter count and types. */
1119 if (cParms != SHCRGL_CPARMS_SCREEN_CHANGED)
1120 {
1121 rc = VERR_INVALID_PARAMETER;
1122 }
1123 else if (paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT)
1124 {
1125 rc = VERR_INVALID_PARAMETER;
1126 }
1127 else
1128 {
1129 /* Fetch parameters. */
1130 uint32_t screenId = paParms[0].u.uint32;
1131
1132 /* Execute the function. */
1133 ComPtr<IDisplay> pDisplay;
1134 ComPtr<IFramebuffer> pFramebuffer;
1135 LONG xo, yo;
1136 LONG64 winId = 0;
1137 ULONG w, h;
1138
1139 Assert(g_pConsole);
1140 CHECK_ERROR_RET(g_pConsole, COMGETTER(Display)(pDisplay.asOutParam()), rc);
1141 CHECK_ERROR_RET(pDisplay, GetFramebuffer(screenId, pFramebuffer.asOutParam(), &xo, &yo), rc);
1142
1143 crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE);
1144
1145 if (!pFramebuffer)
1146 {
1147 rc = crVBoxServerUnmapScreen(screenId);
1148 AssertRCReturn(rc, rc);
1149 }
1150 else
1151 {
1152 CHECK_ERROR_RET(pFramebuffer, COMGETTER(WinId)(&winId), rc);
1153
1154 if (!winId)
1155 {
1156 /* View associated with framebuffer is destroyed, happens with 2d accel enabled */
1157 rc = crVBoxServerUnmapScreen(screenId);
1158 AssertRCReturn(rc, rc);
1159 }
1160 else
1161 {
1162 CHECK_ERROR_RET(pFramebuffer, COMGETTER(Width)(&w), rc);
1163 CHECK_ERROR_RET(pFramebuffer, COMGETTER(Height)(&h), rc);
1164
1165 rc = crVBoxServerMapScreen(screenId, xo, yo, w, h, winId);
1166 AssertRCReturn(rc, rc);
1167 }
1168 }
1169
1170 crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE);
1171
1172 rc = VINF_SUCCESS;
1173 }
1174 break;
1175 }
1176 case SHCRGL_HOST_FN_VIEWPORT_CHANGED:
1177 {
1178 Log(("svcCall: SHCRGL_HOST_FN_VIEWPORT_CHANGED\n"));
1179
1180 /* Verify parameter count and types. */
1181 if (cParms != SHCRGL_CPARMS_VIEWPORT_CHANGED)
1182 {
1183 LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: cParms invalid - %d", cParms));
1184 rc = VERR_INVALID_PARAMETER;
1185 break;
1186 }
1187
1188 for (int i = 0; i < SHCRGL_CPARMS_VIEWPORT_CHANGED; ++i)
1189 {
1190 if (paParms[i].type != VBOX_HGCM_SVC_PARM_32BIT)
1191 {
1192 LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: param[%d] type invalid - %d", i, paParms[i].type));
1193 rc = VERR_INVALID_PARAMETER;
1194 break;
1195 }
1196 }
1197
1198 if (!RT_SUCCESS(rc))
1199 {
1200 LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: param validation failed, returning.."));
1201 break;
1202 }
1203
1204 crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE);
1205
1206 rc = crVBoxServerSetScreenViewport((int)paParms[0].u.uint32,
1207 paParms[1].u.uint32, /* x */
1208 paParms[2].u.uint32, /* y */
1209 paParms[3].u.uint32, /* w */
1210 paParms[4].u.uint32 /* h */);
1211 if (!RT_SUCCESS(rc))
1212 {
1213 LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: crVBoxServerSetScreenViewport failed, rc %d", rc));
1214 }
1215
1216 crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE);
1217
1218 break;
1219 }
1220 case SHCRGL_HOST_FN_SET_OUTPUT_REDIRECT:
1221 {
1222 /*
1223 * OutputRedirect.
1224 * Note: the service calls OutputRedirect callbacks directly
1225 * and they must not block. If asynchronous processing is needed,
1226 * the callback provider must organize this.
1227 */
1228 Log(("svcCall: SHCRGL_HOST_FN_SET_OUTPUT_REDIRECT\n"));
1229
1230 /* Verify parameter count and types. */
1231 if (cParms != SHCRGL_CPARMS_SET_OUTPUT_REDIRECT)
1232 {
1233 rc = VERR_INVALID_PARAMETER;
1234 }
1235 else if (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)
1236 {
1237 rc = VERR_INVALID_PARAMETER;
1238 }
1239 else
1240 {
1241 /* Fetch parameters. */
1242 H3DOUTPUTREDIRECT *pOutputRedirect = (H3DOUTPUTREDIRECT *)paParms[0].u.pointer.addr;
1243 uint32_t cbData = paParms[0].u.pointer.size;
1244
1245 /* Verify parameters values. */
1246 if (cbData != sizeof (H3DOUTPUTREDIRECT))
1247 {
1248 rc = VERR_INVALID_PARAMETER;
1249 }
1250 else /* Execute the function. */
1251 {
1252 if (pOutputRedirect->H3DORBegin != NULL)
1253 {
1254 rc = crVBoxServerSetOffscreenRendering(GL_TRUE);
1255
1256 if (RT_SUCCESS(rc))
1257 {
1258 CROutputRedirect outputRedirect;
1259 outputRedirect.pvContext = pOutputRedirect->pvContext;
1260 outputRedirect.CRORBegin = pOutputRedirect->H3DORBegin;
1261 outputRedirect.CRORGeometry = pOutputRedirect->H3DORGeometry;
1262 outputRedirect.CRORVisibleRegion = pOutputRedirect->H3DORVisibleRegion;
1263 outputRedirect.CRORFrame = pOutputRedirect->H3DORFrame;
1264 outputRedirect.CROREnd = pOutputRedirect->H3DOREnd;
1265 outputRedirect.CRORContextProperty = pOutputRedirect->H3DORContextProperty;
1266 rc = crVBoxServerOutputRedirectSet(&outputRedirect);
1267 }
1268 }
1269 else
1270 {
1271 /* Redirection is disabled. */
1272 crVBoxServerSetOffscreenRendering(GL_FALSE);
1273 crVBoxServerOutputRedirectSet(NULL);
1274 }
1275 }
1276 }
1277 break;
1278 }
1279 default:
1280 rc = VERR_NOT_IMPLEMENTED;
1281 break;
1282 }
1283
1284 LogFlow(("svcHostCall: rc = %Rrc\n", rc));
1285 return rc;
1286}
1287
1288extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable)
1289{
1290 int rc = VINF_SUCCESS;
1291
1292 Log(("SHARED_CROPENGL VBoxHGCMSvcLoad: ptable = %p\n", ptable));
1293
1294 if (!ptable)
1295 {
1296 rc = VERR_INVALID_PARAMETER;
1297 }
1298 else
1299 {
1300 Log(("VBoxHGCMSvcLoad: ptable->cbSize = %d, ptable->u32Version = 0x%08X\n", ptable->cbSize, ptable->u32Version));
1301
1302 if ( ptable->cbSize != sizeof (VBOXHGCMSVCFNTABLE)
1303 || ptable->u32Version != VBOX_HGCM_SVC_VERSION)
1304 {
1305 rc = VERR_INVALID_PARAMETER;
1306 }
1307 else
1308 {
1309 g_pHelpers = ptable->pHelpers;
1310
1311 ptable->cbClient = sizeof (void*);
1312
1313 ptable->pfnUnload = svcUnload;
1314 ptable->pfnConnect = svcConnect;
1315 ptable->pfnDisconnect = svcDisconnect;
1316 ptable->pfnCall = svcCall;
1317 ptable->pfnHostCall = svcHostCall;
1318 ptable->pfnSaveState = svcSaveState;
1319 ptable->pfnLoadState = svcLoadState;
1320 ptable->pvService = NULL;
1321
1322 if (!crVBoxServerInit())
1323 return VERR_NOT_SUPPORTED;
1324
1325 rc = svcPresentFBOInit();
1326
1327 crServerVBoxSetNotifyEventCB(svcNotifyEventCB);
1328 }
1329 }
1330
1331 return rc;
1332}
1333
1334#ifdef RT_OS_WINDOWS
1335#define WIN32_LEAN_AND_MEAN
1336#include <windows.h>
1337BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)
1338{
1339 (void) lpvReserved;
1340
1341 switch (fdwReason)
1342 {
1343 case DLL_THREAD_ATTACH:
1344 {
1345 crStateVBoxAttachThread();
1346 break;
1347 }
1348
1349 case DLL_PROCESS_DETACH:
1350 /* do exactly the same thing as for DLL_THREAD_DETACH since
1351 * DLL_THREAD_DETACH is not called for the thread doing DLL_PROCESS_DETACH according to msdn docs */
1352 case DLL_THREAD_DETACH:
1353 {
1354 crStateVBoxDetachThread();
1355 break;
1356 }
1357
1358 case DLL_PROCESS_ATTACH:
1359 default:
1360 break;
1361 }
1362
1363 return TRUE;
1364}
1365#endif
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