VirtualBox

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

Last change on this file since 50913 was 50913, checked in by vboxsync, 11 years ago

wddm/graphics: new command submission working for 2D, more testing needed

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