VirtualBox

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

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

HGCM,GuestProps: Added HGCM service notifications for VM power-on, VM resume, VM suspend, VM reset and VM power-off. Made use of the first two in guest properties to wake up guest programs waiting on any of the host version properties. Also moved inserting sysprep and host version properties to the services as that's a better home than ConsoleImpl/VMMDevInterface in my opinion.

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