crservice.cpp revision 2609df5222cfcceb51ec536b2e3173b7227a232a
/* $Id$ */
/** @file
* VBox crOpenGL: Host service entry points.
*/
/*
* Copyright (C) 2006-2008 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
#define __STDC_CONSTANT_MACROS /* needed for a definition in iprt/string.h */
#ifdef RT_OS_WINDOWS
# include "cr_server.h"
# define LOG_GROUP LOG_GROUP_SHARED_CROPENGL
#else
# include "cr_server.h"
# define LOG_GROUP LOG_GROUP_SHARED_CROPENGL
#endif /* RT_OS_WINDOWS */
#include <iprt/critsect.h>
#include <iprt/semaphore.h>
#include "cr_mem.h"
#ifndef RT_OS_WINDOWS
# define DWORD int
# define WINAPI
#endif
static const char* gszVBoxOGLSSMMagic = "***OpenGL state data***";
/* Used to process guest calls exceeding maximum allowed HGCM call size in a sequence of smaller calls */
typedef struct _CRVBOXSVCBUFFER_t {
void* pData;
static uint32_t g_CRVBoxSVCBufferID = 0;
/* svcPresentFBO related data */
typedef struct _CRVBOXSVCPRESENTFBOCMD_t {
void *pData;
typedef struct _CRVBOXSVCPRESENTFBO_t {
bool volatile bShutdownWorker; /* Shutdown flag */
static CRVBOXSVCPRESENTFBO_t g_SvcPresentFBO;
/* Schedule a call to a separate worker thread to avoid deadlock on EMT thread when the screen configuration changes
and we're processing crServerPresentFBO caused by guest application command.
To avoid unnecessary memcpy, worker thread frees the data passed.
*/
static DECLCALLBACK(void) svcPresentFBO(void *data, int32_t screenId, int32_t x, int32_t y, uint32_t w, uint32_t h)
{
if (!pCmd)
{
LogRel(("SHARED_CROPENGL svcPresentFBO: not enough memory (%d)\n", sizeof(CRVBOXSVCPRESENTFBOCMD_t)));
return;
}
pCmd->x = x;
pCmd->y = y;
pCmd->w = w;
pCmd->h = h;
{
}
else
{
}
}
{
int rc = VINF_SUCCESS;
Log(("SHARED_CROPENGL svcPresentFBOWorkerThreadProc started\n"));
for (;;)
{
{
break;
}
// @todo use critsect only to fetch the list and update the g_SvcPresentFBO's pQueueHead and pQueueTail.
while (pCmd)
{
/*remove from queue*/
if (!g_SvcPresentFBO.pQueueHead)
{
}
CHECK_ERROR_RET(pDisplay, DrawToScreen(pCmd->screenId, (BYTE*)pCmd->pData, pCmd->x, pCmd->y, pCmd->w, pCmd->h), rc);
}
}
Log(("SHARED_CROPENGL svcPresentFBOWorkerThreadProc finished\n"));
return rc;
}
static int svcPresentFBOInit(void)
{
int rc = VINF_SUCCESS;
g_SvcPresentFBO.bShutdownWorker = false;
return rc;
}
static int svcPresentFBOTearDown(void)
{
int rc = VINF_SUCCESS;
while (pQueue)
{
}
return rc;
}
static DECLCALLBACK(int) svcUnload (void *)
{
int rc = VINF_SUCCESS;
Log(("SHARED_CROPENGL svcUnload\n"));
return rc;
}
{
int rc = VINF_SUCCESS;
return rc;
}
{
int rc = VINF_SUCCESS;
return rc;
}
static DECLCALLBACK(int) svcSaveState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
{
int rc = VINF_SUCCESS;
/* Start*/
/* Version */
/* The state itself */
/* Save svc buffers info */
{
while (pBuffer)
{
}
}
/* End */
return VINF_SUCCESS;
}
static DECLCALLBACK(int) svcLoadState(void *, uint32_t u32ClientID, void *pvClient, PSSMHANDLE pSSM)
{
int rc = VINF_SUCCESS;
char psz[2000];
/* Start of data */
return VERR_SSM_UNEXPECTED_DATA;
/* Version */
/* The state itself */
#if SHCROGL_SSM_VERSION==24
if (ui32==23)
{
}
else
#endif
{
/*@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*/
{
const char *pMatch = &gszVBoxOGLSSMMagic[0];
char current;
while (*pMatch)
{
{
pMatch++;
}
else
{
pMatch = &gszVBoxOGLSSMMagic[0];
}
}
}
return VINF_SUCCESS;
}
/* Load svc buffers info */
if (ui32>=24)
{
while (uiId)
{
if (!pBuffer)
{
return VERR_NO_MEMORY;
}
{
return VERR_NO_MEMORY;
}
if (g_pCRVBoxSVCBuffers)
{
}
}
}
/* End of data */
return VERR_SSM_UNEXPECTED_DATA;
return VINF_SUCCESS;
}
{
/*MS's opengl32 tries to load our ICD around 30 times on failure...this is to prevent unnecessary spam*/
static int shown = 0;
{
"An attempt by the virtual machine to use hardware 3D acceleration failed. "
"The version of the Guest Additions installed in the virtual machine does not match the "
"version of VirtualBox on the host. Please install appropriate Guest Additions to fix this issue");
shown = 1;
}
}
{
if (iBuffer)
{
while (pBuffer)
{
{
{
static int shown=0;
if (shown<20)
{
shown++;
LogRel(("SHARED_CROPENGL svcGetBuffer: invalid buffer(%i) size %i instead of %i\n",
}
return NULL;
}
return pBuffer;
}
}
return NULL;
}
else /*allocate new buffer*/
{
if (pBuffer)
{
{
return NULL;
}
{
}
if (g_pCRVBoxSVCBuffers)
{
}
}
else
{
}
return pBuffer;
}
}
{
{
}
else
{
}
{
}
}
static DECLCALLBACK(void) svcCall (void *, VBOXHGCMCALLHANDLE callHandle, uint32_t u32ClientID, void *pvClient, uint32_t u32Function, uint32_t cParms, VBOXHGCMSVCPARM paParms[])
{
int rc = VINF_SUCCESS;
Log(("SHARED_CROPENGL svcCall: u32ClientID = %d, fn = %d, cParms = %d, pparms = %d\n", u32ClientID, u32Function, cParms, paParms));
#ifdef DEBUG
uint32_t i;
for (i = 0; i < cParms; i++)
{
/** @todo parameters other than 32 bit */
}
#endif
switch (u32Function)
{
case SHCRGL_GUEST_FN_WRITE:
{
Log(("svcCall: SHCRGL_GUEST_FN_WRITE\n"));
/* Verify parameter count and types. */
if (cParms != SHCRGL_CPARMS_WRITE)
{
}
else
)
{
}
else
{
/* Fetch parameters. */
/* Execute the function. */
if (!RT_SUCCESS(rc))
{
svcClientVersionUnsupported(0, 0);
}
}
break;
}
case SHCRGL_GUEST_FN_INJECT:
{
Log(("svcCall: SHCRGL_GUEST_FN_INJECT\n"));
/* Verify parameter count and types. */
if (cParms != SHCRGL_CPARMS_INJECT)
{
}
else
)
{
}
else
{
/* Fetch parameters. */
/* Execute the function. */
if (!RT_SUCCESS(rc))
{
if (VERR_NOT_SUPPORTED==rc)
{
svcClientVersionUnsupported(0, 0);
}
else
{
crWarning("SHCRGL_GUEST_FN_INJECT failed to inject for %i from %i", u32InjectClientID, u32ClientID);
}
}
}
break;
}
case SHCRGL_GUEST_FN_READ:
{
Log(("svcCall: SHCRGL_GUEST_FN_READ\n"));
/* Verify parameter count and types. */
if (cParms != SHCRGL_CPARMS_READ)
{
}
else
)
{
}
/* Fetch parameters. */
/* Execute the function. */
if (RT_SUCCESS(rc))
{
/* Update parameters.*/
} else if (VERR_NOT_SUPPORTED==rc)
{
svcClientVersionUnsupported(0, 0);
}
/* Return the required buffer size always */
break;
}
{
Log(("svcCall: SHCRGL_GUEST_FN_WRITE_READ\n"));
/* Verify parameter count and types. */
if (cParms != SHCRGL_CPARMS_WRITE_READ)
{
}
else
)
{
}
else
{
/* Fetch parameters. */
/* Execute the function. */
if (!RT_SUCCESS(rc))
{
svcClientVersionUnsupported(0, 0);
}
if (RT_SUCCESS(rc))
{
/* Update parameters.*/
}
/* Return the required buffer size always */
}
break;
}
{
Log(("svcCall: SHCRGL_GUEST_FN_SET_VERSION\n"));
/* Verify parameter count and types. */
if (cParms != SHCRGL_CPARMS_SET_VERSION)
{
}
else
)
{
}
else
{
/* Fetch parameters. */
/* Execute the function. */
if (!RT_SUCCESS(rc))
{
}
}
break;
}
case SHCRGL_GUEST_FN_SET_PID:
{
Log(("svcCall: SHCRGL_GUEST_FN_SET_PID\n"));
/* Verify parameter count and types. */
if (cParms != SHCRGL_CPARMS_SET_PID)
{
}
else
{
}
else
{
/* Fetch parameters. */
/* Execute the function. */
}
break;
}
{
Log(("svcCall: SHCRGL_GUEST_FN_WRITE_BUFFER\n"));
/* Verify parameter count and types. */
if (cParms != SHCRGL_CPARMS_WRITE_BUFFER)
{
}
else
)
{
}
else
{
/* Fetch parameters. */
/* Execute the function. */
{
}
else
{
/* Return the buffer id */
}
}
break;
}
{
Log(("svcCall: SHCRGL_GUEST_FN_WRITE_READ_BUFFERED\n"));
/* Verify parameter count and types. */
{
}
else
)
{
}
else
{
/* Fetch parameters. */
if (!pSvcBuffer)
{
break;
}
/* Execute the function. */
if (!RT_SUCCESS(rc))
{
svcClientVersionUnsupported(0, 0);
}
if (RT_SUCCESS(rc))
{
/* Update parameters.*/
}
/* Return the required buffer size always */
}
break;
}
default:
{
}
}
}
/*
* 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[])
{
int rc = VINF_SUCCESS;
Log(("SHARED_CROPENGL svcHostCall: fn = %d, cParms = %d, pparms = %d\n", u32Function, cParms, paParms));
#ifdef DEBUG
uint32_t i;
for (i = 0; i < cParms; i++)
{
/** @todo parameters other than 32 bit */
}
#endif
switch (u32Function)
{
#ifdef VBOX_WITH_CRHGSMI
{
{
if (VERR_NOT_SUPPORTED == rc)
{
svcClientVersionUnsupported(0, 0);
}
}
else
} break;
{
else
} break;
#endif
{
Log(("svcCall: SHCRGL_HOST_FN_SET_DISPLAY\n"));
/* Verify parameter count and types. */
if (cParms != SHCRGL_CPARMS_SET_CONSOLE)
{
}
{
}
else
{
/* Fetch parameters. */
/* Verify parameters values. */
{
}
else if (!pConsole)
{
}
else /* Execute the function. */
{
ULONG monitorCount, i, w, h;
for (i=0; i<monitorCount; ++i)
{
if (!pFramebuffer)
{
rc = crVBoxServerUnmapScreen(i);
}
else
{
}
}
rc = VINF_SUCCESS;
}
}
break;
}
case SHCRGL_HOST_FN_SET_VM:
{
Log(("svcCall: SHCRGL_HOST_FN_SET_VM\n"));
/* Verify parameter count and types. */
if (cParms != SHCRGL_CPARMS_SET_VM)
{
}
{
}
else
{
/* Fetch parameters. */
/* Verify parameters values. */
{
}
else
{
/* Execute the function. */
rc = VINF_SUCCESS;
}
}
break;
}
{
Log(("svcCall: SHCRGL_HOST_FN_SET_VISIBLE_REGION\n"));
{
break;
}
)
{
break;
}
break;
}
{
Log(("svcCall: SHCRGL_HOST_FN_SCREEN_CHANGED\n"));
/* Verify parameter count and types. */
if (cParms != SHCRGL_CPARMS_SCREEN_CHANGED)
{
}
{
}
else
{
/* Fetch parameters. */
/* Execute the function. */
ULONG w, h;
if (!pFramebuffer)
{
}
else
{
if (!winId)
{
/* View associated with framebuffer is destroyed, happens with 2d accel enabled */
}
else
{
}
}
rc = VINF_SUCCESS;
}
break;
}
{
/*
* OutputRedirect.
* Note: the service calls OutputRedirect callbacks directly
* and they must not block. If asynchronous processing is needed,
* the callback provider must organize this.
*/
Log(("svcCall: SHCRGL_HOST_FN_SET_OUTPUT_REDIRECT\n"));
/* Verify parameter count and types. */
{
}
{
}
else
{
/* Fetch parameters. */
/* Verify parameters values. */
if (cbData != sizeof (H3DOUTPUTREDIRECT))
{
}
else /* Execute the function. */
{
if (RT_SUCCESS(rc))
{
}
}
}
break;
}
default:
break;
}
return rc;
}
{
int rc = VINF_SUCCESS;
if (!ptable)
{
}
else
{
Log(("VBoxHGCMSvcLoad: ptable->cbSize = %d, ptable->u32Version = 0x%08X\n", ptable->cbSize, ptable->u32Version));
{
}
else
{
if (!crVBoxServerInit())
return VERR_NOT_SUPPORTED;
rc = svcPresentFBOInit();
}
}
return rc;
}