VirtualBox

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

Last change on this file since 75773 was 75773, checked in by vboxsync, 6 years ago

HGCM: Added fRequestor and fRestoring to VBOXHGCMSVCFNTABLE::pfnConnect. bugref:9105

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