VirtualBox

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

Last change on this file since 35347 was 35347, checked in by vboxsync, 14 years ago

build fix.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 37.6 KB
Line 
1/* $Id: crservice.cpp 35347 2010-12-27 16:25:58Z vboxsync $ */
2
3/** @file
4 * VBox crOpenGL: Host service entry points.
5 */
6
7/*
8 * Copyright (C) 2006-2008 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#ifdef RT_OS_WINDOWS
22# include <iprt/alloc.h>
23# include <iprt/string.h>
24# include <iprt/assert.h>
25# include <iprt/stream.h>
26# include <VBox/vmm/ssm.h>
27# include <VBox/hgcmsvc.h>
28# include <VBox/HostServices/VBoxCrOpenGLSvc.h>
29# include "cr_server.h"
30# define LOG_GROUP LOG_GROUP_SHARED_CROPENGL
31# include <VBox/log.h>
32
33# include <VBox/com/com.h>
34# include <VBox/com/string.h>
35# include <VBox/com/array.h>
36# include <VBox/com/Guid.h>
37# include <VBox/com/ErrorInfo.h>
38# include <VBox/com/EventQueue.h>
39# include <VBox/com/VirtualBox.h>
40# include <VBox/com/assert.h>
41
42#else
43# include <VBox/com/VirtualBox.h>
44# include <iprt/assert.h>
45# include <VBox/vmm/ssm.h>
46# include <VBox/hgcmsvc.h>
47# include <VBox/HostServices/VBoxCrOpenGLSvc.h>
48
49# include "cr_server.h"
50# define LOG_GROUP LOG_GROUP_SHARED_CROPENGL
51# include <VBox/log.h>
52# include <VBox/com/ErrorInfo.h>
53#endif /* RT_OS_WINDOWS */
54
55#ifdef VBOX_WITH_CRHGSMI
56# include <VBox/VBoxVideo.h>
57#endif
58
59#include <VBox/com/errorprint.h>
60
61PVBOXHGCMSVCHELPERS g_pHelpers;
62static IConsole* g_pConsole = NULL;
63static PVM g_pVM = NULL;
64#ifdef VBOX_WITH_CRHGSMI
65static uint8_t* g_pvVRamBase;
66#endif
67
68#ifndef RT_OS_WINDOWS
69# define DWORD int
70# define WINAPI
71#endif
72
73static const char* gszVBoxOGLSSMMagic = "***OpenGL state data***";
74
75typedef struct _CRVBOXSVCBUFFER_t {
76 uint32_t uiId;
77 uint32_t uiSize;
78 void* pData;
79 _CRVBOXSVCBUFFER_t *pNext, *pPrev;
80} CRVBOXSVCBUFFER_t;
81
82static CRVBOXSVCBUFFER_t *g_pCRVBoxSVCBuffers = NULL;
83static uint32_t g_CRVBoxSVCBufferID = 0;
84
85static DECLCALLBACK(int) svcUnload (void *)
86{
87 int rc = VINF_SUCCESS;
88
89 Log(("SHARED_CROPENGL svcUnload\n"));
90
91 crVBoxServerTearDown();
92
93 return rc;
94}
95
96static DECLCALLBACK(int) svcConnect (void *, uint32_t u32ClientID, void *pvClient)
97{
98 int rc = VINF_SUCCESS;
99
100 NOREF(pvClient);
101
102 Log(("SHARED_CROPENGL svcConnect: u32ClientID = %d\n", u32ClientID));
103
104 rc = crVBoxServerAddClient(u32ClientID);
105
106 return rc;
107}
108
109static DECLCALLBACK(int) svcDisconnect (void *, uint32_t u32ClientID, void *pvClient)
110{
111 int rc = VINF_SUCCESS;
112
113 NOREF(pvClient);
114
115 Log(("SHARED_CROPENGL svcDisconnect: u32ClientID = %d\n", u32ClientID));
116
117 crVBoxServerRemoveClient(u32ClientID);
118
119 return rc;
120}
121
122static DECLCALLBACK(int) svcSaveState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
123{
124 int rc = VINF_SUCCESS;
125
126 NOREF(pvClient);
127
128 Log(("SHARED_CROPENGL svcSaveState: u32ClientID = %d\n", u32ClientID));
129
130 /* Start*/
131 rc = SSMR3PutStrZ(pSSM, gszVBoxOGLSSMMagic);
132 AssertRCReturn(rc, rc);
133
134 /* Version */
135 rc = SSMR3PutU32(pSSM, (uint32_t) SHCROGL_SSM_VERSION);
136 AssertRCReturn(rc, rc);
137
138 /* The state itself */
139 rc = crVBoxServerSaveState(pSSM);
140 AssertRCReturn(rc, rc);
141
142 /* Save svc buffers info */
143 {
144 CRVBOXSVCBUFFER_t *pBuffer = g_pCRVBoxSVCBuffers;
145
146 rc = SSMR3PutU32(pSSM, g_CRVBoxSVCBufferID);
147 AssertRCReturn(rc, rc);
148
149 while (pBuffer)
150 {
151 rc = SSMR3PutU32(pSSM, pBuffer->uiId);
152 AssertRCReturn(rc, rc);
153
154 rc = SSMR3PutU32(pSSM, pBuffer->uiSize);
155 AssertRCReturn(rc, rc);
156
157 rc = SSMR3PutMem(pSSM, pBuffer->pData, pBuffer->uiSize);
158 AssertRCReturn(rc, rc);
159
160 pBuffer = pBuffer->pNext;
161 }
162
163 rc = SSMR3PutU32(pSSM, 0);
164 AssertRCReturn(rc, rc);
165 }
166
167 /* End */
168 rc = SSMR3PutStrZ(pSSM, gszVBoxOGLSSMMagic);
169 AssertRCReturn(rc, rc);
170
171 return VINF_SUCCESS;
172}
173
174static DECLCALLBACK(int) svcLoadState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
175{
176 int rc = VINF_SUCCESS;
177
178 NOREF(pvClient);
179
180 Log(("SHARED_CROPENGL svcLoadState: u32ClientID = %d\n", u32ClientID));
181
182 char psz[2000];
183 uint32_t ui32;
184
185 /* Start of data */
186 rc = SSMR3GetStrZEx(pSSM, psz, 2000, NULL);
187 AssertRCReturn(rc, rc);
188 if (strcmp(gszVBoxOGLSSMMagic, psz))
189 return VERR_SSM_UNEXPECTED_DATA;
190
191 /* Version */
192 rc = SSMR3GetU32(pSSM, &ui32);
193 AssertRCReturn(rc, rc);
194
195 /* The state itself */
196#if SHCROGL_SSM_VERSION==24
197 if (ui32==23)
198 {
199 rc = crVBoxServerLoadState(pSSM, 24);
200 }
201 else
202#endif
203 rc = crVBoxServerLoadState(pSSM, ui32);
204
205 if (rc==VERR_SSM_DATA_UNIT_FORMAT_CHANGED && ui32!=SHCROGL_SSM_VERSION)
206 {
207 LogRel(("SHARED_CROPENGL svcLoadState: unsupported save state version %d\n", ui32));
208
209 /*@todo ugly hack, as we don't know size of stored opengl data try to read untill end of opengl data marker*/
210 /*VboxSharedCrOpenGL isn't last hgcm service now, so can't use SSMR3SkipToEndOfUnit*/
211 {
212 const char *pMatch = &gszVBoxOGLSSMMagic[0];
213 char current;
214
215 while (*pMatch)
216 {
217 rc = SSMR3GetS8(pSSM, (int8_t*)&current);
218 AssertRCReturn(rc, rc);
219
220 if (current==*pMatch)
221 {
222 pMatch++;
223 }
224 else
225 {
226 pMatch = &gszVBoxOGLSSMMagic[0];
227 }
228 }
229 }
230
231 return VINF_SUCCESS;
232 }
233 AssertRCReturn(rc, rc);
234
235 /* Load svc buffers info */
236 if (ui32>=24)
237 {
238 uint32_t uiId;
239
240 rc = SSMR3GetU32(pSSM, &g_CRVBoxSVCBufferID);
241 AssertRCReturn(rc, rc);
242
243 rc = SSMR3GetU32(pSSM, &uiId);
244 AssertRCReturn(rc, rc);
245
246 while (uiId)
247 {
248 CRVBOXSVCBUFFER_t *pBuffer = (CRVBOXSVCBUFFER_t *) RTMemAlloc(sizeof(CRVBOXSVCBUFFER_t));
249 if (!pBuffer)
250 {
251 return VERR_NO_MEMORY;
252 }
253 pBuffer->uiId = uiId;
254
255 rc = SSMR3GetU32(pSSM, &pBuffer->uiSize);
256 AssertRCReturn(rc, rc);
257
258 pBuffer->pData = RTMemAlloc(pBuffer->uiSize);
259 if (!pBuffer->pData)
260 {
261 RTMemFree(pBuffer);
262 return VERR_NO_MEMORY;
263 }
264
265 rc = SSMR3GetMem(pSSM, pBuffer->pData, pBuffer->uiSize);
266 AssertRCReturn(rc, rc);
267
268 pBuffer->pNext = g_pCRVBoxSVCBuffers;
269 pBuffer->pPrev = NULL;
270 if (g_pCRVBoxSVCBuffers)
271 {
272 g_pCRVBoxSVCBuffers->pPrev = pBuffer;
273 }
274 g_pCRVBoxSVCBuffers = pBuffer;
275
276 rc = SSMR3GetU32(pSSM, &uiId);
277 AssertRCReturn(rc, rc);
278 }
279 }
280
281 /* End of data */
282 rc = SSMR3GetStrZEx(pSSM, psz, 2000, NULL);
283 AssertRCReturn(rc, rc);
284 if (strcmp(gszVBoxOGLSSMMagic, psz))
285 return VERR_SSM_UNEXPECTED_DATA;
286
287 return VINF_SUCCESS;
288}
289
290static void svcClientVersionUnsupported(uint32_t minor, uint32_t major)
291{
292 LogRel(("SHARED_CROPENGL: unsupported client version %d.%d\n", minor, major));
293
294 /*MS's opengl32 tries to load our ICD around 30 times on failure...this is to prevent unnecessary spam*/
295 static int shown = 0;
296
297 if (g_pVM && !shown)
298 {
299 VMSetRuntimeError(g_pVM, VMSETRTERR_FLAGS_NO_WAIT, "3DSupportIncompatibleAdditions",
300 "An attempt by the virtual machine to use hardware 3D acceleration failed. "
301 "The version of the Guest Additions installed in the virtual machine does not match the "
302 "version of VirtualBox on the host. Please install appropriate Guest Additions to fix this issue");
303 shown = 1;
304 }
305}
306
307static DECLCALLBACK(void) svcPresentFBO(void *data, int32_t screenId, int32_t x, int32_t y, uint32_t w, uint32_t h)
308{
309#if 0
310 ComPtr<IDisplay> pDisplay;
311 BYTE *data;
312 int i,j;
313 CHECK_ERROR(g_pConsole, COMGETTER(Display)(pDisplay.asOutParam()));
314
315 data = (BYTE*) RTMemTmpAllocZ(100*100*4);
316
317 for (i=0; i<100; i+=2)
318 {
319 for (j=0; j<100; ++j)
320 {
321 *(data+i*100*4+j*4+0) = 0xFF;
322 *(data+i*100*4+j*4+1) = 0xFF;
323 *(data+i*100*4+j*4+2) = 0xFF;
324 *(data+i*100*4+j*4+3) = 0xFF;
325 }
326 }
327
328 CHECK_ERROR(pDisplay, DrawToScreen(screenId, data, 0, 0, 100, 100));
329
330 RTMemTmpFree(data);
331#endif
332 HRESULT rc;
333 ComPtr<IDisplay> pDisplay;
334
335 CHECK_ERROR(g_pConsole, COMGETTER(Display)(pDisplay.asOutParam()));
336 CHECK_ERROR(pDisplay, DrawToScreen(screenId, (BYTE*)data, x, y, w, h));
337}
338
339static CRVBOXSVCBUFFER_t* svcGetBuffer(uint32_t iBuffer, uint32_t cbBufferSize)
340{
341 CRVBOXSVCBUFFER_t* pBuffer;
342
343 if (iBuffer)
344 {
345 pBuffer = g_pCRVBoxSVCBuffers;
346 while (pBuffer)
347 {
348 if (pBuffer->uiId == iBuffer)
349 {
350 return pBuffer;
351 }
352 pBuffer = pBuffer->pNext;
353 }
354 return NULL;
355 }
356 else /*allocate new buffer*/
357 {
358 pBuffer = (CRVBOXSVCBUFFER_t*) RTMemAlloc(sizeof(CRVBOXSVCBUFFER_t));
359 if (pBuffer)
360 {
361 pBuffer->pData = RTMemAlloc(cbBufferSize);
362 if (!pBuffer->pData)
363 {
364 LogRel(("SHARED_CROPENGL svcGetBuffer: not enough memory (%d)\n", cbBufferSize));
365 RTMemFree(pBuffer);
366 return NULL;
367 }
368 pBuffer->uiId = ++g_CRVBoxSVCBufferID;
369 if (!pBuffer->uiId)
370 {
371 pBuffer->uiId = ++g_CRVBoxSVCBufferID;
372 }
373 Assert(pBuffer->uiId);
374 pBuffer->uiSize = cbBufferSize;
375 pBuffer->pPrev = NULL;
376 pBuffer->pNext = g_pCRVBoxSVCBuffers;
377 if (g_pCRVBoxSVCBuffers)
378 {
379 g_pCRVBoxSVCBuffers->pPrev = pBuffer;
380 }
381 g_pCRVBoxSVCBuffers = pBuffer;
382 }
383 else
384 {
385 LogRel(("SHARED_CROPENGL svcGetBuffer: not enough memory (%d)\n", sizeof(CRVBOXSVCBUFFER_t)));
386 }
387 return pBuffer;
388 }
389}
390
391static void svcFreeBuffer(CRVBOXSVCBUFFER_t* pBuffer)
392{
393 Assert(pBuffer);
394
395 if (pBuffer->pPrev)
396 {
397 pBuffer->pPrev->pNext = pBuffer->pNext;
398 }
399 else
400 {
401 Assert(pBuffer==g_pCRVBoxSVCBuffers);
402 g_pCRVBoxSVCBuffers = pBuffer->pNext;
403 }
404
405 if (pBuffer->pNext)
406 {
407 pBuffer->pNext->pPrev = pBuffer->pPrev;
408 }
409
410 RTMemFree(pBuffer->pData);
411 RTMemFree(pBuffer);
412}
413
414static DECLCALLBACK(void) svcCall (void *, VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, void *pvClient, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
415{
416 int rc = VINF_SUCCESS;
417
418 NOREF(pvClient);
419
420 Log(("SHARED_CROPENGL svcCall: u32ClientID = %d, fn = %d, cParms = %d, pparms = %d\n", u32ClientID, u32Function, cParms, paParms));
421
422#ifdef DEBUG
423 uint32_t i;
424
425 for (i = 0; i < cParms; i++)
426 {
427 /** @todo parameters other than 32 bit */
428 Log((" pparms[%d]: type %d value %d\n", i, paParms[i].type, paParms[i].u.uint32));
429 }
430#endif
431
432 switch (u32Function)
433 {
434 case SHCRGL_GUEST_FN_WRITE:
435 {
436 Log(("svcCall: SHCRGL_GUEST_FN_WRITE\n"));
437
438 /* Verify parameter count and types. */
439 if (cParms != SHCRGL_CPARMS_WRITE)
440 {
441 rc = VERR_INVALID_PARAMETER;
442 }
443 else
444 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* pBuffer */
445 )
446 {
447 rc = VERR_INVALID_PARAMETER;
448 }
449 else
450 {
451 /* Fetch parameters. */
452 uint8_t *pBuffer = (uint8_t *)paParms[0].u.pointer.addr;
453 uint32_t cbBuffer = paParms[0].u.pointer.size;
454
455 /* Execute the function. */
456 rc = crVBoxServerClientWrite(u32ClientID, pBuffer, cbBuffer);
457 if (!RT_SUCCESS(rc))
458 {
459 Assert(VERR_NOT_SUPPORTED==rc);
460 svcClientVersionUnsupported(0, 0);
461 }
462
463 }
464 break;
465 }
466
467 case SHCRGL_GUEST_FN_INJECT:
468 {
469 Log(("svcCall: SHCRGL_GUEST_FN_INJECT\n"));
470
471 /* Verify parameter count and types. */
472 if (cParms != SHCRGL_CPARMS_INJECT)
473 {
474 rc = VERR_INVALID_PARAMETER;
475 }
476 else
477 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* u32ClientID */
478 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* pBuffer */
479 )
480 {
481 rc = VERR_INVALID_PARAMETER;
482 }
483 else
484 {
485 /* Fetch parameters. */
486 uint32_t u32InjectClientID = paParms[0].u.uint32;
487 uint8_t *pBuffer = (uint8_t *)paParms[1].u.pointer.addr;
488 uint32_t cbBuffer = paParms[1].u.pointer.size;
489
490 /* Execute the function. */
491 rc = crVBoxServerClientWrite(u32InjectClientID, pBuffer, cbBuffer);
492 if (!RT_SUCCESS(rc))
493 {
494 if (VERR_NOT_SUPPORTED==rc)
495 {
496 svcClientVersionUnsupported(0, 0);
497 }
498 else
499 {
500 crWarning("SHCRGL_GUEST_FN_INJECT failed to inject for %i from %i", u32InjectClientID, u32ClientID);
501 }
502 }
503 }
504 break;
505 }
506
507 case SHCRGL_GUEST_FN_READ:
508 {
509 Log(("svcCall: SHCRGL_GUEST_FN_READ\n"));
510
511 /* Verify parameter count and types. */
512 if (cParms != SHCRGL_CPARMS_READ)
513 {
514 rc = VERR_INVALID_PARAMETER;
515 }
516 else
517 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* pBuffer */
518 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* cbBuffer */
519 )
520 {
521 rc = VERR_INVALID_PARAMETER;
522 }
523
524 /* Fetch parameters. */
525 uint8_t *pBuffer = (uint8_t *)paParms[0].u.pointer.addr;
526 uint32_t cbBuffer = paParms[0].u.pointer.size;
527
528 /* Execute the function. */
529 rc = crVBoxServerClientRead(u32ClientID, pBuffer, &cbBuffer);
530
531 if (RT_SUCCESS(rc))
532 {
533 /* Update parameters.*/
534 paParms[0].u.pointer.size = cbBuffer; //@todo guest doesn't see this change somehow?
535 } else if (VERR_NOT_SUPPORTED==rc)
536 {
537 svcClientVersionUnsupported(0, 0);
538 }
539
540 /* Return the required buffer size always */
541 paParms[1].u.uint32 = cbBuffer;
542
543 break;
544 }
545
546 case SHCRGL_GUEST_FN_WRITE_READ:
547 {
548 Log(("svcCall: SHCRGL_GUEST_FN_WRITE_READ\n"));
549
550 /* Verify parameter count and types. */
551 if (cParms != SHCRGL_CPARMS_WRITE_READ)
552 {
553 rc = VERR_INVALID_PARAMETER;
554 }
555 else
556 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* pBuffer */
557 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* pWriteback */
558 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* cbWriteback */
559 )
560 {
561 rc = VERR_INVALID_PARAMETER;
562 }
563 else
564 {
565 /* Fetch parameters. */
566 uint8_t *pBuffer = (uint8_t *)paParms[0].u.pointer.addr;
567 uint32_t cbBuffer = paParms[0].u.pointer.size;
568
569 uint8_t *pWriteback = (uint8_t *)paParms[1].u.pointer.addr;
570 uint32_t cbWriteback = paParms[1].u.pointer.size;
571
572 /* Execute the function. */
573 rc = crVBoxServerClientWrite(u32ClientID, pBuffer, cbBuffer);
574 if (!RT_SUCCESS(rc))
575 {
576 Assert(VERR_NOT_SUPPORTED==rc);
577 svcClientVersionUnsupported(0, 0);
578 }
579
580 rc = crVBoxServerClientRead(u32ClientID, pWriteback, &cbWriteback);
581
582 if (RT_SUCCESS(rc))
583 {
584 /* Update parameters.*/
585 paParms[1].u.pointer.size = cbWriteback;
586 }
587 /* Return the required buffer size always */
588 paParms[2].u.uint32 = cbWriteback;
589 }
590
591 break;
592 }
593
594 case SHCRGL_GUEST_FN_SET_VERSION:
595 {
596 Log(("svcCall: SHCRGL_GUEST_FN_SET_VERSION\n"));
597
598 /* Verify parameter count and types. */
599 if (cParms != SHCRGL_CPARMS_SET_VERSION)
600 {
601 rc = VERR_INVALID_PARAMETER;
602 }
603 else
604 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* vMajor */
605 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* vMinor */
606 )
607 {
608 rc = VERR_INVALID_PARAMETER;
609 }
610 else
611 {
612 /* Fetch parameters. */
613 uint32_t vMajor = paParms[0].u.uint32;
614 uint32_t vMinor = paParms[1].u.uint32;
615
616 /* Execute the function. */
617 rc = crVBoxServerClientSetVersion(u32ClientID, vMajor, vMinor);
618
619 if (!RT_SUCCESS(rc))
620 {
621 svcClientVersionUnsupported(vMajor, vMinor);
622 }
623 }
624
625 break;
626 }
627
628 case SHCRGL_GUEST_FN_SET_PID:
629 {
630 Log(("svcCall: SHCRGL_GUEST_FN_SET_PID\n"));
631
632 /* Verify parameter count and types. */
633 if (cParms != SHCRGL_CPARMS_SET_PID)
634 {
635 rc = VERR_INVALID_PARAMETER;
636 }
637 else
638 if (paParms[0].type != VBOX_HGCM_SVC_PARM_64BIT)
639 {
640 rc = VERR_INVALID_PARAMETER;
641 }
642 else
643 {
644 /* Fetch parameters. */
645 uint64_t pid = paParms[0].u.uint64;
646
647 /* Execute the function. */
648 rc = crVBoxServerClientSetPID(u32ClientID, pid);
649 }
650
651 break;
652 }
653
654 case SHCRGL_GUEST_FN_WRITE_BUFFER:
655 {
656 Log(("svcCall: SHCRGL_GUEST_FN_WRITE_BUFFER\n"));
657 /* Verify parameter count and types. */
658 if (cParms != SHCRGL_CPARMS_WRITE_BUFFER)
659 {
660 rc = VERR_INVALID_PARAMETER;
661 }
662 else
663 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /*iBufferID*/
664 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /*cbBufferSize*/
665 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /*ui32Offset*/
666 || paParms[3].type != VBOX_HGCM_SVC_PARM_PTR /*pBuffer*/
667 )
668 {
669 rc = VERR_INVALID_PARAMETER;
670 }
671 else
672 {
673 /* Fetch parameters. */
674 uint32_t iBuffer = paParms[0].u.uint32;
675 uint32_t cbBufferSize = paParms[1].u.uint32;
676 uint32_t ui32Offset = paParms[2].u.uint32;
677 uint8_t *pBuffer = (uint8_t *)paParms[3].u.pointer.addr;
678 uint32_t cbBuffer = paParms[3].u.pointer.size;
679
680 /* Execute the function. */
681 CRVBOXSVCBUFFER_t *pSvcBuffer = svcGetBuffer(iBuffer, cbBufferSize);
682 if (!pSvcBuffer || ui32Offset+cbBuffer>cbBufferSize)
683 {
684 rc = VERR_INVALID_PARAMETER;
685 }
686 else
687 {
688 memcpy((void*)((uintptr_t)pSvcBuffer->pData+ui32Offset), pBuffer, cbBuffer);
689
690 /* Return the buffer id */
691 paParms[0].u.uint32 = pSvcBuffer->uiId;
692 }
693 }
694
695 break;
696 }
697
698 case SHCRGL_GUEST_FN_WRITE_READ_BUFFERED:
699 {
700 Log(("svcCall: SHCRGL_GUEST_FN_WRITE_READ_BUFFERED\n"));
701
702 /* Verify parameter count and types. */
703 if (cParms != SHCRGL_CPARMS_WRITE_READ_BUFFERED)
704 {
705 rc = VERR_INVALID_PARAMETER;
706 }
707 else
708 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* iBufferID */
709 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* pWriteback */
710 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* cbWriteback */
711 || !paParms[0].u.uint32 /*iBufferID can't be 0 here*/
712 )
713 {
714 rc = VERR_INVALID_PARAMETER;
715 }
716 else
717 {
718 /* Fetch parameters. */
719 uint32_t iBuffer = paParms[0].u.uint32;
720 uint8_t *pWriteback = (uint8_t *)paParms[1].u.pointer.addr;
721 uint32_t cbWriteback = paParms[1].u.pointer.size;
722
723 CRVBOXSVCBUFFER_t *pSvcBuffer = svcGetBuffer(iBuffer, 0);
724 if (!pSvcBuffer)
725 {
726 LogRel(("SHARED_CROPENGL svcCall(WRITE_READ_BUFFERED): invalid buffer (%d)\n", iBuffer));
727 rc = VERR_INVALID_PARAMETER;
728 break;
729 }
730
731 uint8_t *pBuffer = (uint8_t *)pSvcBuffer->pData;
732 uint32_t cbBuffer = pSvcBuffer->uiSize;
733
734 /* Execute the function. */
735 rc = crVBoxServerClientWrite(u32ClientID, pBuffer, cbBuffer);
736 if (!RT_SUCCESS(rc))
737 {
738 Assert(VERR_NOT_SUPPORTED==rc);
739 svcClientVersionUnsupported(0, 0);
740 }
741
742 rc = crVBoxServerClientRead(u32ClientID, pWriteback, &cbWriteback);
743
744 if (RT_SUCCESS(rc))
745 {
746 /* Update parameters.*/
747 paParms[1].u.pointer.size = cbWriteback;
748 }
749 /* Return the required buffer size always */
750 paParms[2].u.uint32 = cbWriteback;
751
752 svcFreeBuffer(pSvcBuffer);
753 }
754
755 break;
756 }
757
758 default:
759 {
760 rc = VERR_NOT_IMPLEMENTED;
761 }
762 }
763
764
765 LogFlow(("svcCall: rc = %Rrc\n", rc));
766
767 g_pHelpers->pfnCallComplete (callHandle, rc);
768}
769
770#ifdef VBOX_WITH_CRHGSMI
771static int vboxCrHgsmiCtl(PVBOXVDMACMD_CHROMIUM_CTL pCtl)
772{
773 int rc;
774
775 switch (pCtl->enmType)
776 {
777 case VBOXVDMACMD_CHROMIUM_CTL_TYPE_CRHGSMI_SETUP:
778 {
779 PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP pSetup = (PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP)pCtl;
780 g_pvVRamBase = (uint8_t*)pSetup->pvRamBase;
781 rc = VINF_SUCCESS;
782 } break;
783 case VBOXVDMACMD_CHROMIUM_CTL_TYPE_SAVESTATE_BEGIN:
784 case VBOXVDMACMD_CHROMIUM_CTL_TYPE_SAVESTATE_END:
785 rc = VINF_SUCCESS;
786 break;
787 default:
788 Assert(0);
789 rc = VERR_INVALID_PARAMETER;
790 }
791
792 return rc;
793}
794
795#define VBOXCRHGSMI_PTR(_off, _t) ((_t*)(g_pvVRamBase + (_off)))
796static int vboxCrHgsmiCmd(PVBOXVDMACMD_CHROMIUM_CMD pCmd)
797{
798 int rc;
799 uint32_t cBuffers = pCmd->cBuffers;
800 uint32_t cParams;
801
802 if (!g_pvVRamBase)
803 {
804 Assert(0);
805 return VERR_INVALID_STATE;
806 }
807
808 if (!cBuffers)
809 {
810 Assert(0);
811 return VERR_INVALID_PARAMETER;
812 }
813
814 cParams = cBuffers-1;
815
816 CRVBOXHGSMIHDR *pHdr = VBOXCRHGSMI_PTR(pCmd->aBuffers[0].offBuffer, CRVBOXHGSMIHDR);
817 uint32_t u32Function = pHdr->u32Function;
818 uint32_t u32ClientID = pHdr->u32ClientID;
819 /* now we compile HGCM params out of HGSMI
820 * @todo: can we avoid this ? */
821 switch (u32Function)
822 {
823
824 case SHCRGL_GUEST_FN_WRITE:
825 {
826 Log(("svcCall: SHCRGL_GUEST_FN_WRITE\n"));
827
828 CRVBOXHGSMIWRITE* pFnCmd = (CRVBOXHGSMIWRITE*)pHdr;
829
830 /* @todo: Verify */
831 if (cParams == 1)
832 {
833 VBOXVDMACMD_CHROMIUM_BUFFER *pBuf = &pCmd->aBuffers[1];
834 /* Fetch parameters. */
835 uint8_t *pBuffer = VBOXCRHGSMI_PTR(pBuf->offBuffer, uint8_t);
836 uint32_t cbBuffer = pBuf->cbBuffer;
837
838 /* Execute the function. */
839 rc = crVBoxServerClientWrite(u32ClientID, pBuffer, cbBuffer);
840 if (!RT_SUCCESS(rc))
841 {
842 Assert(VERR_NOT_SUPPORTED==rc);
843 svcClientVersionUnsupported(0, 0);
844 }
845 }
846 else
847 {
848 Assert(0);
849 rc = VERR_INVALID_PARAMETER;
850 }
851 break;
852 }
853
854 case SHCRGL_GUEST_FN_INJECT:
855 {
856 Log(("svcCall: SHCRGL_GUEST_FN_INJECT\n"));
857
858 CRVBOXHGSMIINJECT *pFnCmd = (CRVBOXHGSMIINJECT*)pHdr;
859
860 /* @todo: Verify */
861 if (cParams == 1)
862 {
863 /* Fetch parameters. */
864 uint32_t u32InjectClientID = pFnCmd->u32ClientID;
865 VBOXVDMACMD_CHROMIUM_BUFFER *pBuf = &pCmd->aBuffers[1];
866 uint8_t *pBuffer = VBOXCRHGSMI_PTR(pBuf->offBuffer, uint8_t);
867 uint32_t cbBuffer = pBuf->cbBuffer;
868
869 /* Execute the function. */
870 rc = crVBoxServerClientWrite(u32InjectClientID, pBuffer, cbBuffer);
871 if (!RT_SUCCESS(rc))
872 {
873 if (VERR_NOT_SUPPORTED==rc)
874 {
875 svcClientVersionUnsupported(0, 0);
876 }
877 else
878 {
879 crWarning("SHCRGL_GUEST_FN_INJECT failed to inject for %i from %i", u32InjectClientID, u32ClientID);
880 }
881 }
882 }
883 else
884 {
885 Assert(0);
886 rc = VERR_INVALID_PARAMETER;
887 }
888 break;
889 }
890
891 case SHCRGL_GUEST_FN_READ:
892 {
893 Log(("svcCall: SHCRGL_GUEST_FN_READ\n"));
894
895 /* @todo: Verify */
896 if (cParams == 1)
897 {
898 CRVBOXHGSMIREAD *pFnCmd = (CRVBOXHGSMIREAD*)pHdr;
899 VBOXVDMACMD_CHROMIUM_BUFFER *pBuf = &pCmd->aBuffers[1];
900 /* Fetch parameters. */
901 uint8_t *pBuffer = VBOXCRHGSMI_PTR(pBuf->offBuffer, uint8_t);
902 uint32_t cbBuffer = pBuf->cbBuffer;
903
904 /* Execute the function. */
905 rc = crVBoxServerClientRead(u32ClientID, pBuffer, &cbBuffer);
906
907 if (RT_SUCCESS(rc))
908 {
909 /* Update parameters.*/
910// paParms[0].u.pointer.size = cbBuffer; //@todo guest doesn't see this change somehow?
911 } else if (VERR_NOT_SUPPORTED==rc)
912 {
913 svcClientVersionUnsupported(0, 0);
914 }
915
916 /* Return the required buffer size always */
917 pFnCmd->cbBuffer = cbBuffer;
918 }
919 else
920 {
921 Assert(0);
922 rc = VERR_INVALID_PARAMETER;
923 }
924
925 break;
926 }
927
928 case SHCRGL_GUEST_FN_WRITE_READ:
929 {
930 Log(("svcCall: SHCRGL_GUEST_FN_WRITE_READ\n"));
931
932 /* @todo: Verify */
933 if (cParams == 2)
934 {
935 CRVBOXHGSMIWRITEREAD *pFnCmd = (CRVBOXHGSMIWRITEREAD*)pHdr;
936 VBOXVDMACMD_CHROMIUM_BUFFER *pBuf = &pCmd->aBuffers[1];
937 VBOXVDMACMD_CHROMIUM_BUFFER *pWbBuf = &pCmd->aBuffers[2];
938
939 /* Fetch parameters. */
940 uint8_t *pBuffer = VBOXCRHGSMI_PTR(pBuf->offBuffer, uint8_t);
941 uint32_t cbBuffer = pBuf->cbBuffer;
942
943 uint8_t *pWriteback = VBOXCRHGSMI_PTR(pWbBuf->offBuffer, uint8_t);
944 uint32_t cbWriteback = pWbBuf->cbBuffer;
945
946 /* Execute the function. */
947 rc = crVBoxServerClientWrite(u32ClientID, pBuffer, cbBuffer);
948 if (!RT_SUCCESS(rc))
949 {
950 Assert(VERR_NOT_SUPPORTED==rc);
951 svcClientVersionUnsupported(0, 0);
952 }
953
954 rc = crVBoxServerClientRead(u32ClientID, pWriteback, &cbWriteback);
955
956// if (RT_SUCCESS(rc))
957// {
958// /* Update parameters.*/
959// paParms[1].u.pointer.size = cbWriteback;
960// }
961 /* Return the required buffer size always */
962 pFnCmd->cbWriteback = cbWriteback;
963 }
964 else
965 {
966 Assert(0);
967 rc = VERR_INVALID_PARAMETER;
968 }
969
970 break;
971 }
972
973 case SHCRGL_GUEST_FN_SET_VERSION:
974 {
975 Assert(0);
976 rc = VERR_NOT_IMPLEMENTED;
977 break;
978 }
979
980 case SHCRGL_GUEST_FN_SET_PID:
981 {
982 Assert(0);
983 rc = VERR_NOT_IMPLEMENTED;
984 break;
985 }
986
987 default:
988 {
989 Assert(0);
990 rc = VERR_NOT_IMPLEMENTED;
991 }
992
993 }
994
995 pHdr->result = rc;
996
997 return VINF_SUCCESS;
998}
999#endif
1000
1001/*
1002 * We differentiate between a function handler for the guest and one for the host.
1003 */
1004static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
1005{
1006 int rc = VINF_SUCCESS;
1007
1008 Log(("SHARED_CROPENGL svcHostCall: fn = %d, cParms = %d, pparms = %d\n", u32Function, cParms, paParms));
1009
1010#ifdef DEBUG
1011 uint32_t i;
1012
1013 for (i = 0; i < cParms; i++)
1014 {
1015 /** @todo parameters other than 32 bit */
1016 Log((" pparms[%d]: type %d value %d\n", i, paParms[i].type, paParms[i].u.uint32));
1017 }
1018#endif
1019
1020 switch (u32Function)
1021 {
1022#ifdef VBOX_WITH_CRHGSMI
1023 case SHCRGL_HOST_FN_CRHGSMI_CMD:
1024 {
1025 Assert(cParms == 1 && paParms[0].type == VBOX_HGCM_SVC_PARM_PTR);
1026 if (cParms == 1 && paParms[0].type == VBOX_HGCM_SVC_PARM_PTR)
1027 rc = vboxCrHgsmiCmd((PVBOXVDMACMD_CHROMIUM_CMD)paParms[0].u.pointer.addr);
1028 else
1029 rc = VERR_INVALID_PARAMETER;
1030 } break;
1031 case SHCRGL_HOST_FN_CRHGSMI_CTL:
1032 {
1033 Assert(cParms == 1 && paParms[0].type == VBOX_HGCM_SVC_PARM_PTR);
1034 if (cParms == 1 && paParms[0].type == VBOX_HGCM_SVC_PARM_PTR)
1035 rc = vboxCrHgsmiCtl((PVBOXVDMACMD_CHROMIUM_CTL)paParms[0].u.pointer.addr);
1036 else
1037 rc = VERR_INVALID_PARAMETER;
1038 } break;
1039#endif
1040 case SHCRGL_HOST_FN_SET_CONSOLE:
1041 {
1042 Log(("svcCall: SHCRGL_HOST_FN_SET_DISPLAY\n"));
1043
1044 /* Verify parameter count and types. */
1045 if (cParms != SHCRGL_CPARMS_SET_CONSOLE)
1046 {
1047 rc = VERR_INVALID_PARAMETER;
1048 }
1049 else if (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)
1050 {
1051 rc = VERR_INVALID_PARAMETER;
1052 }
1053 else
1054 {
1055 /* Fetch parameters. */
1056 IConsole* pConsole = (IConsole*)paParms[0].u.pointer.addr;
1057 uint32_t cbData = paParms[0].u.pointer.size;
1058
1059 /* Verify parameters values. */
1060 if (cbData != sizeof (IConsole*))
1061 {
1062 rc = VERR_INVALID_PARAMETER;
1063 }
1064 else if (!pConsole)
1065 {
1066 rc = VERR_INVALID_PARAMETER;
1067 }
1068 else /* Execute the function. */
1069 {
1070 ComPtr<IMachine> pMachine;
1071 ComPtr<IDisplay> pDisplay;
1072 ComPtr<IFramebuffer> pFramebuffer;
1073 LONG xo, yo;
1074 LONG64 winId = 0;
1075 ULONG monitorCount, i, w, h;
1076
1077 CHECK_ERROR_BREAK(pConsole, COMGETTER(Machine)(pMachine.asOutParam()));
1078 CHECK_ERROR_BREAK(pMachine, COMGETTER(MonitorCount)(&monitorCount));
1079 CHECK_ERROR_BREAK(pConsole, COMGETTER(Display)(pDisplay.asOutParam()));
1080
1081 rc = crVBoxServerSetScreenCount(monitorCount);
1082 AssertRCReturn(rc, rc);
1083
1084 for (i=0; i<monitorCount; ++i)
1085 {
1086 CHECK_ERROR_RET(pDisplay, GetFramebuffer(i, pFramebuffer.asOutParam(), &xo, &yo), rc);
1087
1088 if (!pDisplay)
1089 {
1090 rc = crVBoxServerUnmapScreen(i);
1091 AssertRCReturn(rc, rc);
1092 }
1093 else
1094 {
1095 CHECK_ERROR_RET(pFramebuffer, COMGETTER(WinId)(&winId), rc);
1096 CHECK_ERROR_RET(pFramebuffer, COMGETTER(Width)(&w), rc);
1097 CHECK_ERROR_RET(pFramebuffer, COMGETTER(Height)(&h), rc);
1098
1099 rc = crVBoxServerMapScreen(i, xo, yo, w, h, winId);
1100 AssertRCReturn(rc, rc);
1101 }
1102 }
1103
1104 g_pConsole = pConsole;
1105 rc = VINF_SUCCESS;
1106 }
1107 }
1108 break;
1109 }
1110 case SHCRGL_HOST_FN_SET_VM:
1111 {
1112 Log(("svcCall: SHCRGL_HOST_FN_SET_VM\n"));
1113
1114 /* Verify parameter count and types. */
1115 if (cParms != SHCRGL_CPARMS_SET_VM)
1116 {
1117 rc = VERR_INVALID_PARAMETER;
1118 }
1119 else if (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)
1120 {
1121 rc = VERR_INVALID_PARAMETER;
1122 }
1123 else
1124 {
1125 /* Fetch parameters. */
1126 PVM pVM = (PVM)paParms[0].u.pointer.addr;
1127 uint32_t cbData = paParms[0].u.pointer.size;
1128
1129 /* Verify parameters values. */
1130 if (cbData != sizeof (PVM))
1131 {
1132 rc = VERR_INVALID_PARAMETER;
1133 }
1134 else
1135 {
1136 /* Execute the function. */
1137 g_pVM = pVM;
1138 rc = VINF_SUCCESS;
1139 }
1140 }
1141 break;
1142 }
1143 case SHCRGL_HOST_FN_SET_VISIBLE_REGION:
1144 {
1145 Log(("svcCall: SHCRGL_HOST_FN_SET_VISIBLE_REGION\n"));
1146
1147 if (cParms != SHCRGL_CPARMS_SET_VISIBLE_REGION)
1148 {
1149 rc = VERR_INVALID_PARAMETER;
1150 break;
1151 }
1152
1153 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* pRects */
1154 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* cRects */
1155 )
1156 {
1157 rc = VERR_INVALID_PARAMETER;
1158 break;
1159 }
1160
1161 Assert(sizeof(RTRECT)==4*sizeof(GLint));
1162
1163 rc = crVBoxServerSetRootVisibleRegion(paParms[1].u.uint32, (GLint*)paParms[0].u.pointer.addr);
1164 break;
1165 }
1166 case SHCRGL_HOST_FN_SCREEN_CHANGED:
1167 {
1168 Log(("svcCall: SHCRGL_HOST_FN_SCREEN_CHANGED\n"));
1169
1170 /* Verify parameter count and types. */
1171 if (cParms != SHCRGL_CPARMS_SCREEN_CHANGED)
1172 {
1173 rc = VERR_INVALID_PARAMETER;
1174 }
1175 else if (paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT)
1176 {
1177 rc = VERR_INVALID_PARAMETER;
1178 }
1179 else
1180 {
1181 /* Fetch parameters. */
1182 uint32_t screenId = paParms[0].u.uint32;
1183
1184 /* Execute the function. */
1185 ComPtr<IDisplay> pDisplay;
1186 ComPtr<IFramebuffer> pFramebuffer;
1187 LONG xo, yo;
1188 LONG64 winId = 0;
1189 ULONG w, h;
1190
1191 Assert(g_pConsole);
1192 CHECK_ERROR_RET(g_pConsole, COMGETTER(Display)(pDisplay.asOutParam()), rc);
1193 CHECK_ERROR_RET(pDisplay, GetFramebuffer(screenId, pFramebuffer.asOutParam(), &xo, &yo), rc);
1194
1195 if (!pFramebuffer)
1196 {
1197 rc = crVBoxServerUnmapScreen(screenId);
1198 AssertRCReturn(rc, rc);
1199 }
1200 else
1201 {
1202 CHECK_ERROR_RET(pFramebuffer, COMGETTER(WinId)(&winId), rc);
1203 CHECK_ERROR_RET(pFramebuffer, COMGETTER(Width)(&w), rc);
1204 CHECK_ERROR_RET(pFramebuffer, COMGETTER(Height)(&h), rc);
1205
1206 rc = crVBoxServerMapScreen(screenId, xo, yo, w, h, winId);
1207 AssertRCReturn(rc, rc);
1208 }
1209
1210 rc = VINF_SUCCESS;
1211 }
1212 break;
1213 }
1214 default:
1215 rc = VERR_NOT_IMPLEMENTED;
1216 break;
1217 }
1218
1219 LogFlow(("svcHostCall: rc = %Rrc\n", rc));
1220 return rc;
1221}
1222
1223extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable)
1224{
1225 int rc = VINF_SUCCESS;
1226
1227 Log(("SHARED_CROPENGL VBoxHGCMSvcLoad: ptable = %p\n", ptable));
1228
1229 if (!ptable)
1230 {
1231 rc = VERR_INVALID_PARAMETER;
1232 }
1233 else
1234 {
1235 Log(("VBoxHGCMSvcLoad: ptable->cbSize = %d, ptable->u32Version = 0x%08X\n", ptable->cbSize, ptable->u32Version));
1236
1237 if ( ptable->cbSize != sizeof (VBOXHGCMSVCFNTABLE)
1238 || ptable->u32Version != VBOX_HGCM_SVC_VERSION)
1239 {
1240 rc = VERR_INVALID_PARAMETER;
1241 }
1242 else
1243 {
1244 g_pHelpers = ptable->pHelpers;
1245
1246 ptable->cbClient = sizeof (void*);
1247
1248 ptable->pfnUnload = svcUnload;
1249 ptable->pfnConnect = svcConnect;
1250 ptable->pfnDisconnect = svcDisconnect;
1251 ptable->pfnCall = svcCall;
1252 ptable->pfnHostCall = svcHostCall;
1253 ptable->pfnSaveState = svcSaveState;
1254 ptable->pfnLoadState = svcLoadState;
1255 ptable->pvService = NULL;
1256
1257 if (!crVBoxServerInit())
1258 return VERR_NOT_SUPPORTED;
1259
1260 crVBoxServerSetPresentFBOCB(svcPresentFBO);
1261 }
1262 }
1263
1264 return rc;
1265}
1266
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