VirtualBox

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

Last change on this file since 56578 was 56578, checked in by vboxsync, 10 years ago

HostServices/SharedOpenGL: LogRel nits.

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