diff options
Diffstat (limited to 'src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp')
| -rw-r--r-- | src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp | 429 |
1 files changed, 368 insertions, 61 deletions
diff --git a/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp b/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp index b63f788a..77ddf197 100644 --- a/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp +++ b/src/VBox/HostServices/SharedOpenGL/crserver/crservice.cpp @@ -5,7 +5,7 @@ */ /* - * Copyright (C) 2006-2008 Oracle Corporation + * Copyright (C) 2006-2012 Oracle Corporation * * This file is part of VirtualBox Open Source Edition (OSE), as * available from http://www.virtualbox.org. This file is free software; @@ -18,50 +18,31 @@ #define __STDC_CONSTANT_MACROS /* needed for a definition in iprt/string.h */ -#ifdef RT_OS_WINDOWS -# include <iprt/alloc.h> -# include <iprt/string.h> -# include <iprt/assert.h> -# include <iprt/stream.h> -# include <VBox/vmm/ssm.h> -# include <VBox/hgcmsvc.h> -# include <VBox/HostServices/VBoxCrOpenGLSvc.h> -# include "cr_server.h" -# define LOG_GROUP LOG_GROUP_SHARED_CROPENGL -# include <VBox/log.h> - -# include <VBox/com/com.h> -# include <VBox/com/string.h> -# include <VBox/com/array.h> -# include <VBox/com/Guid.h> -# include <VBox/com/ErrorInfo.h> -# include <VBox/com/EventQueue.h> -# include <VBox/com/VirtualBox.h> -# include <VBox/com/assert.h> - -#else -# include <VBox/com/VirtualBox.h> -# include <iprt/assert.h> -# include <VBox/vmm/ssm.h> -# include <VBox/hgcmsvc.h> -# include <VBox/HostServices/VBoxCrOpenGLSvc.h> - -# include "cr_server.h" -# define LOG_GROUP LOG_GROUP_SHARED_CROPENGL -# include <VBox/log.h> -# include <VBox/com/ErrorInfo.h> -#endif /* RT_OS_WINDOWS */ +#define LOG_GROUP LOG_GROUP_SHARED_CROPENGL -#include <VBox/com/errorprint.h> -#include <iprt/thread.h> +#include <iprt/assert.h> +#include <iprt/asm.h> #include <iprt/critsect.h> +#include <iprt/mem.h> #include <iprt/semaphore.h> -#include <iprt/asm.h> +#include <iprt/stream.h> +#include <iprt/string.h> +#include <iprt/thread.h> + +#include <VBox/hgcmsvc.h> +#include <VBox/log.h> +#include <VBox/com/ErrorInfo.h> +#include <VBox/com/VirtualBox.h> +#include <VBox/com/errorprint.h> +#include <VBox/HostServices/VBoxCrOpenGLSvc.h> +#include <VBox/vmm/ssm.h> #include "cr_mem.h" +#include "cr_server.h" PVBOXHGCMSVCHELPERS g_pHelpers; static IConsole* g_pConsole = NULL; +static uint32_t g_u32ScreenCount = 0; static PVM g_pVM = NULL; #ifndef RT_OS_WINDOWS @@ -244,6 +225,29 @@ static int svcPresentFBOTearDown(void) return rc; } +static DECLCALLBACK(void) svcNotifyEventCB(int32_t screenId, uint32_t uEvent, void*pvData) +{ + ComPtr<IDisplay> pDisplay; + ComPtr<IFramebuffer> pFramebuffer; + LONG xo, yo; + + if (!g_pConsole) + { + crWarning("Console not defined!"); + return; + } + + CHECK_ERROR2_STMT(g_pConsole, COMGETTER(Display)(pDisplay.asOutParam()), return); + + CHECK_ERROR2_STMT(pDisplay, GetFramebuffer(screenId, pFramebuffer.asOutParam(), &xo, &yo), return); + + if (!pFramebuffer) + return; + + pFramebuffer->Notify3DEvent(uEvent, (BYTE*)pvData); +} + + static DECLCALLBACK(int) svcUnload (void *) { int rc = VINF_SUCCESS; @@ -364,7 +368,7 @@ static DECLCALLBACK(int) svcLoadState(void *, uint32_t u32ClientID, void *pvClie LogRel(("SHARED_CROPENGL svcLoadState: unsupported save state version %d\n", ui32)); /*@todo ugly hack, as we don't know size of stored opengl data try to read untill end of opengl data marker*/ - /*VboxSharedCrOpenGL isn't last hgcm service now, so can't use SSMR3SkipToEndOfUnit*/ + /*VBoxSharedCrOpenGL isn't last hgcm service now, so can't use SSMR3SkipToEndOfUnit*/ { const char *pMatch = &gszVBoxOGLSSMMagic[0]; char current; @@ -472,7 +476,7 @@ static CRVBOXSVCBUFFER_t* svcGetBuffer(uint32_t iBuffer, uint32_t cbBufferSize) { if (pBuffer->uiId == iBuffer) { - if (pBuffer->uiSize!=cbBufferSize) + if (cbBufferSize && pBuffer->uiSize!=cbBufferSize) { static int shown=0; @@ -892,6 +896,30 @@ static DECLCALLBACK(void) svcCall (void *, VBOXHGCMCALLHANDLE callHandle, uint32 break; } + case SHCRGL_GUEST_FN_GET_CAPS: + { + Log(("svcCall: SHCRGL_GUEST_FN_GET_CAPS\n")); + + /* Verify parameter count and types. */ + if (cParms != SHCRGL_CPARMS_GET_CAPS) + { + rc = VERR_INVALID_PARAMETER; + } + else + if (paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT) + { + rc = VERR_INVALID_PARAMETER; + } + else + { + /* Execute the function. */ + rc = crVBoxServerClientGetCaps(u32ClientID, &paParms[0].u.uint32); + AssertRC(rc); + } + + break; + } + default: { rc = VERR_NOT_IMPLEMENTED; @@ -904,10 +932,36 @@ static DECLCALLBACK(void) svcCall (void *, VBOXHGCMCALLHANDLE callHandle, uint32 g_pHelpers->pfnCallComplete (callHandle, rc); } +static void crScreenshotHandle(CRVBOXHGCMTAKESCREENSHOT *pScreenshot, uint32_t idScreen, uint64_t u64Now) +{ + if (!pScreenshot->pfnScreenshotBegin || pScreenshot->pfnScreenshotBegin(pScreenshot->pvContext, idScreen, u64Now)) + { + CR_SCREENSHOT Screenshot; + + int rc = crServerVBoxScreenshotGet(idScreen, pScreenshot->u32Width, pScreenshot->u32Height, pScreenshot->u32Pitch, pScreenshot->pvBuffer, &Screenshot); + if (RT_SUCCESS(rc)) + { + if (pScreenshot->pfnScreenshotPerform) + pScreenshot->pfnScreenshotPerform(pScreenshot->pvContext, idScreen, + 0, 0, 32, + Screenshot.Img.pitch, Screenshot.Img.width, Screenshot.Img.height, + (uint8_t*)Screenshot.Img.pvData, u64Now); + crServerVBoxScreenshotRelease(&Screenshot); + } + else + { + Assert(rc == VERR_INVALID_STATE); + } + + if (pScreenshot->pfnScreenshotEnd) + pScreenshot->pfnScreenshotEnd(pScreenshot->pvContext, idScreen, u64Now); + } +} + /* * We differentiate between a function handler for the guest and one for the host. */ -static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) +static int svcHostCallPerform(uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) { int rc = VINF_SUCCESS; @@ -990,6 +1044,11 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa CHECK_ERROR_BREAK(pMachine, COMGETTER(MonitorCount)(&monitorCount)); CHECK_ERROR_BREAK(pConsole, COMGETTER(Display)(pDisplay.asOutParam())); + crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE); + + g_pConsole = pConsole; + g_u32ScreenCount = monitorCount; + rc = crVBoxServerSetScreenCount(monitorCount); AssertRCReturn(rc, rc); @@ -1013,7 +1072,7 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa } } - g_pConsole = pConsole; + crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE); rc = VINF_SUCCESS; } @@ -1064,16 +1123,15 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa } if ( paParms[0].type != VBOX_HGCM_SVC_PARM_PTR /* pRects */ - || paParms[1].type != VBOX_HGCM_SVC_PARM_32BIT /* cRects */ ) { rc = VERR_INVALID_PARAMETER; break; } - Assert(sizeof(RTRECT)==4*sizeof(GLint)); + Assert(sizeof (RTRECT) == 4 * sizeof (GLint)); - rc = crVBoxServerSetRootVisibleRegion(paParms[1].u.uint32, (GLint*)paParms[0].u.pointer.addr); + rc = crVBoxServerSetRootVisibleRegion(paParms[0].u.pointer.size / sizeof (RTRECT), (const RTRECT*)paParms[0].u.pointer.addr); break; } case SHCRGL_HOST_FN_SCREEN_CHANGED: @@ -1105,6 +1163,8 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa CHECK_ERROR_RET(g_pConsole, COMGETTER(Display)(pDisplay.asOutParam()), rc); CHECK_ERROR_RET(pDisplay, GetFramebuffer(screenId, pFramebuffer.asOutParam(), &xo, &yo), rc); + crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE); + if (!pFramebuffer) { rc = crVBoxServerUnmapScreen(screenId); @@ -1112,28 +1172,130 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa } else { - CHECK_ERROR_RET(pFramebuffer, COMGETTER(WinId)(&winId), rc); +#if 0 + CHECK_ERROR_RET(pFramebuffer, Lock(), rc); +#endif - if (!winId) - { - /* View associated with framebuffer is destroyed, happens with 2d accel enabled */ - rc = crVBoxServerUnmapScreen(screenId); - AssertRCReturn(rc, rc); - } - else - { - CHECK_ERROR_RET(pFramebuffer, COMGETTER(Width)(&w), rc); - CHECK_ERROR_RET(pFramebuffer, COMGETTER(Height)(&h), rc); + do { + /* determine if the framebuffer is functional */ + rc = pFramebuffer->Notify3DEvent(VBOX3D_NOTIFY_EVENT_TYPE_TEST_FUNCTIONAL, NULL); - rc = crVBoxServerMapScreen(screenId, xo, yo, w, h, winId); - AssertRCReturn(rc, rc); - } + if (rc == S_OK) + CHECK_ERROR_BREAK(pFramebuffer, COMGETTER(WinId)(&winId)); + + if (!winId) + { + /* View associated with framebuffer is destroyed, happens with 2d accel enabled */ + rc = crVBoxServerUnmapScreen(screenId); + AssertRCReturn(rc, rc); + } + else + { + CHECK_ERROR_BREAK(pFramebuffer, COMGETTER(Width)(&w)); + CHECK_ERROR_BREAK(pFramebuffer, COMGETTER(Height)(&h)); + + rc = crVBoxServerMapScreen(screenId, xo, yo, w, h, winId); + AssertRCReturn(rc, rc); + } + } while (0); +#if 0 + CHECK_ERROR_RET(pFramebuffer, Unlock(), rc); +#endif } + crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE); + rc = VINF_SUCCESS; } break; } + case SHCRGL_HOST_FN_TAKE_SCREENSHOT: + { + if (cParms != 1) + { + LogRel(("SHCRGL_HOST_FN_TAKE_SCREENSHOT: cParms invalid - %d", cParms)); + rc = VERR_INVALID_PARAMETER; + break; + } + + if (paParms->type != VBOX_HGCM_SVC_PARM_PTR) + { + AssertMsgFailed(("invalid param\n")); + rc = VERR_INVALID_PARAMETER; + break; + } + + if (!paParms->u.pointer.addr) + { + AssertMsgFailed(("invalid param\n")); + rc = VERR_INVALID_PARAMETER; + break; + } + + if (paParms->u.pointer.size != sizeof (CRVBOXHGCMTAKESCREENSHOT)) + { + AssertMsgFailed(("invalid param\n")); + rc = VERR_INVALID_PARAMETER; + break; + } + + CRVBOXHGCMTAKESCREENSHOT *pScreenshot = (CRVBOXHGCMTAKESCREENSHOT*)paParms->u.pointer.addr; + uint64_t u64Now = RTTimeProgramMilliTS(); + + if (pScreenshot->u32Screen == CRSCREEN_ALL) + { + for (uint32_t i = 0; i < g_u32ScreenCount; ++i) + { + crScreenshotHandle(pScreenshot, i, u64Now); + } + } + else if (pScreenshot->u32Screen < g_u32ScreenCount) + { + crScreenshotHandle(pScreenshot, pScreenshot->u32Screen, u64Now); + } + else + { + AssertMsgFailed(("invalid screen id\n")); + rc = VERR_INVALID_PARAMETER; + break; + } + break; + } + case SHCRGL_HOST_FN_DEV_RESIZE: + { + Log(("svcCall: SHCRGL_HOST_FN_DEV_RESIZE\n")); + + /* Verify parameter count and types. */ + if (cParms != SHCRGL_CPARMS_DEV_RESIZE) + { + LogRel(("SHCRGL_HOST_FN_DEV_RESIZE: cParms invalid - %d", cParms)); + rc = VERR_INVALID_PARAMETER; + break; + } + + if (paParms->type != VBOX_HGCM_SVC_PARM_PTR) + { + AssertMsgFailed(("invalid param\n")); + return VERR_INVALID_PARAMETER; + } + + if (!paParms->u.pointer.addr) + { + AssertMsgFailed(("invalid param\n")); + return VERR_INVALID_PARAMETER; + } + + if (paParms->u.pointer.size != sizeof (CRVBOXHGCMDEVRESIZE)) + { + AssertMsgFailed(("invalid param\n")); + return VERR_INVALID_PARAMETER; + } + + CRVBOXHGCMDEVRESIZE *pResize = (CRVBOXHGCMDEVRESIZE*)paParms->u.pointer.addr; + + rc = crVBoxServerNotifyResize(&pResize->Screen, pResize->pvVRAM); + break; + } case SHCRGL_HOST_FN_VIEWPORT_CHANGED: { Log(("svcCall: SHCRGL_HOST_FN_VIEWPORT_CHANGED\n")); @@ -1162,6 +1324,8 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa break; } + crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE); + rc = crVBoxServerSetScreenViewport((int)paParms[0].u.uint32, paParms[1].u.uint32, /* x */ paParms[2].u.uint32, /* y */ @@ -1170,9 +1334,52 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa if (!RT_SUCCESS(rc)) { LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: crVBoxServerSetScreenViewport failed, rc %d", rc)); + } + + crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE); + + break; + } + case SHCRGL_HOST_FN_VIEWPORT_CHANGED2: + { + Log(("svcCall: SHCRGL_HOST_FN_VIEWPORT_CHANGED\n")); + + /* Verify parameter count and types. */ + if (cParms != SHCRGL_CPARMS_VIEWPORT_CHANGED) + { + LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: cParms invalid - %d", cParms)); + rc = VERR_INVALID_PARAMETER; + break; + } + + if (paParms[0].type != VBOX_HGCM_SVC_PARM_PTR + || !paParms[0].u.pointer.addr + || paParms[0].u.pointer.size != sizeof (CRVBOXHGCMVIEWPORT)) + { + LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: param invalid - %d, %#x, %d", + paParms[0].type, + paParms[0].u.pointer.addr, + paParms[0].u.pointer.size)); + rc = VERR_INVALID_PARAMETER; break; } + crServerVBoxCompositionSetEnableStateGlobal(GL_FALSE); + + CRVBOXHGCMVIEWPORT *pViewportInfo = (CRVBOXHGCMVIEWPORT*)paParms[0].u.pointer.addr; + + rc = crVBoxServerSetScreenViewport(pViewportInfo->u32Screen, + pViewportInfo->x, /* x */ + pViewportInfo->y, /* y */ + pViewportInfo->width, /* w */ + pViewportInfo->height /* h */); + if (!RT_SUCCESS(rc)) + { + LogRel(("SHCRGL_HOST_FN_VIEWPORT_CHANGED: crVBoxServerSetScreenViewport failed, rc %d", rc)); + } + + crServerVBoxCompositionSetEnableStateGlobal(GL_TRUE); + break; } case SHCRGL_HOST_FN_SET_OUTPUT_REDIRECT: @@ -1207,9 +1414,7 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa } else /* Execute the function. */ { - rc = crVBoxServerSetOffscreenRendering(GL_TRUE); - - if (RT_SUCCESS(rc)) + if (pOutputRedirect->H3DORBegin != NULL) { CROutputRedirect outputRedirect; outputRedirect.pvContext = pOutputRedirect->pvContext; @@ -1220,11 +1425,44 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa outputRedirect.CROREnd = pOutputRedirect->H3DOREnd; outputRedirect.CRORContextProperty = pOutputRedirect->H3DORContextProperty; rc = crVBoxServerOutputRedirectSet(&outputRedirect); + if (RT_SUCCESS(rc)) + { + rc = crVBoxServerSetOffscreenRendering(GL_TRUE); + } + } + else + { + /* Redirection is disabled. */ + crVBoxServerSetOffscreenRendering(GL_FALSE); + crVBoxServerOutputRedirectSet(NULL); } } } break; } + case SHCRGL_HOST_FN_WINDOWS_SHOW: + { + /* Verify parameter count and types. */ + if (cParms != 1) + { + WARN(("invalid parameter")); + rc = VERR_INVALID_PARAMETER; + break; + } + + if (paParms[0].type != VBOX_HGCM_SVC_PARM_32BIT) + { + WARN(("invalid parameter")); + rc = VERR_INVALID_PARAMETER; + break; + } + + rc = crServerVBoxWindowsShow(paParms[0].u.uint32); + if (!RT_SUCCESS(rc)) + WARN(("crServerVBoxWindowsShow failed rc %d", rc)); + + break; + } default: rc = VERR_NOT_IMPLEMENTED; break; @@ -1234,6 +1472,73 @@ static DECLCALLBACK(int) svcHostCall (void *, uint32_t u32Function, uint32_t cPa return rc; } +int crVBoxServerHostCtl(VBOXCRCMDCTL *pCtl, uint32_t cbCtl) +{ + if ((cbCtl - sizeof (VBOXCRCMDCTL)) % sizeof(VBOXHGCMSVCPARM)) + { + WARN(("invalid param size")); + return VERR_INVALID_PARAMETER; + } + uint32_t cParams = (cbCtl - sizeof (VBOXCRCMDCTL)) / sizeof (VBOXHGCMSVCPARM); + return svcHostCallPerform(pCtl->u32Function, cParams, (VBOXHGCMSVCPARM*)(pCtl + 1)); +} + +static DECLCALLBACK(int) svcHostCall(void *, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[]) +{ + switch (u32Function) + { + case SHCRGL_HOST_FN_CTL: + { + if (cParms != 1) + { + WARN(("cParams != 1")); + return VERR_INVALID_PARAMETER; + } + + if (paParms->type != VBOX_HGCM_SVC_PARM_PTR) + { + WARN(("invalid param type")); + return VERR_INVALID_PARAMETER; + } + + if (paParms->u.pointer.size < sizeof (VBOXCRCMDCTL)) + { + WARN(("invalid param size")); + return VERR_INVALID_PARAMETER; + } + + VBOXCRCMDCTL *pCtl = (VBOXCRCMDCTL*)paParms->u.pointer.addr; + switch (pCtl->enmType) + { + case VBOXCRCMDCTL_TYPE_HGCM: + { + return crVBoxServerHostCtl(pCtl, paParms->u.pointer.size); + } + case VBOXCRCMDCTL_TYPE_DISABLE: + { + if (paParms->u.pointer.size != sizeof (VBOXCRCMDCTL)) + WARN(("invalid param size")); + return crVBoxServerHgcmDisable(); + } + case VBOXCRCMDCTL_TYPE_ENABLE: + { + if (paParms->u.pointer.size != sizeof (VBOXCRCMDCTL_ENABLE)) + WARN(("invalid param size")); + VBOXCRCMDCTL_ENABLE *pEnable = (VBOXCRCMDCTL_ENABLE*)pCtl; + return crVBoxServerHgcmEnable(pEnable->hRHCmd, pEnable->pfnRHCmd); + } + default: + WARN(("invalid function")); + return VERR_INVALID_PARAMETER; + } + WARN(("should not be here!")); + return VERR_INTERNAL_ERROR; + } + default: + return svcHostCallPerform(u32Function, cParms, paParms); + } +} + extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *ptable) { int rc = VINF_SUCCESS; @@ -1272,6 +1577,8 @@ extern "C" DECLCALLBACK(DECLEXPORT(int)) VBoxHGCMSvcLoad (VBOXHGCMSVCFNTABLE *pt return VERR_NOT_SUPPORTED; rc = svcPresentFBOInit(); + + crServerVBoxSetNotifyEventCB(svcNotifyEventCB); } } |
