VirtualBox

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

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

typo

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 47.7 KB
Line 
1/* $Id: crservice.cpp 50341 2014-02-06 13:01:37Z 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, &Screenshot);
942 if (RT_SUCCESS(rc))
943 {
944 pScreenshot->pfnScreenshotPerform(pScreenshot->pvContext, idScreen,
945 0, 0, 32,
946 Screenshot.Img.pitch, Screenshot.Img.width, Screenshot.Img.height,
947 (uint8_t*)Screenshot.Img.pvData, u64Now);
948 crServerVBoxScreenshotRelease(&Screenshot);
949 }
950 else
951 {
952 Assert(rc == VERR_INVALID_STATE);
953 }
954
955 if (pScreenshot->pfnScreenshotEnd)
956 pScreenshot->pfnScreenshotEnd(pScreenshot->pvContext, idScreen, u64Now);
957 }
958}
959
960/*
961 * We differentiate between a function handler for the guest and one for the host.
962 */
963static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
964{
965 int rc = VINF_SUCCESS;
966
967 Log(("SHARED_CROPENGL svcHostCall: fn = %d, cParms = %d, pparms = %d\n", u32Function, cParms, paParms));
968
969#ifdef DEBUG
970 uint32_t i;
971
972 for (i = 0; i < cParms; i++)
973 {
974 /** @todo parameters other than 32 bit */
975 Log((" pparms[%d]: type %d value %d\n", i, paParms[i].type, paParms[i].u.uint32));
976 }
977#endif
978
979 switch (u32Function)
980 {
981 case SHCRGL_HOST_FN_CRCMD_NOTIFY_CMDS:
982 {
983 rc = crVBoxServerCrCmdNotifyCmds();
984 } break;
985#ifdef VBOX_WITH_CRHGSMI
986 case SHCRGL_HOST_FN_CRHGSMI_CMD:
987 {
988 Assert(cParms == 1 && paParms[0].type == VBOX_HGCM_SVC_PARM_PTR);
989 if (cParms == 1 && paParms[0].type == VBOX_HGCM_SVC_PARM_PTR)
990 {
991 rc = crVBoxServerCrHgsmiCmd((PVBOXVDMACMD_CHROMIUM_CMD)paParms[0].u.pointer.addr, paParms[0].u.pointer.size);
992 if (VERR_NOT_SUPPORTED == rc)
993 {
994 svcClientVersionUnsupported(0, 0);
995 }
996 }
997 else
998 rc = VERR_INVALID_PARAMETER;
999 } break;
1000 case SHCRGL_HOST_FN_CRHGSMI_CTL:
1001 {
1002 Assert(cParms == 1 && paParms[0].type == VBOX_HGCM_SVC_PARM_PTR);
1003 if (cParms == 1 && paParms[0].type == VBOX_HGCM_SVC_PARM_PTR)
1004 rc = crVBoxServerCrHgsmiCtl((PVBOXVDMACMD_CHROMIUM_CTL)paParms[0].u.pointer.addr, paParms[0].u.pointer.size);
1005 else
1006 rc = VERR_INVALID_PARAMETER;
1007 } break;
1008#endif
1009 case SHCRGL_HOST_FN_SET_CONSOLE:
1010 {
1011 Log(("svcCall: SHCRGL_HOST_FN_SET_DISPLAY\n"));
1012
1013 /* Verify parameter count and types. */
1014 if (cParms != SHCRGL_CPARMS_SET_CONSOLE)
1015 {
1016 rc = VERR_INVALID_PARAMETER;
1017 }
1018 else if (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)
1019 {
1020 rc = VERR_INVALID_PARAMETER;
1021 }
1022 else
1023 {
1024 /* Fetch parameters. */
1025 IConsole* pConsole = (IConsole*)paParms[0].u.pointer.addr;
1026 uint32_t cbData = paParms[0].u.pointer.size;
1027
1028 /* Verify parameters values. */
1029 if (cbData != sizeof (IConsole*))
1030 {
1031 rc = VERR_INVALID_PARAMETER;
1032 }
1033 else if (!pConsole)
1034 {
1035 rc = VERR_INVALID_PARAMETER;
1036 }
1037 else /* Execute the function. */
1038 {
1039 ComPtr<IMachine> pMachine;
1040 ComPtr<IDisplay> pDisplay;
1041 ComPtr<IFramebuffer> pFramebuffer;
1042 LONG xo, yo;
1043 LONG64 winId = 0;
1044 ULONG monitorCount, i, w, h;
1045
1046 CHECK_ERROR_BREAK(pConsole, COMGETTER(Machine)(pMachine.asOutParam()));
1047 CHECK_ERROR_BREAK(pMachine, COMGETTER(MonitorCount)(&monitorCount));
1048 CHECK_ERROR_BREAK(pConsole, COMGETTER(Display)(pDisplay.asOutParam()));
1049
1050 crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE);
1051
1052 g_pConsole = pConsole;
1053 g_u32ScreenCount = monitorCount;
1054
1055 rc = crVBoxServerSetScreenCount(monitorCount);
1056 AssertRCReturn(rc, rc);
1057
1058 for (i=0; i<monitorCount; ++i)
1059 {
1060 CHECK_ERROR_RET(pDisplay, GetFramebuffer(i, pFramebuffer.asOutParam(), &xo, &yo), rc);
1061
1062 if (!pFramebuffer)
1063 {
1064 rc = crVBoxServerUnmapScreen(i);
1065 AssertRCReturn(rc, rc);
1066 }
1067 else
1068 {
1069 CHECK_ERROR_RET(pFramebuffer, COMGETTER(WinId)(&winId), rc);
1070 CHECK_ERROR_RET(pFramebuffer, COMGETTER(Width)(&w), rc);
1071 CHECK_ERROR_RET(pFramebuffer, COMGETTER(Height)(&h), rc);
1072
1073 rc = crVBoxServerMapScreen(i, xo, yo, w, h, winId);
1074 AssertRCReturn(rc, rc);
1075 }
1076 }
1077
1078 crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE);
1079
1080 rc = VINF_SUCCESS;
1081 }
1082 }
1083 break;
1084 }
1085 case SHCRGL_HOST_FN_SET_VM:
1086 {
1087 Log(("svcCall: SHCRGL_HOST_FN_SET_VM\n"));
1088
1089 /* Verify parameter count and types. */
1090 if (cParms != SHCRGL_CPARMS_SET_VM)
1091 {
1092 rc = VERR_INVALID_PARAMETER;
1093 }
1094 else if (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)
1095 {
1096 rc = VERR_INVALID_PARAMETER;
1097 }
1098 else
1099 {
1100 /* Fetch parameters. */
1101 PVM pVM = (PVM)paParms[0].u.pointer.addr;
1102 uint32_t cbData = paParms[0].u.pointer.size;
1103
1104 /* Verify parameters values. */
1105 if (cbData != sizeof (PVM))
1106 {
1107 rc = VERR_INVALID_PARAMETER;
1108 }
1109 else
1110 {
1111 /* Execute the function. */
1112 g_pVM = pVM;
1113 rc = VINF_SUCCESS;
1114 }
1115 }
1116 break;
1117 }
1118 case SHCRGL_HOST_FN_SET_VISIBLE_REGION:
1119 {
1120 Log(("svcCall: SHCRGL_HOST_FN_SET_VISIBLE_REGION\n"));
1121
1122 if (cParms != SHCRGL_CPARMS_SET_VISIBLE_REGION)
1123 {
1124 rc = VERR_INVALID_PARAMETER;
1125 break;
1126 }
1127
1128 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* pRects */
1129 )
1130 {
1131 rc = VERR_INVALID_PARAMETER;
1132 break;
1133 }
1134
1135 Assert(sizeof (RTRECT) == 4 * sizeof (GLint));
1136
1137 rc = crVBoxServerSetRootVisibleRegion(paParms[0].u.pointer.size / sizeof (RTRECT), (const RTRECT*)paParms[0].u.pointer.addr);
1138 break;
1139 }
1140 case SHCRGL_HOST_FN_SCREEN_CHANGED:
1141 {
1142 Log(("svcCall: SHCRGL_HOST_FN_SCREEN_CHANGED\n"));
1143
1144 /* Verify parameter count and types. */
1145 if (cParms != SHCRGL_CPARMS_SCREEN_CHANGED)
1146 {
1147 rc = VERR_INVALID_PARAMETER;
1148 }
1149 else if (paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT)
1150 {
1151 rc = VERR_INVALID_PARAMETER;
1152 }
1153 else
1154 {
1155 /* Fetch parameters. */
1156 uint32_t screenId = paParms[0].u.uint32;
1157
1158 /* Execute the function. */
1159 ComPtr<IDisplay> pDisplay;
1160 ComPtr<IFramebuffer> pFramebuffer;
1161 LONG xo, yo;
1162 LONG64 winId = 0;
1163 ULONG w, h;
1164
1165 Assert(g_pConsole);
1166 CHECK_ERROR_RET(g_pConsole, COMGETTER(Display)(pDisplay.asOutParam()), rc);
1167 CHECK_ERROR_RET(pDisplay, GetFramebuffer(screenId, pFramebuffer.asOutParam(), &xo, &yo), rc);
1168
1169 crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE);
1170
1171 if (!pFramebuffer)
1172 {
1173 rc = crVBoxServerUnmapScreen(screenId);
1174 AssertRCReturn(rc, rc);
1175 }
1176 else
1177 {
1178#if 0
1179 CHECK_ERROR_RET(pFramebuffer, Lock(), rc);
1180#endif
1181
1182 do {
1183 /* determine if the framebuffer is functional */
1184 rc = pFramebuffer->Notify3DEvent(VBOX3D_NOTIFY_EVENT_TYPE_TEST_FUNCTIONAL, NULL);
1185
1186 if (rc == S_OK)
1187 CHECK_ERROR_BREAK(pFramebuffer, COMGETTER(WinId)(&winId));
1188
1189 if (!winId)
1190 {
1191 /* View associated with framebuffer is destroyed, happens with 2d accel enabled */
1192 rc = crVBoxServerUnmapScreen(screenId);
1193 AssertRCReturn(rc, rc);
1194 }
1195 else
1196 {
1197 CHECK_ERROR_BREAK(pFramebuffer, COMGETTER(Width)(&w));
1198 CHECK_ERROR_BREAK(pFramebuffer, COMGETTER(Height)(&h));
1199
1200 rc = crVBoxServerMapScreen(screenId, xo, yo, w, h, winId);
1201 AssertRCReturn(rc, rc);
1202 }
1203 } while (0);
1204#if 0
1205 CHECK_ERROR_RET(pFramebuffer, Unlock(), rc);
1206#endif
1207 }
1208
1209 crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE);
1210
1211 rc = VINF_SUCCESS;
1212 }
1213 break;
1214 }
1215 case SHCRGL_HOST_FN_TAKE_SCREENSHOT:
1216 {
1217 if (cParms != 1)
1218 {
1219 LogRel(("SHCRGL_HOST_FN_TAKE_SCREENSHOT: cParms invalid - %d", cParms));
1220 rc = VERR_INVALID_PARAMETER;
1221 break;
1222 }
1223
1224 if (paParms->type != VBOX_HGCM_SVC_PARM_PTR)
1225 {
1226 AssertMsgFailed(("invalid param\n"));
1227 rc = VERR_INVALID_PARAMETER;
1228 break;
1229 }
1230
1231 if (!paParms->u.pointer.addr)
1232 {
1233 AssertMsgFailed(("invalid param\n"));
1234 rc = VERR_INVALID_PARAMETER;
1235 break;
1236 }
1237
1238 if (paParms->u.pointer.size != sizeof (CRVBOXHGCMTAKESCREENSHOT))
1239 {
1240 AssertMsgFailed(("invalid param\n"));
1241 rc = VERR_INVALID_PARAMETER;
1242 break;
1243 }
1244
1245 CRVBOXHGCMTAKESCREENSHOT *pScreenshot = (CRVBOXHGCMTAKESCREENSHOT*)paParms->u.pointer.addr;
1246 uint64_t u64Now = RTTimeProgramMilliTS();
1247
1248 if (pScreenshot->u32Screen == CRSCREEN_ALL)
1249 {
1250 for (uint32_t i = 0; i < g_u32ScreenCount; ++i)
1251 {
1252 crScreenshotHandle(pScreenshot, i, u64Now);
1253 }
1254 }
1255 else if (pScreenshot->u32Screen < g_u32ScreenCount)
1256 {
1257 crScreenshotHandle(pScreenshot, pScreenshot->u32Screen, u64Now);
1258 }
1259 else
1260 {
1261 AssertMsgFailed(("invalid screen id\n"));
1262 rc = VERR_INVALID_PARAMETER;
1263 break;
1264 }
1265 break;
1266 }
1267 case SHCRGL_HOST_FN_DEV_RESIZE:
1268 {
1269 Log(("svcCall: SHCRGL_HOST_FN_DEV_RESIZE\n"));
1270
1271 /* Verify parameter count and types. */
1272 if (cParms != SHCRGL_CPARMS_DEV_RESIZE)
1273 {
1274 LogRel(("SHCRGL_HOST_FN_DEV_RESIZE: cParms invalid - %d", cParms));
1275 rc = VERR_INVALID_PARAMETER;
1276 break;
1277 }
1278
1279 if (paParms->type != VBOX_HGCM_SVC_PARM_PTR)
1280 {
1281 AssertMsgFailed(("invalid param\n"));
1282 return VERR_INVALID_PARAMETER;
1283 }
1284
1285 if (!paParms->u.pointer.addr)
1286 {
1287 AssertMsgFailed(("invalid param\n"));
1288 return VERR_INVALID_PARAMETER;
1289 }
1290
1291 if (paParms->u.pointer.size != sizeof (CRVBOXHGCMDEVRESIZE))
1292 {
1293 AssertMsgFailed(("invalid param\n"));
1294 return VERR_INVALID_PARAMETER;
1295 }
1296
1297 CRVBOXHGCMDEVRESIZE *pResize = (CRVBOXHGCMDEVRESIZE*)paParms->u.pointer.addr;
1298
1299 rc = crVBoxServerNotifyResize(&pResize->Screen, pResize->pvVRAM);
1300 break;
1301 }
1302 case SHCRGL_HOST_FN_VIEWPORT_CHANGED:
1303 {
1304 Log(("svcCall: SHCRGL_HOST_FN_VIEWPORT_CHANGED\n"));
1305
1306 /* Verify parameter count and types. */
1307 if (cParms != SHCRGL_CPARMS_VIEWPORT_CHANGED)
1308 {
1309 LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: cParms invalid - %d", cParms));
1310 rc = VERR_INVALID_PARAMETER;
1311 break;
1312 }
1313
1314 for (int i = 0; i < SHCRGL_CPARMS_VIEWPORT_CHANGED; ++i)
1315 {
1316 if (paParms[i].type != VBOX_HGCM_SVC_PARM_32BIT)
1317 {
1318 LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: param[%d] type invalid - %d", i, paParms[i].type));
1319 rc = VERR_INVALID_PARAMETER;
1320 break;
1321 }
1322 }
1323
1324 if (!RT_SUCCESS(rc))
1325 {
1326 LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: param validation failed, returning.."));
1327 break;
1328 }
1329
1330 crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE);
1331
1332 rc = crVBoxServerSetScreenViewport((int)paParms[0].u.uint32,
1333 paParms[1].u.uint32, /* x */
1334 paParms[2].u.uint32, /* y */
1335 paParms[3].u.uint32, /* w */
1336 paParms[4].u.uint32 /* h */);
1337 if (!RT_SUCCESS(rc))
1338 {
1339 LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: crVBoxServerSetScreenViewport failed, rc %d", rc));
1340 }
1341
1342 crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE);
1343
1344 break;
1345 }
1346 case SHCRGL_HOST_FN_VIEWPORT_CHANGED2:
1347 {
1348 Log(("svcCall: SHCRGL_HOST_FN_VIEWPORT_CHANGED\n"));
1349
1350 /* Verify parameter count and types. */
1351 if (cParms != SHCRGL_CPARMS_VIEWPORT_CHANGED)
1352 {
1353 LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: cParms invalid - %d", cParms));
1354 rc = VERR_INVALID_PARAMETER;
1355 break;
1356 }
1357
1358 if (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR
1359 || !paParms[0].u.pointer.addr
1360 || paParms[0].u.pointer.size != sizeof (CRVBOXHGCMVIEWPORT))
1361 {
1362 LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: param invalid - %d, %#x, %d",
1363 paParms[0].type,
1364 paParms[0].u.pointer.addr,
1365 paParms[0].u.pointer.size));
1366 rc = VERR_INVALID_PARAMETER;
1367 break;
1368 }
1369
1370 crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE);
1371
1372 CRVBOXHGCMVIEWPORT *pViewportInfo = (CRVBOXHGCMVIEWPORT*)paParms[0].u.pointer.addr;
1373
1374 rc = crVBoxServerSetScreenViewport(pViewportInfo->u32Screen,
1375 pViewportInfo->x, /* x */
1376 pViewportInfo->y, /* y */
1377 pViewportInfo->width, /* w */
1378 pViewportInfo->height /* h */);
1379 if (!RT_SUCCESS(rc))
1380 {
1381 LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: crVBoxServerSetScreenViewport failed, rc %d", rc));
1382 }
1383
1384 crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE);
1385
1386 break;
1387 }
1388 case SHCRGL_HOST_FN_SET_OUTPUT_REDIRECT:
1389 {
1390 /*
1391 * OutputRedirect.
1392 * Note: the service calls OutputRedirect callbacks directly
1393 * and they must not block. If asynchronous processing is needed,
1394 * the callback provider must organize this.
1395 */
1396 Log(("svcCall: SHCRGL_HOST_FN_SET_OUTPUT_REDIRECT\n"));
1397
1398 /* Verify parameter count and types. */
1399 if (cParms != SHCRGL_CPARMS_SET_OUTPUT_REDIRECT)
1400 {
1401 rc = VERR_INVALID_PARAMETER;
1402 }
1403 else if (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)
1404 {
1405 rc = VERR_INVALID_PARAMETER;
1406 }
1407 else
1408 {
1409 /* Fetch parameters. */
1410 H3DOUTPUTREDIRECT *pOutputRedirect = (H3DOUTPUTREDIRECT *)paParms[0].u.pointer.addr;
1411 uint32_t cbData = paParms[0].u.pointer.size;
1412
1413 /* Verify parameters values. */
1414 if (cbData != sizeof (H3DOUTPUTREDIRECT))
1415 {
1416 rc = VERR_INVALID_PARAMETER;
1417 }
1418 else /* Execute the function. */
1419 {
1420 if (pOutputRedirect->H3DORBegin != NULL)
1421 {
1422 CROutputRedirect outputRedirect;
1423 outputRedirect.pvContext = pOutputRedirect->pvContext;
1424 outputRedirect.CRORBegin = pOutputRedirect->H3DORBegin;
1425 outputRedirect.CRORGeometry = pOutputRedirect->H3DORGeometry;
1426 outputRedirect.CRORVisibleRegion = pOutputRedirect->H3DORVisibleRegion;
1427 outputRedirect.CRORFrame = pOutputRedirect->H3DORFrame;
1428 outputRedirect.CROREnd = pOutputRedirect->H3DOREnd;
1429 outputRedirect.CRORContextProperty = pOutputRedirect->H3DORContextProperty;
1430 rc = crVBoxServerOutputRedirectSet(&outputRedirect);
1431 if (RT_SUCCESS(rc))
1432 {
1433 rc = crVBoxServerSetOffscreenRendering(GL_TRUE);
1434 }
1435 }
1436 else
1437 {
1438 /* Redirection is disabled. */
1439 crVBoxServerSetOffscreenRendering(GL_FALSE);
1440 crVBoxServerOutputRedirectSet(NULL);
1441 }
1442 }
1443 }
1444 break;
1445 }
1446 default:
1447 rc = VERR_NOT_IMPLEMENTED;
1448 break;
1449 }
1450
1451 LogFlow(("svcHostCall: rc = %Rrc\n", rc));
1452 return rc;
1453}
1454
1455extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable)
1456{
1457 int rc = VINF_SUCCESS;
1458
1459 Log(("SHARED_CROPENGL VBoxHGCMSvcLoad: ptable = %p\n", ptable));
1460
1461 if (!ptable)
1462 {
1463 rc = VERR_INVALID_PARAMETER;
1464 }
1465 else
1466 {
1467 Log(("VBoxHGCMSvcLoad: ptable->cbSize = %d, ptable->u32Version = 0x%08X\n", ptable->cbSize, ptable->u32Version));
1468
1469 if ( ptable->cbSize != sizeof (VBOXHGCMSVCFNTABLE)
1470 || ptable->u32Version != VBOX_HGCM_SVC_VERSION)
1471 {
1472 rc = VERR_INVALID_PARAMETER;
1473 }
1474 else
1475 {
1476 g_pHelpers = ptable->pHelpers;
1477
1478 ptable->cbClient = sizeof (void*);
1479
1480 ptable->pfnUnload = svcUnload;
1481 ptable->pfnConnect = svcConnect;
1482 ptable->pfnDisconnect = svcDisconnect;
1483 ptable->pfnCall = svcCall;
1484 ptable->pfnHostCall = svcHostCall;
1485 ptable->pfnSaveState = svcSaveState;
1486 ptable->pfnLoadState = svcLoadState;
1487 ptable->pvService = NULL;
1488
1489 if (!crVBoxServerInit())
1490 return VERR_NOT_SUPPORTED;
1491
1492 rc = svcPresentFBOInit();
1493
1494 crServerVBoxSetNotifyEventCB(svcNotifyEventCB);
1495 }
1496 }
1497
1498 return rc;
1499}
1500
1501#ifdef RT_OS_WINDOWS
1502#define WIN32_LEAN_AND_MEAN
1503#include <windows.h>
1504BOOL WINAPI DllMain(HINSTANCE hDLLInst, DWORD fdwReason, LPVOID lpvReserved)
1505{
1506 (void) lpvReserved;
1507
1508 switch (fdwReason)
1509 {
1510 case DLL_THREAD_ATTACH:
1511 {
1512 crStateVBoxAttachThread();
1513 break;
1514 }
1515
1516 case DLL_PROCESS_DETACH:
1517 /* do exactly the same thing as for DLL_THREAD_DETACH since
1518 * DLL_THREAD_DETACH is not called for the thread doing DLL_PROCESS_DETACH according to msdn docs */
1519 case DLL_THREAD_DETACH:
1520 {
1521 crStateVBoxDetachThread();
1522 break;
1523 }
1524
1525 case DLL_PROCESS_ATTACH:
1526 default:
1527 break;
1528 }
1529
1530 return TRUE;
1531}
1532#endif
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