VirtualBox

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

Last change on this file since 69500 was 69500, checked in by vboxsync, 7 years ago

*: scm --update-copyright-year

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