VirtualBox

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

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

scm --update-copyright-year

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

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette