static void crStateCopyShaderCB(unsigned long key, void *data1, void *data2)
{
    CRGLSLShader *pRealShader = (CRGLSLShader *) data1;
    CRGLSLProgram *pProgram = (CRGLSLProgram *) data2;
    CRGLSLShader *pShader;
    GLint sLen=0;

    CRASSERT(pRealShader);
    pRealShader->refCount++;

    pShader = (CRGLSLShader *) crAlloc(sizeof(*pShader));
    if (!pShader)
    {
        crWarning("crStateCopyShaderCB: Out of memory!");
        return;
    }

    crMemcpy(pShader, pRealShader, sizeof(*pShader));

    diff_api.GetShaderiv(pShader->hwid, GL_SHADER_SOURCE_LENGTH, &sLen);
    if (sLen>0)
    {
        pShader->source = (GLchar*) crAlloc(sLen);
        diff_api.GetShaderSource(pShader->hwid, sLen, NULL, pShader->source);
    }

    crHashtableAdd(pProgram->activeState.attachedShaders, key, pShader);
}
DECLEXPORT(void) STATE_APIENTRY crStateAttachShader(GLuint program, GLuint shader)
{
    CRGLSLProgram *pProgram = crStateGetProgramObj(program);
    CRGLSLShader *pShader;

    if (!pProgram)
    {
        crWarning("Unknown program %d", program);
        return;
    }

    if (crHashtableSearch(pProgram->currentState.attachedShaders, shader))
    {
        /*shader already attached to this program*/
        return;
    }

    pShader = crStateGetShaderObj(shader);

    if (!pShader)
    {
        crWarning("Unknown shader %d", shader);
        return;
    }

    pShader->refCount++;

    crHashtableAdd(pProgram->currentState.attachedShaders, shader, pShader);
}
Beispiel #3
0
GLint renderspuWindowCreateEx( const char *dpyName, GLint visBits, GLint id )
{
    WindowInfo *window;
    VisualInfo *visual;
    GLboolean showIt;

    if (id <= 0)
    {
        id = (GLint)crHashtableAllocKeys(render_spu.windowTable, 1);
        if (id <= 0)
        {
            crWarning("failed to allocate window id");
            return -1;
        }
    }
    else
    {
        if (crHashtableIsKeyUsed(render_spu.windowTable, id))
        {
            crWarning("the specified window key %d is in use", id);
            return -1;
        }
    }


    if (!dpyName || crStrlen(render_spu.display_string) > 0)
        dpyName = render_spu.display_string;

    visual = renderspuFindVisual( dpyName, visBits );
    if (!visual)
    {
        crWarning( "Render SPU: Couldn't create a window, renderspuFindVisual returned NULL" );
        return -1;
    }

    /* Allocate WindowInfo */
    window = (WindowInfo *) crCalloc(sizeof(WindowInfo));
    if (!window)
    {
        crWarning( "Render SPU: Couldn't create a window" );
        return -1;
    }
    
    crHashtableAdd(render_spu.windowTable, id, window);

    showIt = 0;

    /*
    crDebug("Render SPU: Creating window (visBits=0x%x, id=%d)", visBits, window->BltInfo.Base.id);
    */
    /* Have GLX/WGL/AGL create the window */
    if (!renderspuWindowInit( window, visual, showIt, id ))
    {
        crFree(window);
        crWarning( "Render SPU: Couldn't create a window, renderspu_SystemCreateWindow failed" );
        return -1;
    }
    
    return window->BltInfo.Base.id;
}
Beispiel #4
0
void crHashtableReplace( CRHashTable *h, unsigned long key, void *data,
                         CRHashtableCallback deleteFunc)
{
    unsigned int index = crHash( key );
    CRHashNode *temp;
#ifdef CHROMIUM_THREADSAFE
    crLockMutex(&h->mutex);
#endif
    for ( temp = h->buckets[index]; temp; temp = temp->next )
    {
        if ( temp->key == key )
            break;
    }
#ifdef CHROMIUM_THREADSAFE
    crUnlockMutex(&h->mutex);
#endif
    if ( !temp )
    {
        crHashtableAdd( h, key, data );
        return;
    }
#ifdef CHROMIUM_THREADSAFE
    crLockMutex(&h->mutex);
#endif
    if ( temp->data && deleteFunc )
    {
        (*deleteFunc)( temp->data );
    }
    temp->data = data;
#ifdef CHROMIUM_THREADSAFE
    crUnlockMutex(&h->mutex);
#endif
}
Beispiel #5
0
static GLint BINARYSWAPSPU_APIENTRY
binaryswapspuCreateContext(const char *dpyName, GLint visBits, GLint shareCtx)
{
	static GLint freeID = 0;
	ContextInfo *context;
	GLint childVisBits, superVisBits;
	GLint childShareCtx = 0, superShareCtx = 0;

	CRASSERT(binaryswap_spu.child.BarrierCreateCR);

	if (shareCtx > 0) {
		/* get child/super context IDs */
		context =
			(ContextInfo *) crHashtableSearch(binaryswap_spu.contextTable, shareCtx);
		if (context) {
			childShareCtx = context->childContext;
			superShareCtx = context->renderContext;
		}
	}


	if (freeID != 0)
	{
		crError("Binaryswap cannot support multiple contexts");
		return 0;
	}

	context = (ContextInfo *) crCalloc(sizeof(ContextInfo));
	if (!context)
	{
		crWarning("binaryswap SPU: create context failed.");
		return -1;
	}

	binaryswapspuTweakVisBits(visBits, &childVisBits, &superVisBits);

	context->renderContext =
		binaryswap_spu.super.CreateContext(dpyName, superVisBits, superShareCtx);
	context->childContext =
		binaryswap_spu.child.CreateContext(dpyName, childVisBits, childShareCtx);
	context->childVisBits = childVisBits;
	context->superVisBits = superVisBits;

	if (context->renderContext < 0 || context->childContext < 0)
	{
		crFree(context);
		return -1;
	}

	/* put into hash table */
	crHashtableAdd(binaryswap_spu.contextTable, freeID, context);
	freeID++;
	return freeID - 1;
}
Beispiel #6
0
DECLEXPORT(GLuint) STATE_APIENTRY crStateCreateProgram(GLuint hwid)
{
    CRGLSLProgram *pProgram;
    CRContext *g = GetCurrentContext();
    GLuint stateId = hwid;

#ifdef IN_GUEST
    pProgram = crStateGetProgramObj(stateId);
    if (pProgram)
    {
        crWarning("Program object %d already exists!", stateId);
        crStateDeleteProgram(stateId);
        CRASSERT(!crStateGetProgramObj(stateId));
    }
#else
    /* the id may not necesserily be hwid after save state restoration */
    while ((pProgram = crStateGetProgramObj(stateId)) != NULL)
    {
        GLuint newStateId = stateId + 7;
        crDebug("Program object %d already exists, generating a new one, %d", stateId, newStateId);
        stateId = newStateId;
    }
#endif

    pProgram = (CRGLSLProgram *) crAlloc(sizeof(*pProgram));
    if (!pProgram)
    {
        crWarning("crStateCreateShader: Out of memory!");
        return 0;
    }

    pProgram->id = stateId;
    pProgram->hwid = hwid;
    pProgram->validated = GL_FALSE;
    pProgram->linked = GL_FALSE;
    pProgram->deleted = GL_FALSE;
    pProgram->activeState.attachedShaders = NULL;
    pProgram->currentState.attachedShaders = crAllocHashtable();

    pProgram->activeState.cAttribs = 0;
    pProgram->activeState.pAttribs = NULL;
    pProgram->currentState.cAttribs = 0;
    pProgram->currentState.pAttribs = NULL;

    pProgram->pUniforms = NULL;
    pProgram->cUniforms = 0;
#ifdef IN_GUEST
    pProgram->bUniformsSynced = GL_FALSE;
#endif

    crHashtableAdd(g->glsl.programs, stateId, pProgram);

    return stateId;
}
DECLEXPORT(GLuint) STATE_APIENTRY crStateCreateProgram(GLuint hwid)
{
    CRGLSLProgram *pProgram;
    CRContext *g = GetCurrentContext();
    GLuint stateId = hwid;

#ifdef IN_GUEST
    pProgram = crStateGetProgramObj(stateId);
    if (pProgram)
    {
        crWarning("Program object %d already exists!", stateId);
        crStateDeleteProgram(stateId);
        CRASSERT(!crStateGetProgramObj(stateId));
    }
#else
    stateId = crHashtableAllocKeys(g->glsl.programs, 1);
    if (!stateId)
    {
        crWarning("failed to allocate program key");
        return 0;
    }
#endif

    pProgram = (CRGLSLProgram *) crAlloc(sizeof(*pProgram));
    if (!pProgram)
    {
        crWarning("crStateCreateProgram: Out of memory!");
        return 0;
    }

    pProgram->id = stateId;
    pProgram->hwid = hwid;
    pProgram->validated = GL_FALSE;
    pProgram->linked = GL_FALSE;
    pProgram->deleted = GL_FALSE;
    pProgram->activeState.attachedShaders = NULL;
    pProgram->currentState.attachedShaders = crAllocHashtable();

    pProgram->activeState.cAttribs = 0;
    pProgram->activeState.pAttribs = NULL;
    pProgram->currentState.cAttribs = 0;
    pProgram->currentState.pAttribs = NULL;

    pProgram->pUniforms = NULL;
    pProgram->cUniforms = 0;
#ifdef IN_GUEST
    pProgram->bUniformsSynced = GL_FALSE;
#endif

    crHashtableAdd(g->glsl.programs, stateId, pProgram);

    return stateId;
}
Beispiel #8
0
static ContextInfo * renderspuCreateContextInternal(const char *dpyName, GLint visBits, GLint idCtx, ContextInfo * sharedContext)
{
    ContextInfo *context;
    VisualInfo *visual;

    if (idCtx <= 0)
    {
        idCtx = (GLint)crHashtableAllocKeys(render_spu.contextTable, 1);
        if (idCtx <= 0)
        {
            crWarning("failed to allocate context id");
            return NULL;
        }
    }
    else
    {
        if (crHashtableIsKeyUsed(render_spu.contextTable, idCtx))
        {
            crWarning("the specified ctx key %d is in use", idCtx);
            return NULL;
        }
    }


    if (!dpyName || crStrlen(render_spu.display_string)>0)
        dpyName = render_spu.display_string;

    visual = renderspuFindVisual(dpyName, visBits);
    if (!visual)
        return NULL;

    context = (ContextInfo *) crCalloc(sizeof(ContextInfo));
    if (!context)
        return NULL;
    context->BltInfo.Base.id = idCtx;
    context->shared = sharedContext;
    if (!renderspu_SystemCreateContext(visual, context, sharedContext))
        return NULL;

    crHashtableAdd(render_spu.contextTable, idCtx, context);

    context->BltInfo.Base.visualBits = visual->visAttribs;
    /*
    crDebug("Render SPU: CreateContext(%s, 0x%x) returning %d",
                    dpyName, visBits, context->BltInfo.Base.id);
    */

    if (sharedContext)
        ASMAtomicIncU32(&sharedContext->cRefs);
    context->cRefs = 1;

    return context;
}
Beispiel #9
0
static SPUFunctions *
readbackSPUInit( int id, SPU *child, SPU *self,
								 unsigned int context_id,
								 unsigned int num_contexts )
{
	WindowInfo *window;
	(void) context_id;
	(void) num_contexts;

#ifdef CHROMIUM_THREADSAFE
	crDebug("Readback SPU: thread-safe");
#endif

	crMemZero(&readback_spu, sizeof(readback_spu));
	readback_spu.id = id;
	readback_spu.has_child = 0;
	if (child)
	{
		crSPUInitDispatchTable( &(readback_spu.child) );
		crSPUCopyDispatchTable( &(readback_spu.child), &(child->dispatch_table) );
		readback_spu.has_child = 1;
	}
	else
	{
	   /* don't override any API functions - use the Render SPU functions */
	   static SPUNamedFunctionTable empty_table[] = {
		  { NULL, NULL }
	   };
	   readback_functions.table = empty_table;
	}
	crSPUInitDispatchTable( &(readback_spu.super) );
	crSPUCopyDispatchTable( &(readback_spu.super), &(self->superSPU->dispatch_table) );
	readbackspuGatherConfiguration( &readback_spu );

	readback_spu.contextTable = crAllocHashtable();
	readback_spu.windowTable = crAllocHashtable();

	/* create my default window (window number 0) */
	window = (WindowInfo *) crCalloc(sizeof(WindowInfo));
	CRASSERT(window);
	window->index = 0;
	window->renderWindow = 0; /* default render SPU window */
	window->childWindow = 0;  /* default child SPU window */
	readbackspuTweakVisBits(readback_spu.default_visual,
													&window->childVisBits,
													&window->superVisBits);
	crHashtableAdd(readback_spu.windowTable, 0, window);

	readback_spu.gather_conn = NULL;

	return &readback_functions;
}
static CRServerProgram *
LookupProgram(GLuint id)
{
    CRServerProgram *prog = (CRServerProgram *)crHashtableSearch(cr_server.programTable, id);
    if (!prog) {
        prog = (CRServerProgram *) crAlloc(sizeof(CRServerProgram));
        if (!prog)
            return NULL;
        prog->id = id;
        prog->projParamStart = cr_server.vpProjectionMatrixParameter;
        crHashtableAdd(cr_server.programTable, id, prog);
    }
    return prog;
}
Beispiel #11
0
PCR_BLITTER renderspuVBoxPresentBlitterGet( WindowInfo *window )
{
    PCR_BLITTER pBlitter = window->pBlitter;
    if (!pBlitter)
    {
        if (render_spu.blitterTable)
        {
            crHashtableLock(render_spu.blitterTable);
            pBlitter = (PCR_BLITTER)crHashtableSearch(render_spu.blitterTable, window->visual->visAttribs);
        }

        if (!pBlitter)
        {
            int rc;
            CR_BLITTER_CONTEXT ctx;
            pBlitter = (PCR_BLITTER)crCalloc(sizeof (*pBlitter));
            if (!pBlitter)
            {
                crWarning("failed to allocate blitter");
                return NULL;
            }

            /* @todo: this is the assumption that crserverlib uses context 1 as a default one
             * need to do it in a more proper way */
            ctx.Base.id = 1;
            ctx.Base.visualBits = window->visual->visAttribs;
            rc = CrBltInit(pBlitter, &ctx, true, true, render_spu.blitterDispatch);
            if (!RT_SUCCESS(rc))
            {
                crWarning("CrBltInit failed, rc %d", rc);
                crFree(pBlitter);
                return NULL;
            }

            if (render_spu.blitterTable)
            {
                crHashtableAdd( render_spu.blitterTable, window->visual->visAttribs, pBlitter );
            }
        }

        if (render_spu.blitterTable)
            crHashtableUnlock(render_spu.blitterTable);

        Assert(pBlitter);
        window->pBlitter = pBlitter;
    }

    CrBltMuralSetCurrent(pBlitter, &window->BltInfo);
    return pBlitter;
}
Beispiel #12
0
/**
 * Create a new _Chromium_ window, not GLX, WGL or CGL.
 * Called by crWindowCreate() only.
 */
    GLint
stubNewWindow( const char *dpyName, GLint visBits )
{
    WindowInfo *winInfo;
    GLint spuWin, size[2];

    spuWin = stub.spu->dispatch_table.WindowCreate( dpyName, visBits );
    if (spuWin < 0) {
	return -1;
    }

    winInfo = (WindowInfo *) crCalloc(sizeof(WindowInfo));
    if (!winInfo) {
	stub.spu->dispatch_table.WindowDestroy(spuWin);
	return -1;
    }

    winInfo->type = CHROMIUM;

    /* Ask the head SPU for the initial window size */
    size[0] = size[1] = 0;
    stub.spu->dispatch_table.GetChromiumParametervCR(GL_WINDOW_SIZE_CR, 0, GL_INT, 2, size);
    if (size[0] == 0 && size[1] == 0) {
	/* use some reasonable defaults */
	size[0] = size[1] = 512;
    }
    winInfo->width = size[0];
    winInfo->height = size[1];
    winInfo->mapped = 1;

    if (!dpyName)
	dpyName = "";

    crStrncpy(winInfo->dpyName, dpyName, MAX_DPY_NAME);
    winInfo->dpyName[MAX_DPY_NAME-1] = 0;

    /* Use spuWin as the hash table index and GLX/WGL handle */
#ifdef WINDOWS
    winInfo->drawable = (HDC) spuWin;
#elif defined(Darwin)
    winInfo->drawable = (CGSWindowID) spuWin;
#elif defined(GLX)
    winInfo->drawable = (GLXDrawable) spuWin;
#endif
    winInfo->spuWindow = spuWin;

    crHashtableAdd(stub.windowTable, (unsigned int) spuWin, winInfo);

    return spuWin;
}
Beispiel #13
0
/**
 * Allocate a new ContextInfo object, initialize it, put it into the
 * context hash table.  If type==CHROMIUM, call the head SPU's
 * CreateContext() function too.
 */
    ContextInfo *
stubNewContext( const char *dpyName, GLint visBits, ContextType type,
	unsigned long shareCtx )
{
    GLint spuContext = -1, spuShareCtx = 0;
    ContextInfo *context;

    if (shareCtx > 0) {
	/* translate shareCtx to a SPU context ID */
	context = (ContextInfo *)
	    crHashtableSearch(stub.contextTable, shareCtx);
		if (context)
			spuShareCtx = context->spuContext;
	}

	if (type == CHROMIUM) {
		spuContext
			= stub.spu->dispatch_table.CreateContext(dpyName, visBits, spuShareCtx);
		if (spuContext < 0)
			return NULL;
	}

	context = crCalloc(sizeof(ContextInfo));
	if (!context) {
		stub.spu->dispatch_table.DestroyContext(spuContext);
		return NULL;
	}

	if (!dpyName)
		dpyName = "";

	context->id = stub.freeContextNumber++;
	context->type = type;
	context->spuContext = spuContext;
	context->visBits = visBits;
	context->currentDrawable = NULL;
	crStrncpy(context->dpyName, dpyName, MAX_DPY_NAME);
	context->dpyName[MAX_DPY_NAME-1] = 0;

#if defined(GLX) || defined(DARWIN)
	context->share = (ContextInfo *)
		crHashtableSearch(stub.contextTable, (unsigned long) shareCtx);
#endif

	crHashtableAdd(stub.contextTable, context->id, (void *) context);

	return context;
}
Beispiel #14
0
static GLint BINARYSWAPSPU_APIENTRY
binaryswapspuWindowCreate(const char *dpyName, GLint visBits)
{
	WindowInfo *window;
	static GLint freeID = 1;			/* skip default window 0 */
	GLint childVisBits, superVisBits;

	/* Error out on second window */
	if (freeID != 1)
	{
		crError("Binaryswap can't deal with multiple windows!");
		return 0;
	}

	/* allocate window */
	window = (WindowInfo *) crCalloc(sizeof(WindowInfo));
	if (!window)
	{
		crWarning("binaryswap SPU: unable to allocate window.");
		return -1;
	}

	binaryswapspuTweakVisBits(visBits, &childVisBits, &superVisBits);

	/* init window */
	window->index = freeID;
	window->renderWindow =
		binaryswap_spu.super.WindowCreate(dpyName, superVisBits);
	window->childWindow =
		binaryswap_spu.child.WindowCreate(dpyName, childVisBits);
	window->width = -1;						/* unknown */
	window->height = -1;					/* unknown */
	window->msgBuffer = NULL;
	window->childVisBits = childVisBits;
	window->superVisBits = superVisBits;

	if (window->renderWindow < 0 || window->childWindow < 0)
	{
		crFree(window);
		return -1;
	}

	/* put into hash table */
	crHashtableAdd(binaryswap_spu.windowTable, window->index, window);
	freeID++;

	return freeID - 1;
}
Beispiel #15
0
void STATE_APIENTRY
crStateBeginQueryARB(GLenum target, GLuint id)
{
	CRContext *g = GetCurrentContext();
	CROcclusionState *o = &(g->occlusion);
	CROcclusionObject *q;

	FLUSH();

	if (g->current.inBeginEnd) {
		crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
								 "glGetGetQueryObjectuivARB called in begin/end");
		return;
	}

	if (target != GL_SAMPLES_PASSED_ARB) {
		crStateError(__LINE__, __FILE__, GL_INVALID_ENUM,
								 "glBeginQueryARB(target)");
		return;
	}

	if (o->currentQueryObject) {
		crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
								 "glBeginQueryARB(target)");
		return;
	}

	q = (CROcclusionObject *) crHashtableSearch(o->objects, id);
	if (q && q->active) {
		crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION, "glBeginQueryARB");
		return;
	}
	else if (!q) {
		q = NewQueryObject(target, id);
		if (!q) {
			crStateError(__LINE__, __FILE__, GL_OUT_OF_MEMORY, "glBeginQueryARB");
			return;
		}
		crHashtableAdd(o->objects, id, q);
	}
	
	q->active = GL_TRUE;
	q->passedCounter = 0;
	q->active = GL_TRUE;
	q->passedCounter = 0;
	o->currentQueryObject = id;
}
Beispiel #16
0
PCR_DISPLAY_ENTRY CrDemEntryGetCreate(PCR_DISPLAY_ENTRY_MAP pMap, GLuint idTexture, CRContextInfo *pCtxInfo)
{
    PCR_DISPLAY_ENTRY pEntry = (PCR_DISPLAY_ENTRY)crHashtableSearch(pMap->pTextureMap, idTexture);
    if (pEntry)
        return pEntry;

    CRContext *pContext = pCtxInfo->pContext;
    if (!pContext)
    {
        crWarning("pContext is null!");
        return NULL;
    }

    CRTextureObj *pTobj = (CRTextureObj*)crHashtableSearch(pContext->shared->textureTable, idTexture);
    if (!pTobj)
    {
        crWarning("pTobj is null!");
        return NULL;
    }

    GLuint hwId = crStateGetTextureObjHWID(pTobj);
    if (!hwId)
    {
        crWarning("hwId is null!");
        return NULL;
    }

    VBOXVR_TEXTURE TextureData;
    TextureData.width = pTobj->level[0]->width;
    TextureData.height = pTobj->level[0]->height;
    TextureData.target = pTobj->target;
    TextureData.hwid = hwId;

    pEntry = (PCR_DISPLAY_ENTRY)crAlloc(sizeof (*pEntry));
    if (!pEntry)
    {
        crWarning("crAlloc failed allocating CR_DISPLAY_ENTRY");
        return NULL;
    }

    CrDpEntryInit(pEntry, &TextureData);

    crHashtableAdd(pMap->pTextureMap, idTexture, pEntry);
    return pEntry;

}
Beispiel #17
0
GLint PACKSPU_APIENTRY packspu_WindowCreate( const char *dpyName, GLint visBits )
{
	static int num_calls = 0;
	int writeback = pack_spu.thread[0].netServer.conn->actual_network;
	GLint return_val = (GLint) 0;
	WindowInfo *WInfo;

	/* WindowCreate is special - just like CreateContext.
	 * GET_THREAD(thread) doesn't work as the thread won't have called
	 * MakeCurrent yet, so we've got to use the first thread's packer
	 * buffer.
	 */

	crPackSetContext( pack_spu.thread[0].packer );

	if (pack_spu.swap)
	{
		crPackWindowCreateSWAP( dpyName, visBits, &return_val, &writeback );
	}
	else
	{
		crPackWindowCreate( dpyName, visBits, &return_val, &writeback );
	}
	packspuFlush( &pack_spu.thread[0] );
	if (!(pack_spu.thread[0].netServer.conn->actual_network))
	{
		return num_calls++;
	}
	else
	{
		while (writeback)
			crNetRecv();
		if (pack_spu.swap)
		{
			return_val = (GLint) SWAP32(return_val);
		}
		WInfo = (WindowInfo *) crAlloc(sizeof(WindowInfo));
		WInfo->XWindow = 0;
		WInfo->visual = visBits;
		crHashtableAdd(pack_spu.XWindows,return_val,WInfo);
		return return_val;
	}
}
DECLEXPORT(GLuint) STATE_APIENTRY crStateCreateShader(GLuint hwid, GLenum type)
{
    CRGLSLShader *pShader;
    CRContext *g = GetCurrentContext();
    GLuint stateId = hwid;

#ifdef IN_GUEST
    CRASSERT(!crStateGetShaderObj(stateId));
#else
    /* the proogram and shader names must not intersect because DeleteObjectARB must distinguish between them
     * see crStateDeleteObjectARB
     * this is why use programs table for shader keys allocation */
    stateId = crHashtableAllocKeys(g->glsl.programs, 1);
    if (!stateId)
    {
        crWarning("failed to allocate program key");
        return 0;
    }

    Assert((pShader = crStateGetShaderObj(stateId)) == NULL);
#endif

    pShader = (CRGLSLShader *) crAlloc(sizeof(*pShader));
    if (!pShader)
    {
        crWarning("crStateCreateShader: Out of memory!");
        return 0;
    }

    pShader->id = stateId;
    pShader->hwid = hwid;
    pShader->type = type;
    pShader->source = NULL;
    pShader->compiled = GL_FALSE;
    pShader->deleted = GL_FALSE;
    pShader->refCount = 0;

    crHashtableAdd(g->glsl.shaders, stateId, pShader);

    return stateId;
}
void SERVER_DISPATCH_APIENTRY crServerDispatchSemaphoreCreateCR( GLuint name, GLuint count )
{
	CRServerSemaphore *sema;

	if (cr_server.ignore_papi)
	{
		cr_server.head_spu->dispatch_table.SemaphoreCreateCR( name, count );
		return;
	}

	sema = crHashtableSearch(cr_server.semaphores, name);
	if (sema)
		return; /* already created */

	sema = (CRServerSemaphore *) crAlloc( sizeof( *sema ) );
	crHashtableAdd( cr_server.semaphores, name, sema );
	sema->count = count;
	sema->waiting = sema->tail = NULL;
	if (cr_server.debug_barriers)
		crDebug("crserver: SemaphoreCreate(id=%d, count=%d)", name, count);
}
Beispiel #20
0
stubGetWindowInfo( Display *dpy, GLXDrawable drawable )
#endif
{
    WindowInfo *winInfo = (WindowInfo *) crHashtableSearch(stub.windowTable, (unsigned int) drawable);
    if (!winInfo) {
	winInfo = (WindowInfo *) crCalloc(sizeof(WindowInfo));
	if (!winInfo)
	    return NULL;
#ifdef GLX
	crStrncpy(winInfo->dpyName, DisplayString(dpy), MAX_DPY_NAME);
	winInfo->dpyName[MAX_DPY_NAME-1] = 0;
	winInfo->dpy = dpy;
#elif defined(Darwin)
	winInfo->connection = _CGSDefaultConnection(); // store our connection as default
#endif
	winInfo->drawable = drawable;
	winInfo->type = UNDECIDED;
	winInfo->spuWindow = -1;
	winInfo->mapped = -1; /* don't know */
	crHashtableAdd(stub.windowTable, (unsigned int) drawable, winInfo);
    }
    return winInfo;
}
Beispiel #21
0
DECLEXPORT(GLuint) STATE_APIENTRY crStateCreateShader(GLuint hwid, GLenum type)
{
    CRGLSLShader *pShader;
    CRContext *g = GetCurrentContext();
    GLuint stateId = hwid;

#ifdef IN_GUEST
    CRASSERT(!crStateGetShaderObj(stateId));
#else
    /* the id may not necesserily be hwid after save state restoration */
    while ((pShader = crStateGetShaderObj(stateId)) != NULL)
    {
        GLuint newStateId = stateId + 7;
        crDebug("Shader object %d already exists, generating a new one, %d", stateId, newStateId);
        stateId = newStateId;
    }
#endif

    pShader = (CRGLSLShader *) crAlloc(sizeof(*pShader));
    if (!pShader)
    {
        crWarning("crStateCreateShader: Out of memory!");
        return 0;
    }

    pShader->id = stateId;
    pShader->hwid = hwid;
    pShader->type = type;
    pShader->source = NULL;
    pShader->compiled = GL_FALSE;
    pShader->deleted = GL_FALSE;
    pShader->refCount = 0;

    crHashtableAdd(g->glsl.shaders, stateId, pShader);

    return stateId;
}
Beispiel #22
0
static void MATTESPU_APIENTRY matteMakeCurrent(GLint crWindow, GLint nativeWindow, GLint ctx)
{
    ContextInfo *contextInfo;

    matte_spu.super.MakeCurrent(crWindow, nativeWindow, ctx);

    /* If we've already got a context record for this, use it.
     * Otherwise, make a new one.
     */
    contextInfo = crHashtableSearch(matte_spu.contextTable, ctx);
    if (contextInfo == NULL) {
	/* Make our own. */
	contextInfo = crCalloc(sizeof(ContextInfo));
	if (contextInfo == NULL) {
	    crError("matte: could not allocate context info record for context %d", ctx);
	    return;
	}

	crHashtableAdd(matte_spu.contextTable, ctx, contextInfo);
    }

    /* Set this a s the current context */
    SET_CONTEXT_INFO(contextInfo);
}
Beispiel #23
0
GLint RENDER_APIENTRY
renderspuCreateContext(const char *dpyName, GLint visBits, GLint shareCtx)
{
	ContextInfo *context, *sharedContext = NULL;
	VisualInfo *visual;

	if (shareCtx > 0) {
		sharedContext
			= (ContextInfo *) crHashtableSearch(render_spu.contextTable, shareCtx);
	}

	if (!dpyName || crStrlen(render_spu.display_string)>0)
		dpyName = render_spu.display_string;

	visual = renderspuFindVisual(dpyName, visBits);
	if (!visual)
		return -1;

	context = (ContextInfo *) crCalloc(sizeof(ContextInfo));
	if (!context)
		return -1;
	context->id = render_spu.context_id;
	context->shared = sharedContext;
	if (!renderspu_SystemCreateContext(visual, context, sharedContext))
		return -1;

	crHashtableAdd(render_spu.contextTable, render_spu.context_id, context);
	render_spu.context_id++;

	/*
	crDebug("Render SPU: CreateContext(%s, 0x%x) returning %d",
					dpyName, visBits, context->id);
	*/

	return context->id;
}
static CRRenderbufferObject *
crStateRenderbufferAllocate(CRContext *ctx, GLuint name)
{
    CRRenderbufferObject *buffer = (CRRenderbufferObject*) crCalloc(sizeof(CRRenderbufferObject));
    CRSTATE_CHECKERR_RET(!buffer, GL_OUT_OF_MEMORY, "crStateRenderbufferAllocate", NULL);
    buffer->id = name;
#ifndef IN_GUEST
    diff_api.GenRenderbuffersEXT(1, &buffer->hwid);
    if (!buffer->hwid)
    {
        crWarning("GenRenderbuffersEXT failed!");
        crFree(buffer);
        return NULL;
    }
#else
    buffer->hwid = name;
#endif

    buffer->internalformat = GL_RGBA;
    crHashtableAdd(ctx->shared->rbTable, name, buffer);
    CR_STATE_SHAREDOBJ_USAGE_INIT(buffer);

    return buffer;
}
Beispiel #25
0
/**
 * Init variables in the stub structure, install signal handler.
 */
static void stubInitVars(void)
{
    WindowInfo *defaultWin;

#ifdef CHROMIUM_THREADSAFE
    crInitMutex(&stub.mutex);
#endif

    /* At the very least we want CR_RGB_BIT. */
    stub.haveNativeOpenGL = GL_FALSE;
    stub.spu = NULL;
    stub.appDrawCursor = 0;
    stub.minChromiumWindowWidth = 0;
    stub.minChromiumWindowHeight = 0;
    stub.maxChromiumWindowWidth = 0;
    stub.maxChromiumWindowHeight = 0;
    stub.matchChromiumWindowCount = 0;
    stub.matchChromiumWindowID = NULL;
    stub.matchWindowTitle = NULL;
    stub.ignoreFreeglutMenus = 0;
    stub.threadSafe = GL_FALSE;
    stub.trackWindowSize = 0;
    stub.trackWindowPos = 0;
    stub.trackWindowVisibility = 0;
    stub.trackWindowVisibleRgn = 0;
    stub.mothershipPID = 0;
    stub.spu_dir = NULL;

    stub.freeContextNumber = MAGIC_CONTEXT_BASE;
    stub.contextTable = crAllocHashtable();
#ifndef RT_OS_WINDOWS
# ifdef CHROMIUM_THREADSAFE
    if (!g_stubIsCurrentContextTSDInited)
    {
        crInitTSDF(&g_stubCurrentContextTSD, stubThreadTlsDtor);
        g_stubIsCurrentContextTSDInited = true;
    }
# endif
#endif
    stubSetCurrentContext(NULL);

    stub.windowTable = crAllocHashtable();

#ifdef CR_NEWWINTRACK
    stub.bShutdownSyncThread = false;
    stub.hSyncThread = NIL_RTTHREAD;
#endif

    defaultWin = (WindowInfo *) crCalloc(sizeof(WindowInfo));
    defaultWin->type = CHROMIUM;
    defaultWin->spuWindow = 0;  /* window 0 always exists */
#ifdef WINDOWS
    defaultWin->hVisibleRegion = INVALID_HANDLE_VALUE;
#elif defined(GLX)
    defaultWin->pVisibleRegions = NULL;
    defaultWin->cVisibleRegions = 0;
#endif
    crHashtableAdd(stub.windowTable, 0, defaultWin);

#if 1
    atexit(stubExitHandler);
    signal(SIGTERM, stubSignalHandler);
    signal(SIGINT, stubSignalHandler);
#ifndef WINDOWS
    signal(SIGPIPE, SIG_IGN); /* the networking code should catch this */
#endif
#else
    (void) stubExitHandler;
    (void) stubSignalHandler;
#endif
}
void SERVER_DISPATCH_APIENTRY crServerDispatchBarrierCreateCR( GLuint name, GLuint count )
{
	CRServerBarrier *barrier;
#if DEBUG_BARRIERS
	char debug_buf[4096];
#endif

	if (cr_server.ignore_papi)
	{
		cr_server.head_spu->dispatch_table.BarrierCreateCR( name, count );
		return;
	}

	barrier = (CRServerBarrier *) crHashtableSearch( cr_server.barriers, name );

#if DEBUG_BARRIERS
	sprintf( debug_buf, "BarrierCreateCR( %d, %d )", name, count );
	cr_server.head_spu->dispatch_table.ChromiumParametervCR( GL_PRINT_STRING_CR, GL_UNSIGNED_BYTE, sizeof(debug_buf), debug_buf );
#endif
	if (count == 0)
	{
		count = cr_server.numClients;
#if DEBUG_BARRIERS
		sprintf( debug_buf, "changing count to %d", count );
		cr_server.head_spu->dispatch_table.ChromiumParametervCR( GL_PRINT_STRING_CR, GL_UNSIGNED_BYTE, sizeof(debug_buf), debug_buf );
#endif
	}


	/* we use maxBarrierCount in Clear() and SwapBuffers() and also use it
	 * in __getNextClient() for deadlock detection.  The issue is that all
	 * the existing clients may be blocked, but we might soon get another
	 * client connection to break the apparent deadlock.
	 */
	if (count > cr_server.maxBarrierCount)
		cr_server.maxBarrierCount = count;

	if ( barrier == NULL )
	{
		barrier = (CRServerBarrier *) crAlloc( sizeof(*barrier) );
		barrier->count = count;
		barrier->num_waiting = 0;
		barrier->waiting = (RunQueue **) 
			crAlloc( count * sizeof(*(barrier->waiting)) );

		crHashtableAdd( cr_server.barriers, name, barrier );
#if DEBUG_BARRIERS
		sprintf( debug_buf, "This was a new barrier!" );
		cr_server.head_spu->dispatch_table.ChromiumParametervCR( GL_PRINT_STRING_CR, GL_UNSIGNED_BYTE, sizeof(debug_buf), debug_buf );
#endif
	}
	else
	{
		/* HACK -- this allows everybody to create a barrier, and all
           but the first creation are ignored, assuming the count
           match. */
#if DEBUG_BARRIERS
		sprintf( debug_buf, "I already knew about this barrier." );
		cr_server.head_spu->dispatch_table.ChromiumParametervCR( GL_PRINT_STRING_CR, GL_UNSIGNED_BYTE, sizeof(debug_buf), debug_buf );
#endif
		if ( barrier->count != count )
		{
#if DEBUG_BARRIERS
			sprintf( debug_buf, "And someone messed up the count!." );
			cr_server.head_spu->dispatch_table.ChromiumParametervCR( GL_PRINT_STRING_CR, GL_UNSIGNED_BYTE, sizeof(debug_buf), debug_buf );
#endif
			crError( "Barrier name=%u created with count=%u, but already "
						 "exists with count=%u", name, count, barrier->count );
		}
	}

	if (cr_server.debug_barriers)
		crDebug("crserver: BarrierCreate(id=%d, count=%d)", name, barrier->count);
}
/**
 * Allocate a new ContextInfo object, initialize it, put it into the
 * context hash table.  If type==CHROMIUM, call the head SPU's
 * CreateContext() function too.
 */
    ContextInfo *
stubNewContext(char *dpyName, GLint visBits, ContextType type, unsigned long shareCtx
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
        , struct VBOXUHGSMI *pHgsmi
#endif
    )
{
    GLint spuContext = -1, spuShareCtx = 0, spuConnection = 0;
    ContextInfo *context;

    if (shareCtx > 0) {
    /* translate shareCtx to a SPU context ID */
    context = (ContextInfo *)
        crHashtableSearch(stub.contextTable, shareCtx);
        if (context)
            spuShareCtx = context->spuContext;
    }

    if (type == CHROMIUM) {
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
        if (pHgsmi)
        {
            spuConnection = stub.spu->dispatch_table.VBoxConCreate(pHgsmi);
            if (!spuConnection)
            {
                crWarning("VBoxConCreate failed");
                return NULL;
            }
        }
#endif
        spuContext
            = stub.spu->dispatch_table.VBoxCreateContext(spuConnection, dpyName, visBits, spuShareCtx);
        if (spuContext < 0)
        {
            crWarning("VBoxCreateContext failed");
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
            if (spuConnection)
                stub.spu->dispatch_table.VBoxConDestroy(spuConnection);
#endif
            return NULL;
        }
    }

    context = crCalloc(sizeof(ContextInfo));
    if (!context) {
        stub.spu->dispatch_table.DestroyContext(spuContext);
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
        if (spuConnection)
            stub.spu->dispatch_table.VBoxConDestroy(spuConnection);
#endif
        return NULL;
    }

    if (!dpyName)
        dpyName = "";

    context->id = stub.freeContextNumber++;
    context->type = type;
    context->spuContext = spuContext;
    context->visBits = visBits;
    context->currentDrawable = NULL;
    crStrncpy(context->dpyName, dpyName, MAX_DPY_NAME);
    context->dpyName[MAX_DPY_NAME-1] = 0;

#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
    context->spuConnection = spuConnection;
    context->pHgsmi = pHgsmi;
#endif

#ifdef CHROMIUM_THREADSAFE
    VBoxTlsRefInit(context, stubContextDtor);
#endif

#if defined(GLX) || defined(DARWIN)
    context->share = (ContextInfo *)
        crHashtableSearch(stub.contextTable, (unsigned long) shareCtx);
#endif

#ifdef GLX
    context->pGLXPixmapsHash = crAllocHashtable();
    context->damageQueryFailed = GL_FALSE;
    context->damageEventsBase = 0;
#endif

    crHashtableAdd(stub.contextTable, context->id, (void *) context);

    return context;
}
stubGetWindowInfo( Display *dpy, GLXDrawable drawable )
#endif
{
#ifndef WINDOWS
    WindowInfo *winInfo = (WindowInfo *) crHashtableSearch(stub.windowTable, (unsigned int) drawable);
#else
    WindowInfo *winInfo;
    HWND hwnd;
    hwnd = WindowFromDC(drawable);

    if (!hwnd)
    {
        return NULL;
    }

    winInfo = (WindowInfo *) crHashtableSearch(stub.windowTable, (unsigned int) hwnd);
#endif
    if (!winInfo) {
    winInfo = (WindowInfo *) crCalloc(sizeof(WindowInfo));
    if (!winInfo)
        return NULL;
#ifdef GLX
    crStrncpy(winInfo->dpyName, DisplayString(dpy), MAX_DPY_NAME);
    winInfo->dpyName[MAX_DPY_NAME-1] = 0;
    winInfo->dpy = dpy;
    winInfo->pVisibleRegions = NULL;
#elif defined(Darwin)
    winInfo->connection = _CGSDefaultConnection(); // store our connection as default
#elif defined(WINDOWS)
    winInfo->hVisibleRegion = INVALID_HANDLE_VALUE;
    winInfo->hWnd = hwnd;
#endif
    winInfo->drawable = drawable;
    winInfo->type = UNDECIDED;
    winInfo->spuWindow = -1;
#ifdef VBOX_WITH_WDDM
    if (stub.bRunningUnderWDDM)
        winInfo->mapped = 0;
    else
#endif
    {
        winInfo->mapped = -1; /* don't know */
    }
    winInfo->pOwner = NULL;
#ifdef CR_NEWWINTRACK
    winInfo->u32ClientID = -1;
#endif
#ifndef WINDOWS
    crHashtableAdd(stub.windowTable, (unsigned int) drawable, winInfo);
#else
    crHashtableAdd(stub.windowTable, (unsigned int) hwnd, winInfo);
#endif
    }
#ifdef WINDOWS
    else
    {
        winInfo->drawable = drawable;
    }
#endif
    return winInfo;
}
Beispiel #29
0
/**
 * Do CRServer initializations.  After this, we can begin servicing clients.
 */
void
crServerInit(int argc, char *argv[])
{
    int i;
    char *mothership = NULL;
    CRMuralInfo *defaultMural;

    for (i = 1 ; i < argc ; i++)
    {
        if (!crStrcmp( argv[i], "-mothership" ))
        {
            if (i == argc - 1)
            {
                crError( "-mothership requires an argument" );
            }
            mothership = argv[i+1];
            i++;
        }
        else if (!crStrcmp( argv[i], "-port" ))
        {
            /* This is the port on which we'll accept client connections */
            if (i == argc - 1)
            {
                crError( "-port requires an argument" );
            }
            cr_server.tcpip_port = crStrToInt(argv[i+1]);
            i++;
        }
        else if (!crStrcmp( argv[i], "-vncmode" ))
        {
            cr_server.vncMode = 1;
        }
        else if (!crStrcmp( argv[i], "-help" ))
        {
            crPrintHelp();
            exit(0);
        }
    }

    signal( SIGTERM, crServerCleanup );
    signal( SIGINT, crServerCleanup );
#ifndef WINDOWS
    signal( SIGPIPE, SIG_IGN );
#endif

#if DEBUG_FP_EXCEPTIONS
    {
        fpu_control_t mask;
        _FPU_GETCW(mask);
        mask &= ~(_FPU_MASK_IM | _FPU_MASK_DM | _FPU_MASK_ZM
                  | _FPU_MASK_OM | _FPU_MASK_UM);
        _FPU_SETCW(mask);
    }
#endif

    cr_server.firstCallCreateContext = GL_TRUE;
    cr_server.firstCallMakeCurrent = GL_TRUE;

    /*
     * Create default mural info and hash table.
     */
    cr_server.muralTable = crAllocHashtable();
    defaultMural = (CRMuralInfo *) crCalloc(sizeof(CRMuralInfo));
    crHashtableAdd(cr_server.muralTable, 0, defaultMural);

    cr_server.programTable = crAllocHashtable();

    crNetInit(crServerRecv, crServerClose);
    crStateInit();

    crServerGatherConfiguration(mothership);

    crStateLimitsInit( &(cr_server.limits) );

    /*
     * Default context
     */
    cr_server.contextTable = crAllocHashtable();
    cr_server.DummyContext = crStateCreateContext( &cr_server.limits,
                             CR_RGB_BIT | CR_DEPTH_BIT, NULL );
    cr_server.curClient->currentCtx = cr_server.DummyContext;

    crServerInitDispatch();
    crStateDiffAPI( &(cr_server.head_spu->dispatch_table) );

    crUnpackSetReturnPointer( &(cr_server.return_ptr) );
    crUnpackSetWritebackPointer( &(cr_server.writeback_ptr) );

    cr_server.barriers = crAllocHashtable();
    cr_server.semaphores = crAllocHashtable();
}
Beispiel #30
0
GLint crServerDispatchCreateContextEx(const char *dpyName, GLint visualBits, GLint shareCtx, GLint preloadCtxID, int32_t internalID)
{
    GLint retVal = -1;
    CRContext *newCtx;
    CRContextInfo *pContextInfo;
    GLboolean fFirst = GL_FALSE;

    if (shareCtx > 0) {
        crWarning("CRServer: context sharing not implemented.");
        shareCtx = 0;
    }

    pContextInfo = (CRContextInfo *) crAlloc(sizeof (CRContextInfo));
    if (!pContextInfo)
    {
        crWarning("failed to alloc context info!");
        return -1;
    }

    pContextInfo->CreateInfo.visualBits = visualBits;

    /* Since the Cr server serialized all incoming clients/contexts into
     * one outgoing GL stream, we only need to create one context for the
     * head SPU.  We'll only have to make it current once too, below.
     */
    if (cr_server.firstCallCreateContext) {
        cr_server.MainContextInfo.CreateInfo.visualBits = visualBits;
        cr_server.MainContextInfo.SpuContext = cr_server.head_spu->dispatch_table.
            CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.visualBits, shareCtx);
        if (cr_server.MainContextInfo.SpuContext < 0) {
            crWarning("crServerDispatchCreateContext() failed.");
            crFree(pContextInfo);
            return -1;
        }
        cr_server.firstCallCreateContext = GL_FALSE;
        fFirst = GL_TRUE;
    }
    else {
        /* second or third or ... context */
        if (!cr_server.bUseMultipleContexts && ((visualBits & cr_server.MainContextInfo.CreateInfo.visualBits) != visualBits)) {
            int oldSpuContext;

            /* the new context needs new visual attributes */
            cr_server.MainContextInfo.CreateInfo.visualBits |= visualBits;
            crDebug("crServerDispatchCreateContext requires new visual (0x%x).",
                    cr_server.MainContextInfo.CreateInfo.visualBits);

            /* Here, we used to just destroy the old rendering context.
             * Unfortunately, this had the side effect of destroying
             * all display lists and textures that had been loaded on
             * the old context as well.
             *
             * Now, first try to create a new context, with a suitable
             * visual, sharing display lists and textures with the
             * old context.  Then destroy the old context.
             */

            /* create new rendering context with suitable visual */
            oldSpuContext = cr_server.MainContextInfo.SpuContext;
            cr_server.MainContextInfo.SpuContext = cr_server.head_spu->dispatch_table.
                CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.visualBits, cr_server.MainContextInfo.SpuContext);
            /* destroy old rendering context */
            cr_server.head_spu->dispatch_table.DestroyContext(oldSpuContext);
            if (cr_server.MainContextInfo.SpuContext < 0) {
                crWarning("crServerDispatchCreateContext() failed.");
                crFree(pContextInfo);
                return -1;
            }
        }
    }

    if (cr_server.bUseMultipleContexts) {
        pContextInfo->SpuContext = cr_server.head_spu->dispatch_table.
                CreateContext(dpyName, cr_server.MainContextInfo.CreateInfo.visualBits, cr_server.MainContextInfo.SpuContext);
        if (pContextInfo->SpuContext < 0) {
            crWarning("crServerDispatchCreateContext() failed.");
            crStateEnableDiffOnMakeCurrent(GL_TRUE);
            cr_server.bUseMultipleContexts = GL_FALSE;
            if (!fFirst)
                crError("creating shared context failed, while it is expected to work!");
        }
        else if (fFirst)
        {
            crStateEnableDiffOnMakeCurrent(GL_FALSE);
        }
    }
    else
    {
        pContextInfo->SpuContext = -1;
    }

    /* Now create a new state-tracker context and initialize the
     * dispatch function pointers.
     */
    newCtx = crStateCreateContextEx(&cr_server.limits, visualBits, NULL, internalID);
    if (newCtx) {
        crStateSetCurrentPointers( newCtx, &(cr_server.current) );
        crStateResetCurrentPointers(&(cr_server.current));
        retVal = preloadCtxID<0 ? crServerGenerateID(&cr_server.idsPool.freeContextID) : preloadCtxID;

        pContextInfo->pContext = newCtx;
        pContextInfo->CreateInfo.visualBits = visualBits;
        pContextInfo->CreateInfo.externalID = retVal;
        pContextInfo->CreateInfo.pszDpyName = dpyName ? crStrdup(dpyName) : NULL;
        crHashtableAdd(cr_server.contextTable, retVal, pContextInfo);
    }

    if (retVal != -1 && !cr_server.bIsInLoadingState) {
        int pos;
        for (pos = 0; pos < CR_MAX_CONTEXTS; pos++) {
            if (cr_server.curClient->contextList[pos] == 0) {
                cr_server.curClient->contextList[pos] = retVal;
                break;
            }
        }
    }

    {
        /* As we're using only one host context to serve all client contexts, newly created context will still
         * hold last error value from any previous failed opengl call. Proper solution would be to redirect any
         * client glGetError calls to our state tracker, but right now it's missing quite a lot of checks and doesn't
         * reflect host driver/gpu specific issues. Thus we just reset last opengl error at context creation.
         */
        GLint err;

        err = cr_server.head_spu->dispatch_table.GetError();
        if (err!=GL_NO_ERROR)
        {
#ifdef DEBUG_misha
            crDebug("Cleared gl error %#x on context creation", err);
#else
            crWarning("Cleared gl error %#x on context creation", err);
#endif
        }
    }

    crServerReturnValue( &retVal, sizeof(retVal) );

    return retVal;
}