VirtualBox

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

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

3D: Parameters validation corrected, bugref:9327

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