VirtualBox

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

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

crOpenGL: fix deadlock with multiply screens (#5462)

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

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