VirtualBox

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

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

crOpenGL: greyed-out 3D image on VM pause

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