VirtualBox

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

Last change on this file since 36843 was 36843, checked in by vboxsync, 14 years ago

3D for VRDP: initial commit (xTracker 5565).

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