VirtualBox

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

Last change on this file since 41128 was 41128, checked in by vboxsync, 13 years ago

crOpenGL: backwards compatibility for 3D saved state v 28

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