VirtualBox

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

Last change on this file since 22538 was 22502, checked in by vboxsync, 15 years ago

crOpenGL: Allow 64bit window ids for the parent window.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 16.9 KB
Line 
1/* $Id: crservice.cpp 22502 2009-08-27 10:05:18Z vboxsync $ */
2
3/** @file
4 * VBox crOpenGL: Host service entry points.
5 */
6
7/*
8 * Copyright (C) 2006-2008 Sun Microsystems, Inc.
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 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
19 * Clara, CA 95054 USA or visit http://www.sun.com if you need
20 * additional information or have any questions.
21 */
22
23#define __STDC_CONSTANT_MACROS /* needed for a definition in iprt/string.h */
24
25#ifdef RT_OS_WINDOWS
26#include <iprt/alloc.h>
27#include <iprt/string.h>
28#include <iprt/assert.h>
29#include <iprt/stream.h>
30#include <VBox/ssm.h>
31#include <VBox/hgcmsvc.h>
32#include <VBox/HostServices/VBoxCrOpenGLSvc.h>
33#include "cr_server.h"
34#define LOG_GROUP LOG_GROUP_SHARED_CROPENGL
35#include <VBox/log.h>
36
37#include <VBox/com/com.h>
38#include <VBox/com/string.h>
39#include <VBox/com/array.h>
40#include <VBox/com/Guid.h>
41#include <VBox/com/ErrorInfo.h>
42#include <VBox/com/EventQueue.h>
43#include <VBox/com/VirtualBox.h>
44#include <VBox/com/assert.h>
45
46#else
47#include <VBox/com/VirtualBox.h>
48#include <iprt/assert.h>
49#include <VBox/ssm.h>
50#include <VBox/hgcmsvc.h>
51#include <VBox/HostServices/VBoxCrOpenGLSvc.h>
52
53#include "cr_server.h"
54#define LOG_GROUP LOG_GROUP_SHARED_CROPENGL
55#include <VBox/log.h>
56#endif
57
58#include "render/renderspu.h"
59
60PVBOXHGCMSVCHELPERS g_pHelpers;
61static IFramebuffer* g_pFrameBuffer;
62static PVM g_pVM = NULL;
63static ULONG64 g_winId = 0;
64
65#ifndef RT_OS_WINDOWS
66#define DWORD int
67#define WINAPI
68#endif
69
70#define CR_USE_HGCM
71
72static const char* gszVBoxOGLSSMMagic = "***OpenGL state data***";
73#define SHCROGL_SSM_VERSION 6
74
75typedef struct
76{
77 DWORD dwThreadID;
78
79} VBOXOGLCTX, *PVBOXOGLCTX;
80
81/*@todo remove this workaround for crstate "unshareable" data*/
82static int crIsThreadWorking=0;
83
84static DWORD WINAPI crServerProc(void* pv)
85{
86 uint64_t winId = *((uint64_t*)pv);
87 renderspuSetWindowId(winId);
88 CRServerMain(0, NULL);
89 crIsThreadWorking = 0;
90 return 0;
91}
92
93
94static DECLCALLBACK(int) svcUnload (void *)
95{
96 int rc = VINF_SUCCESS;
97
98 Log(("SHARED_CROPENGL svcUnload\n"));
99
100 //vboxglGlobalUnload();
101 crVBoxServerTearDown();
102
103 return rc;
104}
105
106static DECLCALLBACK(int) svcConnect (void *, uint32_t u32ClientID, void *pvClient)
107{
108 int rc = VINF_SUCCESS;
109
110 NOREF(u32ClientID);
111 VBOXOGLCTX *pClient = (VBOXOGLCTX *)pvClient;
112 Assert(pClient);
113
114 Log(("SHARED_CROPENGL svcConnect: u32ClientID = %d\n", u32ClientID));
115
116#ifndef CR_USE_HGCM
117 if (!crIsThreadWorking)
118 {
119 HANDLE h;
120 Assert(g_pFrameBuffer);
121
122 g_pFrameBuffer->COMGETTER(WinId)(&g_winId);
123 //CHECK_ERROR_RET(g_piConsole, COMGETTER(Display)(display.asOutParam()), rc);
124
125 //vboxglConnect((PVBOXOGLCTX)pvClient);
126 crIsThreadWorking=1;
127 h = CreateThread(NULL, 0, crServerProc, (void*)&g_winId, 0, &pClient->dwThreadID);
128 if (!h) rc = VERR_MAX_THRDS_REACHED;
129 }
130 else
131 rc = VERR_MAX_THRDS_REACHED;
132#else
133 g_pFrameBuffer->COMGETTER(WinId)(&g_winId);
134 renderspuSetWindowId(g_winId);
135 rc = crVBoxServerAddClient(u32ClientID);
136#endif
137
138 return rc;
139}
140
141static DECLCALLBACK(int) svcDisconnect (void *, uint32_t u32ClientID, void *pvClient)
142{
143 int rc = VINF_SUCCESS;
144 VBOXOGLCTX *pClient = (VBOXOGLCTX *)pvClient;
145 Assert(pClient);
146
147 Log(("SHARED_CROPENGL svcDisconnect: u32ClientID = %d\n", u32ClientID));
148
149#ifndef CR_USE_HGCM
150 if (crIsThreadWorking && pClient->dwThreadID)
151 PostThreadMessage(pClient->dwThreadID, WM_QUIT, 0, 0);
152#else
153 crVBoxServerRemoveClient(u32ClientID);
154#endif
155 //vboxglDisconnect((PVBOXOGLCTX)pvClient);
156 return rc;
157}
158
159static DECLCALLBACK(int) svcSaveState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
160{
161 VBOXOGLCTX *pClient = (VBOXOGLCTX *)pvClient;
162
163 NOREF(pClient);
164
165 Log(("SHARED_CROPENGL svcSaveState: u32ClientID = %d\n", u32ClientID));
166
167 int rc;
168
169 /* Start*/
170 rc = SSMR3PutStrZ(pSSM, gszVBoxOGLSSMMagic);
171 AssertRCReturn(rc, rc);
172
173 /* Version */
174 rc = SSMR3PutU32(pSSM, (uint32_t) SHCROGL_SSM_VERSION);
175 AssertRCReturn(rc, rc);
176
177 /* The state itself */
178 rc = crVBoxServerSaveState(pSSM);
179 AssertRCReturn(rc, rc);
180
181 /* End */
182 rc = SSMR3PutStrZ(pSSM, gszVBoxOGLSSMMagic);
183 AssertRCReturn(rc, rc);
184
185 return VINF_SUCCESS;
186}
187
188static DECLCALLBACK(int) svcLoadState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
189{
190 VBOXOGLCTX *pClient = (VBOXOGLCTX *)pvClient;
191
192 NOREF(pClient);
193 NOREF(pSSM);
194
195 Log(("SHARED_CROPENGL svcLoadState: u32ClientID = %d\n", u32ClientID));
196
197 char psz[2000];
198 int rc;
199 uint32_t ui32;
200
201 /* Start of data */
202 rc = SSMR3GetStrZEx(pSSM, psz, 2000, NULL);
203 AssertRCReturn(rc, rc);
204 if (strcmp(gszVBoxOGLSSMMagic, psz))
205 return VERR_SSM_UNEXPECTED_DATA;
206
207 /* Version */
208 rc = SSMR3GetU32(pSSM, &ui32);
209 AssertRCReturn(rc, rc);
210 if ((SHCROGL_SSM_VERSION != ui32)
211 && ((SHCROGL_SSM_VERSION!=4) || (3!=ui32)))
212 {
213 /*@todo: add some warning here*/
214 /*@todo: in many cases saved states would be made without any opengl guest app running.
215 * that means we could safely restore the default context.
216 */
217 rc = SSMR3SkipToEndOfUnit(pSSM);
218 return rc;
219 }
220
221 /* The state itself */
222 rc = crVBoxServerLoadState(pSSM, ui32);
223 AssertRCReturn(rc, rc);
224
225 /* End of data */
226 rc = SSMR3GetStrZEx(pSSM, psz, 2000, NULL);
227 AssertRCReturn(rc, rc);
228 if (strcmp(gszVBoxOGLSSMMagic, psz))
229 return VERR_SSM_UNEXPECTED_DATA;
230
231 return VINF_SUCCESS;
232}
233
234static void svcClientVersionUnsupported(uint32_t minor, uint32_t major)
235{
236 LogRel(("SHARED_CROPENGL: unsupported client version %d.%d\n", minor, major));
237
238 /*MS's opengl32 tryes to load our ICD around 30 times on failure...this is to prevent unnecessary spam*/
239 static int shown = 0;
240
241 if (g_pVM && !shown)
242 {
243 VMSetRuntimeError(g_pVM, VMSETRTERR_FLAGS_NO_WAIT, "3DSupportIncompatibleAdditions",
244 "Guest application attempt to use hardware 3D acceleration failed, because"
245 " guest additions version doesn't match VirtualBox host version."
246 "Please install appropriate guest additions to fix this issue");
247 shown = 1;
248 }
249}
250
251static DECLCALLBACK(void) svcCall (void *, VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, void *pvClient, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
252{
253 int rc = VINF_SUCCESS;
254
255 Log(("SHARED_CROPENGL svcCall: u32ClientID = %d, fn = %d, cParms = %d, pparms = %d\n", u32ClientID, u32Function, cParms, paParms));
256
257 VBOXOGLCTX *pClient = (VBOXOGLCTX *)pvClient;
258
259#ifdef DEBUG
260 uint32_t i;
261
262 for (i = 0; i < cParms; i++)
263 {
264 /** @todo parameters other than 32 bit */
265 Log((" pparms[%d]: type %d value %d\n", i, paParms[i].type, paParms[i].u.uint32));
266 }
267#endif
268
269 switch (u32Function)
270 {
271 case SHCRGL_GUEST_FN_WRITE:
272 {
273 Log(("svcCall: SHCRGL_GUEST_FN_WRITE\n"));
274
275 /* Verify parameter count and types. */
276 if (cParms != SHCRGL_CPARMS_WRITE)
277 {
278 rc = VERR_INVALID_PARAMETER;
279 }
280 else
281 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* pBuffer */
282 )
283 {
284 rc = VERR_INVALID_PARAMETER;
285 }
286 else
287 {
288 /* Fetch parameters. */
289 uint8_t *pBuffer = (uint8_t *)paParms[0].u.pointer.addr;
290 uint32_t cbBuffer = paParms[0].u.pointer.size;
291
292 /* Execute the function. */
293 rc = crVBoxServerClientWrite(u32ClientID, pBuffer, cbBuffer);
294 if (!RT_SUCCESS(rc))
295 {
296 Assert(VERR_NOT_SUPPORTED==rc);
297 svcClientVersionUnsupported(0, 0);
298 }
299
300 }
301 break;
302 }
303
304 case SHCRGL_GUEST_FN_READ:
305 {
306 Log(("svcCall: SHCRGL_GUEST_FN_READ\n"));
307
308 /* Verify parameter count and types. */
309 if (cParms != SHCRGL_CPARMS_READ)
310 {
311 rc = VERR_INVALID_PARAMETER;
312 }
313 else
314 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* pBuffer */
315 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* cbBuffer */
316 )
317 {
318 rc = VERR_INVALID_PARAMETER;
319 }
320
321 /* Fetch parameters. */
322 uint8_t *pBuffer = (uint8_t *)paParms[0].u.pointer.addr;
323 uint32_t cbBuffer = paParms[0].u.pointer.size;
324
325 /* Execute the function. */
326 rc = crVBoxServerClientRead(u32ClientID, pBuffer, &cbBuffer);
327
328 if (RT_SUCCESS(rc))
329 {
330 /* Update parameters.*/
331 paParms[0].u.pointer.size = cbBuffer; //@todo guest doesn't see this change somehow?
332 } else if (VERR_NOT_SUPPORTED==rc)
333 {
334 svcClientVersionUnsupported(0, 0);
335 }
336
337 /* Return the required buffer size always */
338 paParms[1].u.uint32 = cbBuffer;
339
340 break;
341 }
342
343 case SHCRGL_GUEST_FN_WRITE_READ:
344 {
345 Log(("svcCall: SHCRGL_GUEST_FN_WRITE_READ\n"));
346
347 /* Verify parameter count and types. */
348 if (cParms != SHCRGL_CPARMS_WRITE_READ)
349 {
350 rc = VERR_INVALID_PARAMETER;
351 }
352 else
353 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* pBuffer */
354 || paParms[1].type != VBOX_HGCM_SVC_PARM_PTR /* pWriteback */
355 || paParms[2].type != VBOX_HGCM_SVC_PARM_32BIT /* cbWriteback */
356 )
357 {
358 rc = VERR_INVALID_PARAMETER;
359 }
360 else
361 {
362 /* Fetch parameters. */
363 uint8_t *pBuffer = (uint8_t *)paParms[0].u.pointer.addr;
364 uint32_t cbBuffer = paParms[0].u.pointer.size;
365
366 uint8_t *pWriteback = (uint8_t *)paParms[1].u.pointer.addr;
367 uint32_t cbWriteback = paParms[1].u.pointer.size;
368
369 /* Execute the function. */
370 rc = crVBoxServerClientWrite(u32ClientID, pBuffer, cbBuffer);
371 if (!RT_SUCCESS(rc))
372 {
373 Assert(VERR_NOT_SUPPORTED==rc);
374 svcClientVersionUnsupported(0, 0);
375 }
376
377 rc = crVBoxServerClientRead(u32ClientID, pWriteback, &cbWriteback);
378
379 if (RT_SUCCESS(rc))
380 {
381 /* Update parameters.*/
382 paParms[1].u.pointer.size = cbWriteback;
383 }
384 /* Return the required buffer size always */
385 paParms[2].u.uint32 = cbWriteback;
386 }
387 break;
388 }
389
390 case SHCRGL_GUEST_FN_SET_VERSION:
391 {
392 Log(("svcCall: SHCRGL_GUEST_FN_SET_VERSION\n"));
393
394 /* Verify parameter count and types. */
395 if (cParms != SHCRGL_CPARMS_SET_VERSION)
396 {
397 rc = VERR_INVALID_PARAMETER;
398 }
399 else
400 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT /* vMajor */
401 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* vMinor */
402 )
403 {
404 rc = VERR_INVALID_PARAMETER;
405 }
406 else
407 {
408 /* Fetch parameters. */
409 uint32_t vMajor = paParms[0].u.uint32;
410 uint32_t vMinor = paParms[1].u.uint32;
411
412 /* Execute the function. */
413 rc = crVBoxServerClientSetVersion(u32ClientID, vMajor, vMinor);
414
415 if (!RT_SUCCESS(rc))
416 {
417 svcClientVersionUnsupported(vMajor, vMinor);
418 }
419 }
420
421 break;
422 }
423
424 default:
425 {
426 rc = VERR_NOT_IMPLEMENTED;
427 }
428 }
429
430
431 LogFlow(("svcCall: rc = %Rrc\n", rc));
432
433 g_pHelpers->pfnCallComplete (callHandle, rc);
434}
435
436/*
437 * We differentiate between a function handler for the guest and one for the host.
438 */
439static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
440{
441 int rc = VINF_SUCCESS;
442
443 Log(("SHARED_CROPENGL svcHostCall: fn = %d, cParms = %d, pparms = %d\n", u32Function, cParms, paParms));
444
445#ifdef DEBUG
446 uint32_t i;
447
448 for (i = 0; i < cParms; i++)
449 {
450 /** @todo parameters other than 32 bit */
451 Log((" pparms[%d]: type %d value %d\n", i, paParms[i].type, paParms[i].u.uint32));
452 }
453#endif
454
455 switch (u32Function)
456 {
457 case SHCRGL_HOST_FN_SET_FRAMEBUFFER:
458 {
459 Log(("svcCall: SHCRGL_HOST_FN_SET_FRAMEBUFFER\n"));
460
461 /* Verify parameter count and types. */
462 if (cParms != SHCRGL_CPARMS_SET_FRAMEBUFFER)
463 {
464 rc = VERR_INVALID_PARAMETER;
465 }
466 else if (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)
467 {
468 rc = VERR_INVALID_PARAMETER;
469 }
470 else
471 {
472 /* Fetch parameters. */
473 IFramebuffer* pFrameBuffer = (IFramebuffer*)paParms[0].u.pointer.addr;
474 uint32_t cbData = paParms[0].u.pointer.size;
475
476 /* Verify parameters values. */
477 if (cbData != sizeof (IFramebuffer*))
478 {
479 rc = VERR_INVALID_PARAMETER;
480 }
481 else
482 {
483 /* Execute the function. */
484 g_pFrameBuffer = pFrameBuffer;
485 rc = VINF_SUCCESS;
486 }
487 }
488 break;
489 }
490 case SHCRGL_HOST_FN_SET_VM:
491 {
492 Log(("svcCall: SHCRGL_HOST_FN_SET_VM\n"));
493
494 /* Verify parameter count and types. */
495 if (cParms != SHCRGL_CPARMS_SET_VM)
496 {
497 rc = VERR_INVALID_PARAMETER;
498 }
499 else if (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR)
500 {
501 rc = VERR_INVALID_PARAMETER;
502 }
503 else
504 {
505 /* Fetch parameters. */
506 PVM pVM = (PVM)paParms[0].u.pointer.addr;
507 uint32_t cbData = paParms[0].u.pointer.size;
508
509 /* Verify parameters values. */
510 if (cbData != sizeof (PVM))
511 {
512 rc = VERR_INVALID_PARAMETER;
513 }
514 else
515 {
516 /* Execute the function. */
517 g_pVM = pVM;
518 rc = VINF_SUCCESS;
519 }
520 }
521 break;
522 }
523 case SHCRGL_HOST_FN_SET_VISIBLE_REGION:
524 {
525 Log(("svcCall: SHCRGL_HOST_FN_SET_VISIBLE_REGION\n"));
526
527 if (cParms != SHCRGL_CPARMS_SET_VISIBLE_REGION)
528 {
529 rc = VERR_INVALID_PARAMETER;
530 break;
531 }
532
533 if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* pRects */
534 || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* cRects */
535 )
536 {
537 rc = VERR_INVALID_PARAMETER;
538 break;
539 }
540
541 Assert(sizeof(RTRECT)==4*sizeof(GLint));
542
543 renderspuSetRootVisibleRegion(paParms[1].u.uint32, (GLint*)paParms[0].u.pointer.addr);
544 break;
545 }
546 default:
547 rc = VERR_NOT_IMPLEMENTED;
548 break;
549 }
550
551 LogFlow(("svcHostCall: rc = %Rrc\n", rc));
552 return rc;
553}
554
555extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable)
556{
557 int rc = VINF_SUCCESS;
558
559 Log(("SHARED_CROPENGL VBoxHGCMSvcLoad: ptable = %p\n", ptable));
560
561 if (!ptable)
562 {
563 rc = VERR_INVALID_PARAMETER;
564 }
565 else
566 {
567 Log(("VBoxHGCMSvcLoad: ptable->cbSize = %d, ptable->u32Version = 0x%08X\n", ptable->cbSize, ptable->u32Version));
568
569 if ( ptable->cbSize != sizeof (VBOXHGCMSVCFNTABLE)
570 || ptable->u32Version != VBOX_HGCM_SVC_VERSION)
571 {
572 rc = VERR_INVALID_PARAMETER;
573 }
574 else
575 {
576 g_pHelpers = ptable->pHelpers;
577
578 ptable->cbClient = sizeof (VBOXOGLCTX);
579
580 ptable->pfnUnload = svcUnload;
581 ptable->pfnConnect = svcConnect;
582 ptable->pfnDisconnect = svcDisconnect;
583 ptable->pfnCall = svcCall;
584 ptable->pfnHostCall = svcHostCall;
585 ptable->pfnSaveState = svcSaveState;
586 ptable->pfnLoadState = svcLoadState;
587 ptable->pvService = NULL;
588#ifdef CR_USE_HGCM
589 if (!crVBoxServerInit())
590 return VERR_NOT_SUPPORTED;
591#endif
592 }
593 }
594
595 return rc;
596}
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