VirtualBox

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

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

wddm/crOpenGL: misc bugfixes

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