server_main.c revision bd7ba981f594437acad0ea42f07cbd14c41cf485
/* 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_vreg.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 != CR_RENDER_DEFAULT_WINDOW_ID) /* <- 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;
/* needed to make sure window dummy mural not get created on mural destruction
* and generally this should be zeroed up */
{
}
/* sync our state with renderspu,
/* 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
VBoxVrTerm();
}
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;
const char*env;
char *mothership = NULL;
int rc = VBoxVrInit();
if (!RT_SUCCESS(rc))
{
return;
}
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!");
}
{
}
else
{
}
/*
* Create default mural info and hash table.
*/
crStateInit();
/*
* Default context
*/
if (env)
{
}
else
{
}
}
void crVBoxServerTearDown(void)
{
}
/**
* Do CRServer initializations. After this, we can begin servicing clients.
*/
GLboolean crVBoxServerInit(void)
{
const char*env;
int rc = VBoxVrInit();
if (!RT_SUCCESS(rc))
{
return GL_FALSE;
}
{
| _FPU_MASK_OM | _FPU_MASK_UM);
}
#endif
{
crInfo("Info: using multiple contexts!");
crDebug("Debug: using multiple contexts!");
}
{
}
else
{
}
/*
* Create default mural info and hash table.
*/
crStateInit();
/*
* Default context
*/
if (env)
{
}
else
{
}
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
}
{
return VINF_SUCCESS;
}
{
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);
}
}
{
GLuint i;
{
{
/* sanity */
}
}
}
static int crVBoxServerFBImageDataInitEx(CRFBData *pData, CRContextInfo *pCtxInfo, CRMuralInfo *pMural, GLboolean fWrite, uint32_t version, GLuint overrideWidth, GLuint overrideHeight)
{
GLuint i;
/* the version should be always actual when we do reads,
* i.e. it could differ on writes when snapshot is getting loaded */
return VINF_SUCCESS;
if (pMural)
{
if (fWrite)
{
}
else
{
}
}
pEl->idFBO = pMural && (pMural->fPresentMode & CR_SERVER_REDIR_F_FBO) ? pMural->aidFBOs[CR_SERVER_FBO_FB_IDX(pMural)] : 0;
{
crWarning("crVBoxServerFBImageDataInit: crCalloc failed");
return VERR_NO_MEMORY;
}
/* there is a lot of code that assumes we have double buffering, just assert here to print a warning in the log
* so that we know that something irregular is going on */
|| version < SHCROGL_SSM_VERSION_WITH_SINGLE_DEPTH_STENCIL /* <- older version had a typo which lead to back always being used,
* no matter what the visual bits are */
)
{
pEl->idFBO = pMural && (pMural->fPresentMode & CR_SERVER_REDIR_F_FBO) ? pMural->aidFBOs[CR_SERVER_FBO_BB_IDX(pMural)] : 0;
{
crWarning("crVBoxServerFBImageDataInit: crCalloc failed");
return VERR_NO_MEMORY;
}
}
return VINF_SUCCESS;
{
/* if (pCtxInfo->CreateInfo.visualBits & CR_DEPTH_BIT) */ /* <- older version had a typo which lead to back always being used,
* no matter what the visual bits are */
{
pEl->idFBO = pMural && (pMural->fPresentMode & CR_SERVER_REDIR_F_FBO) ? pMural->aidFBOs[CR_SERVER_FBO_FB_IDX(pMural)] : 0;
{
crWarning("crVBoxServerFBImageDataInit: crCalloc failed");
return VERR_NO_MEMORY;
}
/* init to default depth value, just in case */
{
pF[i] = 1.;
}
}
/* if (pCtxInfo->CreateInfo.visualBits & CR_STENCIL_BIT) */ /* <- older version had a typo which lead to back always being used,
* no matter what the visual bits are */
{
pEl->idFBO = pMural && (pMural->fPresentMode & CR_SERVER_REDIR_F_FBO) ? pMural->aidFBOs[CR_SERVER_FBO_FB_IDX(pMural)] : 0;
{
crWarning("crVBoxServerFBImageDataInit: crCalloc failed");
return VERR_NO_MEMORY;
}
}
return VINF_SUCCESS;
}
{
pEl->idFBO = pMural && (pMural->fPresentMode & CR_SERVER_REDIR_F_FBO) ? pMural->aidFBOs[CR_SERVER_FBO_FB_IDX(pMural)] : 0;
{
crWarning("crVBoxServerFBImageDataInit: crCalloc failed");
return VERR_NO_MEMORY;
}
}
return VINF_SUCCESS;
}
static int crVBoxServerFBImageDataInit(CRFBData *pData, CRContextInfo *pCtxInfo, CRMuralInfo *pMural, GLboolean fWrite)
{
}
{
GLuint i;
struct
{
CRFBDataElement buffer[3]; /* CRFBData::aElements[1] + buffer[3] gives 4: back, front, depth and stencil */
} Data;
if (!RT_SUCCESS(rc))
{
return rc;
}
{
}
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
if (pContextInfo->currentMural
|| crHashtableSearch(cr_server.muralTable, pMural->CreateInfo.externalID) /* <- this is not a dummy mural */
)
{
pData->rc = SSMR3PutMem(pSSM, &pMural->CreateInfo.externalID, sizeof(pMural->CreateInfo.externalID));
}
else
{
/* this is a dummy mural */
}
#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;
}
#ifdef DEBUG_misha
#define CR_DBG_STR_STATE_SAVE_START "VBox.Cr.StateSaveStart"
#define CR_DBG_STR_STATE_SAVE_STOP "VBox.Cr.StateSaveStop"
cr_server.head_spu->dispatch_table.StringMarkerGREMEDY(sizeof (CR_DBG_STR_STATE_SAVE_START), CR_DBG_STR_STATE_SAVE_START);
#endif
/* 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 */
#ifdef DEBUG_misha
cr_server.head_spu->dispatch_table.StringMarkerGREMEDY(sizeof (CR_DBG_STR_STATE_SAVE_STOP), CR_DBG_STR_STATE_SAVE_STOP);
#endif
return VINF_SUCCESS;
}
{
return pContextInfo->pContext;
}
typedef struct CR_SERVER_LOADSTATE_READER
{
{
}
{
/* sanity */
}
static int crServerLsrDataGetMem(CR_SERVER_LOADSTATE_READER *pReader, void *pvBuffer, uint32_t cbBuffer)
{
int rc = VINF_SUCCESS;
{
cbRemaining -= cbData;
}
if (cbRemaining)
{
}
return rc;
}
{
}
static int crServerLsrDataPutMem(CR_SERVER_LOADSTATE_READER *pReader, void *pvBuffer, uint32_t cbBuffer)
{
{
}
{
}
else
{
{
return VERR_NO_MEMORY;
}
if (pu8Buffer)
{
}
else
{
}
}
return VINF_SUCCESS;
}
/* data to be skipped */
typedef struct CR_SERVER_BUGGY_MURAL_DATA_2
{
void*ListHead_pNext;
void*ListHead_pPrev;
typedef struct CR_SERVER_BUGGY_MURAL_DATA_1
{
/* VBOXVR_COMPOSITOR_ENTRY Ce; */
void*Ce_Node_pNext;
void*Ce_Node_pPrev;
/* VBOXVR_TEXTURE Tex; */
/* RTPOINT Pos; */
void* paSrcRects;
void* paDstRects;
typedef struct CR_SERVER_BUGGY_MURAL_DATA_4
{
void* EventSem;
typedef struct CR_SERVER_BUGGY_MURAL_DATA_3
{
void*Compositor_List_pNext;
void*Compositor_List_pPrev;
float StretchX;
float StretchY;
void*paSrcRects;
void*paDstRects;
typedef struct CR_SERVER_BUGGY_MURAL_DATA
{
{
unsigned long key;
bool fBuggyMuralData = false;
/* Load windows */
{
char psz[200];
unsigned long key;
if (createInfo.pszDpyName)
{
}
}
/* Load cr_server.muralTable */
{
{
/* Lookahead buffer used to determine whether the data erroneously storred root visible regions data */
union
{
void * apv[1];
/* need to chak spuWindow, so taking the offset of filed following it*/
} LaBuf;
do {
/* first value is bool (uint8_t) value followed by pointer-size-based alignment.
* the mural memory is zero-initialized initially, so we can be sure the padding is zeroed,
* i.e. possible values for visible regions data are 0 or (1 << (sizeof (void*) - 8)) */
break;
/* check that the pointers are either valid or NULL */
break;
break;
if(LaBuf.Data.RootVrCEntry.Vr.ListHead_pNext && !RT_VALID_PTR(LaBuf.Data.RootVrCEntry.Vr.ListHead_pNext))
break;
if(LaBuf.Data.RootVrCEntry.Vr.ListHead_pPrev && !RT_VALID_PTR(LaBuf.Data.RootVrCEntry.Vr.ListHead_pPrev))
break;
/* the entry can can be the only one within the (mural) compositor,
* so its compositor entry node can either contain NULL pNext and pPrev,
* or both of them pointing to compositor's list head */
break;
/* can either both or none be NULL */
break;
{
break;
/* either non-initialized (zeroed) or empty list */
break;
break;
}
else
{
/* the entry should be initialized */
break;
break;
{
/* entry should be in compositor list*/
break;
}
else
{
/* entry should NOT be in compositor list*/
break;
}
}
#if 0
if (muralInfo.pVisibleRects)
{
int j;
for (j = 0; j < cRects; ++j)
{
break;
break;
break;
break;
break;
}
if (j < cRects)
{
fBuggyMuralData = true;
break;
}
}
if (muralInfo.pVisibleRects)
{
/* @todo: do we actually need any further checks here? */
fBuggyMuralData = true;
break;
}
/* no visible regions*/
{
/* this is the last mural, next it goes idsPool, whose content can not match the above template again */
fBuggyMuralData = true;
break;
}
/* next it goes a next mural info */
// if (!fExpectPtr)
// {
// CRMuralInfo *pNextSpuWindowInfoMural = (CRMuralInfo*)((void*)&LaBuf);
// if (!pNextSpuWindowInfoMural->spuWindow)
// fBuggyMuralData = true;
//
// break;
// }
#endif
/* fExpectPtr == true, the valid pointer values should not match possible mural width/height/position */
fBuggyMuralData = true;
break;
} while (0);
}
if (fBuggyMuralData)
{
}
if (muralInfo.pVisibleRects)
{
if (!muralInfo.pVisibleRects)
{
return VERR_NO_MEMORY;
}
rc = crServerLsrDataGetMem(pReader, muralInfo.pVisibleRects, 4*sizeof(GLint)*muralInfo.cVisibleRects);
}
{
}
/* 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)
{
}
else
}
return VINF_SUCCESS;
}
{
GLuint i;
/* can apply the data right away */
struct
{
CRFBDataElement buffer[3]; /* CRFBData::aElements[1] + buffer[3] gives 4: back, front, depth and stencil */
} Data;
{
return VINF_SUCCESS;
if (!RT_SUCCESS(rc))
{
return rc;
}
}
else
{
{
}
else
{
}
if (!storedWidth || !storedHeight)
return VINF_SUCCESS;
rc = crVBoxServerFBImageDataInitEx(&Data.data, pContextInfo, pMural, GL_TRUE, version, storedWidth, storedHeight);
if (!RT_SUCCESS(rc))
{
return rc;
}
}
{
}
{
/* can apply the data right away */
0,
pContextInfo->SpuContext >= 0
if ((pMural->fPresentMode & CR_SERVER_REDIR_F_FBO) && pMural->fDataPresented && crServerVBoxCompositionPresentNeeded(pMural))
{
}
0,
}
else
{
CRASSERT(Data.data.cElements); /* <- older versions always saved front and back, and we filtered out the null-sized buffers above */
{
if (!RT_SUCCESS(rc))
{
crWarning("crAlloc failed");
return VERR_NO_MEMORY;
}
}
}
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;
}
{
}
#ifdef DEBUG_misha
#define CR_DBG_STR_STATE_LOAD_START "VBox.Cr.StateLoadStart"
#define CR_DBG_STR_STATE_LOAD_STOP "VBox.Cr.StateLoadStop"
cr_server.head_spu->dispatch_table.StringMarkerGREMEDY(sizeof (CR_DBG_STR_STATE_LOAD_START), CR_DBG_STR_STATE_LOAD_START);
#endif
/* 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 */
}
if (uiNumElems)
{
/* ensure we have main context set up as current */
}
/* 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 */
}
}
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
#ifdef DEBUG_misha
cr_server.head_spu->dispatch_table.StringMarkerGREMEDY(sizeof (CR_DBG_STR_STATE_LOAD_STOP), CR_DBG_STR_STATE_LOAD_STOP);
#endif
return VINF_SUCCESS;
}
{
}
{
/* this is something unexpected, but just in case */
{
return;
}
}
{
if (cr_server.cDisableEvents)
return;
if (idScreen < 0)
{
int32_t i = 0;
for (; i < cr_server.screenCount; ++i)
{
}
return;
}
if (!cr_server.aWinVisibilityInfos[idScreen].cVisibleWindows == !cr_server.aWinVisibilityInfos[idScreen].fLastReportedVisible)
return;
cr_server.aWinVisibilityInfos[idScreen].fLastReportedVisible = cr_server.aWinVisibilityInfos[idScreen].cVisibleWindows ? 1 : 0;
}
{
{
}
}
{
(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;
{
if (pDisplay)
}
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++)
{
{
{
}
}
}
}
#endif
{
if (pDisplay)
}
return VINF_SUCCESS;
}
{
int rc = VINF_SUCCESS;
{
{
}
if (!RT_SUCCESS(rc))
{
goto end;
}
}
else
{
}
end:
return rc;
}
{
return;
(void) data2;
}
{
/* non-zero rects pointer indicate rects are present and switched on
* i.e. cRects==0 and pRects!=NULL means root visible regioning is ON and there are no visible regions,
* while pRects==NULL means root visible regioning is OFF, i.e. everything is visible */
if (pRects)
{
if (!RT_SUCCESS(rc))
{
return rc;
}
}
else
{
return VINF_SUCCESS;
}
return VINF_SUCCESS;
}
{
}
{
/* sanitize values */
if (value == CR_SERVER_REDIR_F_NONE)
{
crWarning("crServerSetOffscreenRenderingMode: value undefined");
}
{
return VINF_SUCCESS;
}
{
crWarning("crServerSetOffscreenRenderingMode: FBO not supported");
return VERR_NOT_SUPPORTED;
}
return VINF_SUCCESS;
}
{
return crServerSetOffscreenRenderingMode(value ?
}
{
}
{
/* No need for a synchronization as this is single threaded. */
if (pCallbacks)
{
cr_server.bUseOutputRedirect = true;
}
else
{
cr_server.bUseOutputRedirect = false;
}
/* dynamically intercept already existing output */
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 */
}
if (fPosChanged || fSizeChanged)
{
if (pDisplay)
}
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