server_main.c revision c1c23b03ecbb3f4dbfaae84ea633b959757bd5d2
/* Copyright (c) 2001, Stanford University
* All rights reserved
*
* See the file LICENSE.txt for information on redistributing this software.
*/
#include "server.h"
#include "cr_net.h"
#include "cr_unpack.h"
#include "cr_error.h"
#include "cr_glstate.h"
#include "cr_string.h"
#include "cr_mem.h"
#include "cr_hash.h"
#include "cr_environment.h"
#include "cr_pixeldata.h"
#include "server_dispatch.h"
#include "state/cr_texture.h"
#include "render/renderspu.h"
#include <signal.h>
#include <stdlib.h>
#define DEBUG_FP_EXCEPTIONS 0
#include <fpu_control.h>
#include <math.h>
#endif
#ifdef VBOXCR_LOGFPS
#endif
#ifdef VBOX_WITH_CRHGSMI
#endif
/**
* \mainpage CrServerLib
*
* \section CrServerLibIntroduction Introduction
*
* Chromium consists of all the top-level files in the cr
* directory. The core module basically takes care of API dispatch,
* and OpenGL state management.
*/
/**
* CRServer global data
*/
int tearingdown = 0; /* can't be static */
{
int32_t i;
for (i = 0; i < cr_server.numClients; i++)
{
{
break;
}
}
if (!pClient)
{
crWarning("client not found!");
return VERR_INVALID_PARAMETER;
}
{
crWarning("no major version specified for client!");
return VERR_NOT_SUPPORTED;
}
return VINF_SUCCESS;
}
/**
* Return pointer to server's first SPU.
*/
SPU*
crServerHeadSPU(void)
{
}
static void DeleteBarrierCallback( void *data )
{
}
static void deleteContextInfoCallback( void *data )
{
if (c->CreateInfo.pszDpyName)
crFree(c);
}
static void deleteMuralInfoCallback( void *data )
{
if (m->spuWindow) /* <- do not do term for default mural as it does not contain any info to be freed,
* and renderspu will destroy it up itself*/
{
}
crFree(m);
}
static void crServerTearDown( void )
{
GLint i;
/* avoid a race condition */
if (tearingdown)
return;
tearingdown = 1;
/* Deallocate all semaphores */
/* Deallocate all barriers */
/* Free all context info */
/* Free vertex programs */
/* Free dummy murals */
/* Free murals */
for (i = 0; i < cr_server.numClients; i++) {
}
}
cr_server.numClients = 0;
while (pNode)
{
}
#if 1
/* disable these two lines if trying to get stack traces with valgrind */
#endif
}
static void crServerClose( unsigned int id )
{
crError( "Client disconnected!" );
(void) id;
}
static void crServerCleanup( int sigio )
{
tearingdown = 0;
}
void
crServerSetPort(int port)
{
}
static void
crPrintHelp(void)
{
printf("Usage: crserver [OPTIONS]\n");
printf("Options:\n");
printf(" -mothership URL Specifies URL for contacting the mothership.\n");
printf(" URL is of the form [protocol://]hostname[:port]\n");
printf(" -port N Specifies the port number this server will listen to.\n");
printf(" -help Prints this information.\n");
}
/**
* Do CRServer initializations. After this, we can begin servicing clients.
*/
void
{
int i;
char *mothership = NULL;
for (i = 1 ; i < argc ; i++)
{
{
if (i == argc - 1)
{
crError( "-mothership requires an argument" );
}
i++;
}
{
/* This is the port on which we'll accept client connections */
if (i == argc - 1)
{
crError( "-port requires an argument" );
}
i++;
}
{
}
{
crPrintHelp();
exit(0);
}
}
#ifndef WINDOWS
#endif
{
| _FPU_MASK_OM | _FPU_MASK_UM);
}
#endif
{
crInfo("Info: using multiple contexts!");
crDebug("Debug: using multiple contexts!");
}
/*
* Create default mural info and hash table.
*/
crStateInit();
/*
* Default context
*/
}
void crVBoxServerTearDown(void)
{
}
/**
* Do CRServer initializations. After this, we can begin servicing clients.
*/
GLboolean crVBoxServerInit(void)
{
{
| _FPU_MASK_OM | _FPU_MASK_UM);
}
#endif
{
crInfo("Info: using multiple contexts!");
crDebug("Debug: using multiple contexts!");
}
/*
* Create default mural info and hash table.
*/
crStateInit();
/*
* Default context
*/
return GL_FALSE;
/*Check for PBO support*/
{
}
return GL_TRUE;
}
{
{
return VERR_MAX_THRDS_REACHED;
}
return VINF_SUCCESS;
}
{
int32_t i;
for (i = 0; i < cr_server.numClients; i++)
{
{
break;
}
}
//if (!pClient) return VERR_INVALID_PARAMETER;
if (!pClient)
{
return;
}
#ifdef VBOX_WITH_CRHGSMI
#endif
/* Disconnect the client */
/* Let server clear client from the queue */
}
{
#ifdef VBOXCR_LOGFPS
#endif
/*crDebug("=>crServer: ClientWrite u32ClientID=%d", u32ClientID);*/
#ifdef VBOXCR_LOGFPS
tstart = RTTimeNanoTS();
#endif
/* This should be setup already */
#ifdef VBOX_WITH_CRHGSMI
#endif
if (
#ifdef VBOX_WITH_CRHGSMI
#endif
{
}
else
{
}
crNetRecv();
#if 0
if (pClient->currentMural) {
}
#endif
#ifndef VBOX_WITH_CRHGSMI
#endif
#ifdef VBOXCR_LOGFPS
tend = RTTimeNanoTS();
#endif
/*crDebug("<=crServer: ClientWrite u32ClientID=%d", u32ClientID);*/
return VINF_SUCCESS;
}
{
if (RT_FAILURE(rc))
return rc;
/* This should never fire unless we start to multithread */
#ifdef VBOX_WITH_CRHGSMI
#endif
}
{
{
crDebug("crServer: [%lx] ClientRead u32ClientID=%d FAIL, host buffer too small %d of %d",
/* Return the size of needed buffer */
return VERR_BUFFER_OVERFLOW;
}
if (*pcbBuffer)
{
}
return VINF_SUCCESS;
}
{
if (RT_FAILURE(rc))
return rc;
#ifdef VBOX_WITH_CRHGSMI
#endif
}
{
int32_t i;
for (i = 0; i < cr_server.numClients; i++)
{
{
break;
}
}
if (!pClient) return VERR_INVALID_PARAMETER;
if (vMajor != CR_PROTOCOL_VERSION_MAJOR
|| vMinor != CR_PROTOCOL_VERSION_MINOR)
{
return VERR_NOT_SUPPORTED;
}
else return VINF_SUCCESS;
}
{
int32_t i;
for (i = 0; i < cr_server.numClients; i++)
{
{
break;
}
}
if (!pClient) return VERR_INVALID_PARAMETER;
return VINF_SUCCESS;
}
int
{
tearingdown = 0;
return 0;
}
{
/* Don't store default mural */
if (!key) return;
if (pMI->pVisibleRects)
{
}
}
/* @todo add hashtable walker with result info and intermediate abort */
{
/* Don't store default mural create info */
if (!key) return;
if (pCreateInfo->pszDpyName)
{
}
}
{
}
{
/* saved state contains internal id */
}
{
}
typedef struct CRVBOX_SAVE_STATE_GLOBAL
{
/* context id -> mural association
* on context data save, each context will be made current with the corresponding mural from this table
* thus saving the mural front & back buffer data */
/* mural id -> context info
* for murals that do not have associated context in contextMuralTable
* we still need to save*/
int rc;
typedef struct CRVBOX_CTXWND_CTXWALKER_CB
{
static void crVBoxServerBuildAdditionalWindowContextMapCB(unsigned long key, void *data1, void *data2)
{
return;
{
return;
}
{
}
else
{
crWarning("different visual bits not implemented!");
}
crHashtableAdd(pData->pGlobal->additionalMuralContextTable, pMural->CreateInfo.externalID, pContextInfo);
}
typedef struct CRVBOX_CTXWND_WNDWALKER_CB
{
static void crVBoxServerBuildContextWindowMapWindowWalkerCB(unsigned long key, void *data1, void *data2)
{
return;
return;
return;
return;
}
{
if (!pContextInfo->currentMural)
return;
crHashtableAdd(pData->pGlobal->contextMuralTable, pContextInfo->CreateInfo.externalID, pContextInfo->currentMural);
crHashtableAdd(pData->usedMuralTable, pContextInfo->currentMural->CreateInfo.externalID, pContextInfo->currentMural);
}
{
if (!pMural)
{
if (!pMural)
{
crWarning("crCalloc failed!");
return NULL;
}
if (id < 0)
{
crWarning("crServerMuralInit failed!");
return NULL;
}
}
return pMural;
}
{
if (pContextInfo->currentMural)
return;
Assert(crHashtableNumElements(pData->pGlobal->contextMuralTable) <= crHashtableNumElements(cr_server.muralTable) - 1);
if (crHashtableNumElements(pData->pGlobal->contextMuralTable) < crHashtableNumElements(cr_server.muralTable) - 1)
{
}
if (!pMural)
{
if (!pMural)
{
crWarning("crServerGetDummyMural failed");
return;
}
}
else
{
}
}
{
/* 1. go through all contexts and match all having currentMural set */
Data.cAdditionalMurals = 0;
{
Data.cAdditionalMurals = 0;
}
CRASSERT(crHashtableNumElements(pGlobal->contextMuralTable) == crHashtableNumElements(cr_server.contextTable));
{
CRASSERT(cMurals + Data.cAdditionalMurals + crHashtableNumElements(pGlobal->additionalMuralContextTable) == crHashtableNumElements(cr_server.muralTable) - 1);
}
}
{
/* do crStateAcquireFBImage no matter whether offscreen drawing is used or not
* in the former case this would just free pContext->buffer.pFrontImg and pContext->buffer.pFrontImg
*/
return VINF_SUCCESS;
{
}
else
{
void *pvData;
if (idPBO)
{
}
if (!pvData)
{
crWarning("CrHlpGetTexImage failed for frontbuffer");
return VERR_NO_MEMORY;
}
if (!pvData)
{
crWarning("CrHlpGetTexImage failed for backbuffer");
return VERR_NO_MEMORY;
}
}
return VINF_SUCCESS;
}
#define CRSERVER_ASSERTRC_RETURN_VOID(_rc) do { \
if(!RT_SUCCESS((_rc))) { \
AssertFailed(); \
return; \
} \
} while (0)
{
pData->rc = SSMR3PutMem(pSSM, &pContextInfo->CreateInfo.externalID, sizeof(pContextInfo->CreateInfo.externalID));
/* restore the reference data, we synchronize it with the HW state in a later crServerPerformMakeCurrent call */
}
{
/* We could have skipped saving the key and use similar callback to load context states back,
* but there's no guarantee we'd traverse hashtable in same order after loading.
*/
#ifdef DEBUG_misha
{
unsigned long id;
else
}
#endif
{
pData->rc = SSMR3PutMem(pSSM, &pMural->CreateInfo.externalID, sizeof(pMural->CreateInfo.externalID));
}
else
{
}
#endif
/* restore the initial current mural */
}
#if 0
typedef struct CR_SERVER_CHECK_BUFFERS
{
static void crVBoxServerCheckConsistencyContextBuffersCB(unsigned long key, void *data1, void *data2)
{
int j, k;
if (obj == b->arrayBuffer)
{
}
if (obj == b->elementsBuffer)
{
}
#ifdef CR_ARB_pixel_buffer_object
if (obj == b->packBuffer)
{
}
if (obj == b->unpackBuffer)
{
}
#endif
#ifdef CR_ARB_vertex_buffer_object
for (j=0; j<CRSTATECLIENT_MAX_VERTEXARRAYS; ++j)
{
{
}
}
{
for (j=0; j<CRSTATECLIENT_MAX_VERTEXARRAYS; ++j)
{
{
}
}
}
#endif
}
{
CR_SERVER_CHECK_BUFFERS Buffers = {0};
crHashtableWalk(cr_server.contextTable, crVBoxServerCheckConsistencyContextBuffersCB, (void*)&Buffers);
}
//static void crVBoxServerCheckConsistency2CB(unsigned long key, void *data1, void *data2)
//{
// CRContextInfo* pContextInfo1 = (CRContextInfo*)data1;
// CRContextInfo* pContextInfo2 = (CRContextInfo*)data2;
//
// CRASSERT(pContextInfo1->pContext);
// CRASSERT(pContextInfo2->pContext);
//
// if (pContextInfo1 == pContextInfo2)
// {
// CRASSERT(pContextInfo1->pContext == pContextInfo2->pContext);
// return;
// }
//
// CRASSERT(pContextInfo1->pContext != pContextInfo2->pContext);
// CRASSERT(pContextInfo1->pContext->shared);
// CRASSERT(pContextInfo2->pContext->shared);
// CRASSERT(pContextInfo1->pContext->shared == pContextInfo2->pContext->shared);
// if (pContextInfo1->pContext->shared != pContextInfo2->pContext->shared)
// return;
//
// crHashtableWalk(pContextInfo1->pContext->shared->buffersTable, crVBoxServerCheckConsistencyBuffersCB, pContextInfo2);
//}
{
if (!*ppShared)
else
}
static void crVBoxServerCheckConsistency()
{
if (pShared)
{
}
}
#endif
static uint32_t g_hackVBoxServerSaveLoadCallsLeft = 0;
{
GLboolean b;
unsigned long key;
#endif
#if 0
#endif
/* We shouldn't be called if there's no clients at all*/
/* @todo it's hack atm */
/* We want to be called only once to save server state but atm we're being called from svcSaveState
* for every connected client (e.g. guest opengl application)
*/
{
/* Store number of clients */
}
/* Do nothing until we're being called last time */
{
return VINF_SUCCESS;
}
/* Save rendering contexts creation info */
/* Save current win and ctx IDs, as we'd rebind contexts when saving textures */
if (curClient)
{
}
else if (cr_server.numClients)
{
}
#endif
/* first save windows info */
/* Save windows creation info */
/* There should be default mural always */
/* Save cr_server.muralTable
* @todo we don't need it all, just geometry info actually
*/
/* we need to save front & backbuffer data for each mural first create a context -> mural association */
/* Save contexts state tracker data */
/* @todo For now just some blind data dumps,
* allow diff_api to work correctly.
* Should be tested more with multiply guest opengl apps working when saving VM snapshot.
*/
/* Restore original win and ctx IDs*/
{
}
else
{
}
#endif
/* Save clients info */
for (i = 0; i < cr_server.numClients; i++)
{
{
if (pClient->currentCtxInfo && pClient->currentCtxInfo->pContext && pClient->currentContextNumber>=0)
{
CRASSERT(b);
}
{
CRASSERT(b);
}
}
}
/* all context gl error states should have now be synced with chromium erro states,
* reset the error if any */
return VINF_SUCCESS;
}
{
return pContextInfo->pContext;
}
{
unsigned long key;
/* Load windows */
{
char psz[200];
unsigned long key;
if (createInfo.pszDpyName)
{
}
}
/* Load cr_server.muralTable */
{
if (muralInfo.pVisibleRects)
{
if (!muralInfo.pVisibleRects)
{
return VERR_NO_MEMORY;
}
}
{
}
/* Restore windows geometry info */
/* Same workaround as described in stub.c:stubUpdateWindowVisibileRegions for compiz on a freshly booted VM*/
if (muralInfo.bReceivedRects)
{
}
if (muralInfo.pVisibleRects)
{
}
}
return VINF_SUCCESS;
}
{
{
}
else
{
}
if (storedWidth && storedHeight)
{
void *pData;
if (!pData)
{
return VERR_NO_MEMORY;
}
if (!pData)
{
return VERR_NO_MEMORY;
}
{
/* can apply the data right away */
}
}
return VINF_SUCCESS;
}
{
unsigned long key;
if (!cr_server.bIsInLoadingState)
{
/* AssertRCReturn(...) will leave us in loading state, but it doesn't matter as we'd be failing anyway */
/* Read number of clients */
}
/* Do nothing until we're being called last time */
{
return VINF_SUCCESS;
}
{
}
/* Load and recreate rendering contexts */
{
char psz[200];
if (createInfo.pszDpyName)
{
}
ctxID = crServerDispatchCreateContextEx(createInfo.pszDpyName, createInfo.visualBits, 0, key, createInfo.externalID /* <-saved state stores internal id here*/);
}
{
/* we have a mural data here */
}
{
/* set the current client to allow doing crServerPerformMakeCurrent later */
}
/* Restore context state data */
{
{
if (winId)
{
}
else
{
/* null winId means a dummy mural, get it */
}
}
}
{
{
if (ctxId)
{
}
else
/* restore the reference data, we synchronize it with the HW state in a later crServerPerformMakeCurrent call */
}
{
/* most ogl data gets loaded to hw on chromium 3D state switch, i.e. inside crStateMakeCurrent -> crStateSwitchContext
* to force the crStateSwitchContext being called later, we need to set the current context to our dummy one */
}
}
else
{
/* we have a mural data here */
/* not used any more, just read it out and ignore */
}
/* Load clients info */
for (i = 0; i < cr_server.numClients; i++)
{
{
/* If this assert fires, then we should search correct client in the list first*/
if (version>=4)
{
}
/* We can't reassign client number, as we'd get wrong results in TranslateTextureID
* and fail to bind old textures.
*/
/*client.number = pClient->number;*/
{
//pClient->currentCtx = client.currentCtx;
//pClient->currentContextNumber = ctxID;
}
{
//pClient->currentMural = client.currentMural;
//pClient->currentWindow = winID;
}
/* Restore client active context and window */
if (0)
{
// CRContext *tmpCtx;
// CRCreateInfo_t *createInfo;
crHashtableWalk(client.currentCtxInfo->pContext->shared->textureTable, crVBoxServerSyncTextureCB, client.currentCtxInfo->pContext);
crStateTextureObjectDiff(client.currentCtxInfo->pContext, NULL, NULL, &client.currentCtxInfo->pContext->texture.base1D, GL_TRUE);
crStateTextureObjectDiff(client.currentCtxInfo->pContext, NULL, NULL, &client.currentCtxInfo->pContext->texture.base2D, GL_TRUE);
crStateTextureObjectDiff(client.currentCtxInfo->pContext, NULL, NULL, &client.currentCtxInfo->pContext->texture.base3D, GL_TRUE);
#ifdef CR_ARB_texture_cube_map
crStateTextureObjectDiff(client.currentCtxInfo->pContext, NULL, NULL, &client.currentCtxInfo->pContext->texture.baseCubeMap, GL_TRUE);
#endif
#ifdef CR_NV_texture_rectangle
//@todo this doesn't work as expected
//crStateTextureObjectDiff(client.currentCtxInfo->pContext, NULL, NULL, &client.currentCtxInfo->pContext->texture.baseRect, GL_TRUE);
#endif
/*cr_server.head_spu->dispatch_table.Materialfv(GL_FRONT_AND_BACK, GL_AMBIENT, amb);
cr_server.head_spu->dispatch_table.LightModelfv(GL_LIGHT_MODEL_AMBIENT, amb);
cr_server.head_spu->dispatch_table.Lightfv(GL_LIGHT1, GL_DIFFUSE, one);
cr_server.head_spu->dispatch_table.Enable(GL_LIGHTING);
cr_server.head_spu->dispatch_table.Enable(GL_LIGHT0);
cr_server.head_spu->dispatch_table.Enable(GL_LIGHT1);
cr_server.head_spu->dispatch_table.Enable(GL_CULL_FACE);
cr_server.head_spu->dispatch_table.Enable(GL_TEXTURE_2D);*/
//crStateViewport( 0, 0, 600, 600 );
//pClient->currentMural->viewportValidated = GL_FALSE;
//cr_server.head_spu->dispatch_table.Viewport( 0, 0, 600, 600 );
//crStateMatrixMode(GL_PROJECTION);
//cr_server.head_spu->dispatch_table.MatrixMode(GL_PROJECTION);
//crStateLoadIdentity();
//cr_server.head_spu->dispatch_table.LoadIdentity();
//crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
//cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
//crStateMatrixMode(GL_MODELVIEW);
//cr_server.head_spu->dispatch_table.MatrixMode(GL_MODELVIEW);
//crServerDispatchLoadIdentity();
//crStateFrustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
//cr_server.head_spu->dispatch_table.Frustum(-0.5, 0.5, -0.5, 0.5, 1.5, 150.0);
//crServerDispatchLoadIdentity();
/*createInfo = (CRCreateInfo_t *) crHashtableSearch(cr_server.pContextCreateInfoTable, ctxID);
CRASSERT(createInfo);
tmpCtx = crStateCreateContext(NULL, createInfo->visualBits, NULL);
CRASSERT(tmpCtx);
crStateDiffContext(tmpCtx, client.currentCtxInfo->pContext);
crStateDestroyContext(tmpCtx);*/
}
}
}
//crServerDispatchMakeCurrent(-1, 0, -1);
#if 0
#endif
return VINF_SUCCESS;
}
{
{
}
}
{
(void) data2;
}
{
int i;
return VERR_INVALID_PARAMETER;
/*Shouldn't happen yet, but to be safe in future*/
for (i=0; i<cr_server.screenCount; ++i)
{
crWarning("Screen count is changing, but screen[%i] is still mapped", i);
return VERR_NOT_IMPLEMENTED;
}
for (i=0; i<sCount; ++i)
{
}
return VINF_SUCCESS;
}
{
return VERR_INVALID_PARAMETER;
{
}
return VINF_SUCCESS;
}
DECLEXPORT(int32_t) crVBoxServerMapScreen(int sIndex, int32_t x, int32_t y, uint32_t w, uint32_t h, uint64_t winID)
{
return VERR_INVALID_PARAMETER;
{
}
#ifndef WINDOWS
/*Restore FB content for clients, which have current window on a screen being remapped*/
{
GLint i;
for (i = 0; i < cr_server.numClients; i++)
{
&& (cr_server.curClient->currentCtxInfo->pContext->buffer.pFrontImg || cr_server.curClient->currentCtxInfo->pContext->buffer.pBackImg)
{
{
}
}
}
}
#endif
{
if (pDisplay)
CrDpResize(pDisplay, w, h, w, h);
}
return VINF_SUCCESS;
}
{
return VINF_SUCCESS;
}
{
}
{
{
return VINF_SUCCESS;
}
if (value > CR_SERVER_REDIR_MAXVAL)
{
return VERR_INVALID_PARAMETER;
}
if (value && !crServerSupportRedirMuralFBO())
{
return VERR_NOT_SUPPORTED;
}
return VINF_SUCCESS;
}
{
return crServerSetOffscreenRenderingMode(value ? CR_SERVER_REDIR_FBO_RAM : cr_server.bOffscreenRenderingDefault);
}
{
/* No need for a synchronization as this is single threaded. */
if (pCallbacks)
{
cr_server.bUseOutputRedirect = true;
}
else
{
cr_server.bUseOutputRedirect = false;
}
// @todo dynamically intercept already existing output:
// crHashtableWalk(cr_server.muralTable, crVBoxServerOutputRedirectCB, NULL);
return VINF_SUCCESS;
}
{
return;
}
DECLEXPORT(int32_t) crVBoxServerSetScreenViewport(int sIndex, int32_t x, int32_t y, uint32_t w, uint32_t h)
{
{
return VERR_INVALID_PARAMETER;
}
if (!fPosChanged && !fSizeChanged)
{
crDebug("crVBoxServerSetScreenViewport: no changes");
return VINF_SUCCESS;
}
if (fPosChanged)
{
pVieport->x = x;
pVieport->y = y;
}
if (fSizeChanged)
{
pVieport->w = w;
pVieport->h = h;
/* no need to do anything here actually */
}
return VINF_SUCCESS;
}
#ifdef VBOX_WITH_CRHGSMI
/* We moved all CrHgsmi command processing to crserverlib to keep the logic of dealing with CrHgsmi commands in one place.
*
* For now we need the notion of CrHgdmi commands in the crserver_lib to be able to complete it asynchronously once it is really processed.
* This help avoiding the "blocked-client" issues. The client is blocked if another client is doing begin-end stuff.
* For now we eliminated polling that could occur on block, which caused a higher-priority thread (in guest) polling for the blocked command complition
* to block the lower-priority thread trying to complete the blocking command.
* And removed extra memcpy done on blocked command arrival.
*
* In the future we will extend CrHgsmi functionality to maintain texture data directly in CrHgsmi allocation to avoid extra memcpy-ing with PBO,
* implement command completion and stuff necessary for GPU scheduling to work properly for WDDM Windows guests, etc.
*
* NOTE: it is ALWAYS responsibility of the crVBoxServerCrHgsmiCmd to complete the command!
* */
{
if (!g_pvVRamBase)
{
crWarning("g_pvVRamBase is not initialized");
return VINF_SUCCESS;
}
if (!cBuffers)
{
crWarning("zero buffers passed in!");
return VINF_SUCCESS;
}
if (!pHdr)
{
crWarning("invalid header buffer!");
return VINF_SUCCESS;
}
{
crWarning("invalid header buffer size!");
return VINF_SUCCESS;
}
switch (u32Function)
{
case SHCRGL_GUEST_FN_WRITE:
{
crDebug(("svcCall: SHCRGL_GUEST_FN_WRITE\n"));
/* @todo: Verify */
if (cParams == 1)
{
/* Fetch parameters. */
{
crWarning("invalid write cmd buffer size!");
break;
}
if (!pBuffer)
{
crWarning("invalid buffer data received from guest!");
break;
}
if (RT_FAILURE(rc))
{
break;
}
/* This should never fire unless we start to multithread */
return rc;
}
else
{
crWarning("invalid number of args");
break;
}
break;
}
case SHCRGL_GUEST_FN_INJECT:
{
crDebug(("svcCall: SHCRGL_GUEST_FN_INJECT\n"));
/* @todo: Verify */
if (cParams == 1)
{
/* Fetch parameters. */
{
crWarning("invalid inject cmd buffer size!");
break;
}
if (!pBuffer)
{
crWarning("invalid buffer data received from guest!");
break;
}
if (RT_FAILURE(rc))
{
break;
}
/* This should never fire unless we start to multithread */
return rc;
}
crWarning("invalid number of args");
break;
}
case SHCRGL_GUEST_FN_READ:
{
crDebug(("svcCall: SHCRGL_GUEST_FN_READ\n"));
/* @todo: Verify */
if (cParams == 1)
{
/* Fetch parameters. */
{
crWarning("invalid read cmd buffer size!");
break;
}
if (!pBuffer)
{
crWarning("invalid buffer data received from guest!");
break;
}
if (RT_FAILURE(rc))
{
break;
}
/* Return the required buffer size always */
/* the read command is never pended, complete it right away */
return VINF_SUCCESS;
}
crWarning("invalid number of args");
break;
}
{
crDebug(("svcCall: SHCRGL_GUEST_FN_WRITE_READ\n"));
/* @todo: Verify */
if (cParams == 2)
{
/* Fetch parameters. */
{
crWarning("invalid write_read cmd buffer size!");
break;
}
if (!pBuffer)
{
crWarning("invalid write buffer data received from guest!");
break;
}
if (!pWriteback)
{
crWarning("invalid writeback buffer data received from guest!");
break;
}
if (RT_FAILURE(rc))
{
return rc;
}
/* This should never fire unless we start to multithread */
CRVBOXHGSMI_CMDDATA_SETWB(&pClient->conn->CmdData, pCmd, pHdr, pWriteback, cbWriteback, &pFnCmd->cbWriteback);
return rc;
}
crWarning("invalid number of args");
break;
}
{
crWarning("invalid function");
break;
}
case SHCRGL_GUEST_FN_SET_PID:
{
crWarning("invalid function");
break;
}
default:
{
crWarning("invalid function");
break;
}
}
/* we can be on fail only here */
return rc;
}
{
int rc = VINF_SUCCESS;
{
{
rc = VINF_SUCCESS;
break;
}
rc = VINF_SUCCESS;
break;
{
PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_COMPLETION pSetup = (PVBOXVDMACMD_CHROMIUM_CTL_CRHGSMI_SETUP_COMPLETION)pCtl;
rc = VINF_SUCCESS;
break;
}
default:
}
/* NOTE: Control commands can NEVER be pended here, this is why its a task of a caller (Main)
* to complete them accordingly.
* This approach allows using host->host and host->guest commands in the same way here
* making the command completion to be the responsibility of the command originator.
* E.g. ctl commands can be both Hgcm Host synchronous commands that do not require completion at all,
* or Hgcm Host Fast Call commands that do require completion. All this details are hidden here */
return rc;
}
#endif