DECLEXPORT(void) STATE_APIENTRY crStateDetachShader(GLuint program, GLuint shader)
{
    CRGLSLProgram *pProgram = crStateGetProgramObj(program);
    CRGLSLShader *pShader;

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

    pShader = (CRGLSLShader *) crHashtableSearch(pProgram->currentState.attachedShaders, shader);
    if (!pShader)
    {
        crWarning("Shader %d isn't attached to program %d", shader, program);
        return;
    }

    crHashtableDelete(pProgram->currentState.attachedShaders, shader, NULL);

    CRASSERT(pShader->refCount>0);
    pShader->refCount--;

    if (0==pShader->refCount)
    {
        CRContext *g = GetCurrentContext();
        crHashtableDelete(g->glsl.shaders, shader, crStateFreeGLSLShader);
    }
}
Exemple #2
0
static void
RENDER_APIENTRY renderspuWindowDestroy( GLint win )
{
    WindowInfo *window;
    GET_CONTEXT(pOldCtx);

    CRASSERT(win >= 0);
    window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
    if (window) {
        crDebug("Render SPU: Destroy window (%d)", win);
        renderspu_SystemDestroyWindow( window );
        /* remove window info from hash table, and free it */
        crHashtableDelete(render_spu.windowTable, win, crFree);

        /* check if this window is bound to some ctx. Note: window pointer is already freed here */
        crHashtableWalk(render_spu.contextTable, renderspuCheckCurrentCtxWindowCB, window);

        /* restore current context */
        {
            GET_CONTEXT(pNewCtx);
            if (pNewCtx!=pOldCtx)
            {
                renderspuMakeCurrent(pOldCtx&&pOldCtx->currentWindow ? pOldCtx->currentWindow->id:0, 0,
                                     pOldCtx ? pOldCtx->id:0);
            }
        }
    }
    else {
        crDebug("Render SPU: Attempt to destroy invalid window (%d)", win);
    }
}
static void
stubDestroyContextLocked( ContextInfo *context )
{
    unsigned long contextId = context->id;
    if (context->type == NATIVE) {
#ifdef WINDOWS
        stub.wsInterface.wglDeleteContext( context->hglrc );
#elif defined(Darwin)
        stub.wsInterface.CGLDestroyContext( context->cglc );
#elif defined(GLX)
        stub.wsInterface.glXDestroyContext( context->dpy, context->glxContext );
#endif
    }
    else if (context->type == CHROMIUM) {
        /* Have pack SPU or tilesort SPU, etc. destroy the context */
        CRASSERT(context->spuContext >= 0);
        stub.spu->dispatch_table.DestroyContext( context->spuContext );
        crHashtableWalk(stub.windowTable, stubWindowCheckOwnerCB, context);
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
        if (context->spuConnection)
        {
            stub.spu->dispatch_table.VBoxConDestroy(context->spuConnection);
            context->spuConnection = 0;
        }
#endif
    }

#ifdef GLX
    crFreeHashtable(context->pGLXPixmapsHash, crFree);
#endif

    crHashtableDelete(stub.contextTable, contextId, NULL);
}
Exemple #4
0
void APIENTRY crWindowDestroy( GLint window )
{
    WindowInfo *winInfo = (WindowInfo *)
        crHashtableSearch(stub.windowTable, (unsigned int) window);
    if (winInfo && winInfo->type == CHROMIUM && stub.spu)
    {
        crHashtableLock(stub.windowTable);

        stub.spu->dispatch_table.WindowDestroy( winInfo->spuWindow );

#ifdef WINDOWS
        if (winInfo->hVisibleRegion != INVALID_HANDLE_VALUE)
        {
            DeleteObject(winInfo->hVisibleRegion);
        }
#elif defined(GLX)
        if (winInfo->pVisibleRegions)
        {
            XFree(winInfo->pVisibleRegions);
        }
# ifdef CR_NEWWINTRACK
        if (winInfo->syncDpy)
        {
            XCloseDisplay(winInfo->syncDpy);
        }
# endif
#endif
        crForcedFlush();
        crHashtableDelete(stub.windowTable, window, crFree);

        crHashtableUnlock(stub.windowTable);
    }
}
Exemple #5
0
void REPLICATESPU_APIENTRY
replicatespu_WindowDestroy(GLint win)
{
	WindowInfo *winInfo = (WindowInfo *) crHashtableSearch( replicate_spu.windowTable, win );
	GET_THREAD(thread);
	int i;

	replicatespuFlushAll( (void *) thread );

	if (winInfo) {
		for (i = 0; i < CR_MAX_REPLICANTS; i++) {
			if (!IS_CONNECTED(replicate_spu.rserver[i].conn))
				continue;

			if (replicate_spu.swap)
				crPackWindowDestroySWAP( winInfo->id[i] );
			else
				crPackWindowDestroy( winInfo->id[i] );

			winInfo->id[i] = -1; /* just to be safe */

			replicatespuFlushOne(thread, i);
		}
	}

	crHashtableDelete(replicate_spu.windowTable, win, crFree);
}
Exemple #6
0
void STATE_APIENTRY
crStateDeleteQueriesARB(GLsizei n, const GLuint *ids)
{
	CRContext *g = GetCurrentContext();
	CROcclusionState *o = &(g->occlusion);
	/*CRStateBits *sb = GetCurrentBits();*/
	/*CROcclusionBits *bb = &(sb->occlusion);*/
	int i;

	FLUSH();

	if (g->current.inBeginEnd) {
		crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
								 "glDeleteQueriesARB called in Begin/End");
		return;
	}

	if (n < 0) {
		crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
								 "glDeleteQueriesARB(n < 0)");
		return;
	}

	for (i = 0; i < n; i++) {
		if (ids[i]) {
			CROcclusionObject *q = (CROcclusionObject *)
				crHashtableSearch(o->objects, ids[i]);
			if (q) {
				crHashtableDelete(o->objects, ids[i], crFree);
			}
		}
	}
}
Exemple #7
0
void
stubDestroyContext( unsigned long contextId )
{
	ContextInfo *context;

	context = (ContextInfo *) crHashtableSearch(stub.contextTable, contextId);

	CRASSERT(context);

	if (context->type == NATIVE) {
#ifdef WINDOWS
		stub.wsInterface.wglDeleteContext( context->hglrc );
#elif defined(Darwin)
		stub.wsInterface.CGLDestroyContext( context->cglc );
#elif defined(GLX)
		stub.wsInterface.glXDestroyContext( context->dpy, context->glxContext );
#endif
	}
	else if (context->type == CHROMIUM) {
		/* Have pack SPU or tilesort SPU, etc. destroy the context */
		CRASSERT(context->spuContext >= 0);
		stub.spu->dispatch_table.DestroyContext( context->spuContext );
	}

	if (stub.currentContext == context) {
		stub.currentContext = NULL;
	}

	crMemZero(context, sizeof(ContextInfo));  /* just to be safe */
	crHashtableDelete(stub.contextTable, contextId, crFree);
}
Exemple #8
0
void crHashtableDeleteBlock( CRHashTable *h, unsigned long key, GLsizei range, CRHashtableCallback deleteFunc )
{
    /* XXX optimize someday */
    GLuint i;
    for (i = 0; i < (GLuint)range; i++) {
        crHashtableDelete( h, key, deleteFunc );
    }
}
Exemple #9
0
static void BINARYSWAPSPU_APIENTRY
binaryswapspuWindowDestroy(GLint win)
{
	WindowInfo *window;
	window = (WindowInfo *) crHashtableSearch(binaryswap_spu.windowTable, win);
	CRASSERT(window);
	binaryswap_spu.super.WindowDestroy(window->renderWindow);
	crHashtableDelete(binaryswap_spu.windowTable, win, crFree);
}
Exemple #10
0
static void BINARYSWAPSPU_APIENTRY
binaryswapspuDestroyContext(GLint ctx)
{
	ContextInfo *context;
	context =
		(ContextInfo *) crHashtableSearch(binaryswap_spu.contextTable, ctx);
	CRASSERT(context);
	binaryswap_spu.super.DestroyContext(context->renderContext);
	crHashtableDelete(binaryswap_spu.contextTable, ctx, crFree);
}
Exemple #11
0
void REPLICATESPU_APIENTRY
replicatespu_DestroyContext( GLint ctx )
{
	unsigned int i;
	ContextInfo *context = (ContextInfo *) crHashtableSearch(replicate_spu.contextTable, ctx);
	GET_THREAD(thread);

	if (!context) {
		crWarning("Replicate SPU: DestroyContext, bad context %d", ctx);
		return;
	}
	CRASSERT(thread);

	replicatespuFlushAll( (void *)thread );

	for (i = 0; i < CR_MAX_REPLICANTS; i++) {
		if (!IS_CONNECTED(replicate_spu.rserver[i].conn))
			continue;

		if (replicate_spu.swap)
			crPackDestroyContextSWAP( context->rserverCtx[i] );
		else
			crPackDestroyContext( context->rserverCtx[i] );

		replicatespuFlushOne(thread, i);
	}

	crStateDestroyContext( context->State );

	/* Although we only allocate a display list manager once,
	 * we free it every time; this is okay since the DLM itself
	 * will track its uses and will only release the resources
	 * when the last user has relinquished it.
	 */
	crDLMFreeDLM(context->displayListManager);
	crDLMFreeContext(context->dlmState);

	if (thread->currentContext == context) {
		thread->currentContext = NULL;
		crStateMakeCurrent( NULL );
		crDLMSetCurrentState(NULL);
	}

	/* zero, just to be safe */
	crMemZero(context, sizeof(ContextInfo));

	/* Delete from both the context table, and the context list. */
	crHashtableDelete(replicate_spu.contextTable, ctx, crFree);
	{
	    CRListIterator *foundElement = crListFind(replicate_spu.contextList, (void *)ctx, CompareIntegers);
	    if (foundElement != NULL) {
		crListErase(replicate_spu.contextList, foundElement);
	    }
	}
}
Exemple #12
0
void PACKSPU_APIENTRY packspu_WindowDestroy( GLint window )
{
	if (pack_spu.swap)
	{
		crPackWindowDestroySWAP(window);
	}
	else
	{
		crPackWindowDestroy(window);
	}
	crHashtableDelete(pack_spu.XWindows,window,crFree);
}
DECLEXPORT(void) STATE_APIENTRY crStateDeleteShader(GLuint shader)
{
    CRGLSLShader *pShader = crStateGetShaderObj(shader);
    if (!pShader)
    {
        crWarning("Unknown shader %d", shader);
        return;
    }

    pShader->deleted = GL_TRUE;

    if (0==pShader->refCount)
    {
        CRContext *g = GetCurrentContext();
        crHashtableDelete(g->glsl.shaders, shader, crStateFreeGLSLShader);
        /* since we use programs table for key allocation key allocation, we need to
         * free the key in the programs table.
         * See comment in crStateCreateShader */
        crHashtableDelete(g->glsl.programs, shader, crStateDbgCheckNoProgramOfId);
    }
}
static void crStateShaderDecRefCount(void *data)
{
    CRGLSLShader *pShader = (CRGLSLShader *) data;

    CRASSERT(pShader->refCount>0);

    pShader->refCount--;

    if (0==pShader->refCount && pShader->deleted)
    {
        CRContext *g = GetCurrentContext();
        crHashtableDelete(g->glsl.shaders, pShader->id, crStateFreeGLSLShader);
    }
}
void STATE_APIENTRY
crStateDeleteBuffersARB(GLsizei n, const GLuint *buffers)
{
    CRContext *g = GetCurrentContext();
    int i;

    FLUSH();

    if (g->current.inBeginEnd) {
        crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
                                 "glDeleteBuffersARB called in Begin/End");
        return;
    }

    if (n < 0) {
        crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
                                 "glDeleteBuffersARB(n < 0)");
        return;
    }

    for (i = 0; i < n; i++) {
        if (buffers[i]) {
            CRBufferObject *obj = (CRBufferObject *)
                crHashtableSearch(g->shared->buffersTable, buffers[i]);
            if (obj) {
                int j;

                ctStateBuffersRefsCleanup(g, obj, g->neg_bitid);

                CR_STATE_SHAREDOBJ_USAGE_FOREACH_USED_IDX(obj, j)
                {
                    /* saved state version <= SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS does not have usage bits info,
                     * so on restore, we set mark bits as used.
                     * This is why g_pAvailableContexts[j] could be NULL
                     * also g_pAvailableContexts[0] will hold default context, which we should discard */
                    CRContext *ctx = g_pAvailableContexts[j];
                    if (j && ctx)
                    {
                        ctStateBuffersRefsCleanup(ctx, obj, g->neg_bitid); /* <- yes, use g->neg_bitid, i.e. neg_bitid of the current context to ensure others bits get dirtified,
                                                                            * but not the current context ones*/
                    }
                    else
                        CR_STATE_SHAREDOBJ_USAGE_CLEAR_IDX(obj, j);
                }

                crHashtableDelete(g->shared->buffersTable, buffers[i], crStateFreeBufferObject);
            }
        }
    }
Exemple #16
0
static void
RENDER_APIENTRY renderspuWindowDestroy( GLint win )
{
	WindowInfo *window;
	CRASSERT(win >= 0);
	window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
	if (window) {
		renderspu_SystemDestroyWindow( window );
		/* remove window info from hash table, and free it */
		crHashtableDelete(render_spu.windowTable, win, crFree);
	}
	else {
		crDebug("Render SPU: Attempt to destroy invalid window (%d)", win);
	}
}
Exemple #17
0
void CrDemEntryDestroy(PCR_DISPLAY_ENTRY_MAP pMap, GLuint idTexture)
{
#ifdef DEBUG
    {
        PCR_DISPLAY_ENTRY pEntry = (PCR_DISPLAY_ENTRY)crHashtableSearch(pMap->pTextureMap, idTexture);
        if (!pEntry)
        {
            crWarning("request to delete inexistent entry");
            return;
        }

        Assert(!CrDpEntryIsUsed(pEntry));
    }
#endif
    crHashtableDelete(pMap->pTextureMap, idTexture, crFree);
}
Exemple #18
0
static void RENDER_APIENTRY
renderspuDestroyContext( GLint ctx )
{
	ContextInfo *context;

	CRASSERT(ctx);

	context = (ContextInfo *) crHashtableSearch(render_spu.contextTable, ctx);
	CRASSERT(context);
	renderspu_SystemDestroyContext( context );
	if (context->extensionString) {
		crFree(context->extensionString);
		context->extensionString = NULL;
	}
	crHashtableDelete(render_spu.contextTable, ctx, crFree);
}
DECLEXPORT(void) STATE_APIENTRY crStateDeleteShader(GLuint shader)
{
    CRGLSLShader *pShader = crStateGetShaderObj(shader);
    if (!pShader)
    {
        crWarning("Unknown shader %d", shader);
        return;
    }

    pShader->deleted = GL_TRUE;

    if (0==pShader->refCount)
    {
        CRContext *g = GetCurrentContext();
        crHashtableDelete(g->glsl.shaders, shader, crStateFreeGLSLShader);
    }
}
DECLEXPORT(void) STATE_APIENTRY
crStateDeleteRenderbuffersEXT(GLsizei n, const GLuint *renderbuffers)
{
    CRContext *g = GetCurrentContext();
    CRFramebufferObjectState *fbo = &g->framebufferobject;
    int i;

    CRSTATE_CHECKERR(g->current.inBeginEnd, GL_INVALID_OPERATION, "called in begin/end");
    CRSTATE_CHECKERR(n<0, GL_INVALID_OPERATION, "n<0");

    for (i = 0; i < n; i++)
    {
        if (renderbuffers[i])
        {
            CRRenderbufferObject *rbo;
            rbo = (CRRenderbufferObject*) crHashtableSearch(g->shared->rbTable, renderbuffers[i]);
            if (rbo)
            {
                int j;

                ctStateRenderbufferRefsCleanup(g, renderbuffers[i], rbo);
                CR_STATE_SHAREDOBJ_USAGE_FOREACH_USED_IDX(rbo, j)
                {
                    /* saved state version <= SHCROGL_SSM_VERSION_BEFORE_CTXUSAGE_BITS does not have usage bits info,
                     * so on restore, we set mark bits as used.
                     * This is why g_pAvailableContexts[j] could be NULL
                     * also g_pAvailableContexts[0] will hold default context, which we should discard */
                    CRContext *ctx = g_pAvailableContexts[j];
                    if (j && ctx)
                    {
                        CRFramebufferObjectState *ctxFbo;
                        CRASSERT(ctx);
                        ctxFbo = &ctx->framebufferobject;
                        if (ctxFbo->renderbuffer==rbo)
                            crWarning("deleting RBO being used by another context %d", ctx->id);

                        ctStateRenderbufferRefsCleanup(ctx, renderbuffers[i], rbo);
                    }
                    else
                        CR_STATE_SHAREDOBJ_USAGE_CLEAR_IDX(rbo, j);
                }
                crHashtableDelete(g->shared->rbTable, renderbuffers[i], crStateFreeRBO);
            }
        }
    }
DECLEXPORT(void) STATE_APIENTRY crStateDeleteProgram(GLuint program)
{
    CRContext *g = GetCurrentContext();
    CRGLSLProgram *pProgram = crStateGetProgramObj(program);

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

    if (g->glsl.activeProgram == pProgram)
    {
        g->glsl.activeProgram = NULL;
    }

    crHashtableDelete(g->glsl.programs, program, crStateFreeGLSLProgram);
}
void DLM_APIENTRY crDLMDeleteLists(GLuint firstListIdentifier, GLsizei range)
{
	CRDLMContextState *listState = CURRENT_STATE();
	register int i;

	if (listState == NULL)
	{
		crWarning
			("DLM error: DeleteLists(%d,%d) called with no current state (%s line %d)\n",
			 (int) firstListIdentifier, (int) range, __FILE__, __LINE__);
		return;
	}
	if (range < 0)
	{
		char msg[1000];
		sprintf(msg, "DeleteLists called with range (%d) less than zero", (int) range);
		crdlm_error(__LINE__, __FILE__, GL_INVALID_VALUE, msg);								 
		return;
	}

	/* Interestingly, there doesn't seem to be an error for deleting
	 * display list 0, which cannot exist.
	 *
	 * We could delete the desired lists by walking the entire hash of
	 * display lists and looking for and deleting any in our range; or we
	 * could delete lists one by one.  The former is faster if the hashing
	 * algorithm is inefficient or if we're deleting all or most of our
	 * lists; the latter is faster if we're deleting a relatively small
	 * number of lists.
	 *
	 * For now, we'll go with the latter; it's also easier to implement
	 * given the current functions available.
	 */
	DLM_LOCK(listState->dlm)
	for (i = 0; i < range; i++)
	{
		crHashtableDelete(listState->dlm->displayLists, 
				  firstListIdentifier + i, crdlm_free_list);
	}
	DLM_UNLOCK(listState->dlm)
}
Exemple #23
0
static void MATTESPU_APIENTRY matteDestroyContext(GLint ctx)
{
    ContextInfo *contextInfo;
    GET_CONTEXT_INFO(currentContextInfo);

    /* If we're destroying the current context, the current
     * context goes to NULL.
     */
    contextInfo = crHashtableSearch(matte_spu.contextTable, ctx);
    if (contextInfo == currentContextInfo) {
	SET_CONTEXT_INFO(NULL);
    }

    /* Destroy the context info record */
    if (contextInfo != NULL) {
	crHashtableDelete(matte_spu.contextTable, ctx, matteFreeContextInfo);
    }

    /* Pass it along */
    matte_spu.super.DestroyContext(ctx);
}
Exemple #24
0
static void RENDER_APIENTRY
renderspuDestroyContext( GLint ctx )
{
    ContextInfo *context, *curCtx;

    CRASSERT(ctx);

    if (ctx == CR_RENDER_DEFAULT_CONTEXT_ID)
    {
        crWarning("request to destroy a default context, ignoring");
        return;
    }

    context = (ContextInfo *) crHashtableSearch(render_spu.contextTable, ctx);
    CRASSERT(context);
    {
        if (!context)
        {
            crWarning("request to delete inexistent context");
            return;
        }
    }

    curCtx = GET_CONTEXT_VAL();
    CRASSERT(curCtx);
    if (curCtx == context)
    {
        renderspuMakeCurrent( CR_RENDER_DEFAULT_WINDOW_ID, 0, CR_RENDER_DEFAULT_CONTEXT_ID );
        curCtx = GET_CONTEXT_VAL();
		Assert(curCtx);
		Assert(curCtx != context);
    }

    crHashtableDelete(render_spu.contextTable, ctx, NULL);

    renderspuContextMarkDeletedAndRelease(context);
}
void stubDestroyWindow( GLint con, GLint window )
{
    WindowInfo *winInfo = (WindowInfo *)
        crHashtableSearch(stub.windowTable, (unsigned int) window);
    if (winInfo && winInfo->type == CHROMIUM && stub.spu)
    {
        crHashtableLock(stub.windowTable);

        stub.spu->dispatch_table.VBoxWindowDestroy(con, winInfo->spuWindow );

#ifdef WINDOWS
        if (winInfo->hVisibleRegion != INVALID_HANDLE_VALUE)
        {
            DeleteObject(winInfo->hVisibleRegion);
        }
#elif defined(GLX)
        if (winInfo->pVisibleRegions)
        {
            XFree(winInfo->pVisibleRegions);
        }
# ifdef CR_NEWWINTRACK
        if (winInfo->syncDpy)
        {
            XCloseDisplay(winInfo->syncDpy);
        }
# endif
#endif

        stubForcedFlush(con);

        crHashtableWalk(stub.contextTable, stubWindowCleanupForContextsCB, winInfo);

        crHashtableDelete(stub.windowTable, window, crFree);

        crHashtableUnlock(stub.windowTable);
    }
}
Exemple #26
0
void
RENDER_APIENTRY renderspuWindowDestroy( GLint win )
{
    WindowInfo *window;

    CRASSERT(win >= 0);
    if (win == CR_RENDER_DEFAULT_WINDOW_ID)
    {
        crWarning("request to destroy a default mural, ignoring");
        return;
    }
    window = (WindowInfo *) crHashtableSearch(render_spu.windowTable, win);
    if (window) {
        crDebug("Render SPU: Destroy window (%d)", win);
        renderspuWindowTerm( window );

        /* remove window info from hash table, and free it */
        crHashtableDelete(render_spu.windowTable, win, crFree);

    }
    else {
        crDebug("Render SPU: Attempt to destroy invalid window (%d)", win);
    }
}
void STATE_APIENTRY
crStateDeleteBuffersARB(GLsizei n, const GLuint *buffers)
{
    CRContext *g = GetCurrentContext();
    CRBufferObjectState *b = &(g->bufferobject);
    CRStateBits *sb = GetCurrentBits();
    CRBufferObjectBits *bb = &(sb->bufferobject);
    int i;

    FLUSH();

    if (g->current.inBeginEnd) {
        crStateError(__LINE__, __FILE__, GL_INVALID_OPERATION,
                                 "glDeleteBuffersARB called in Begin/End");
        return;
    }

    if (n < 0) {
        crStateError(__LINE__, __FILE__, GL_INVALID_VALUE,
                                 "glDeleteBuffersARB(n < 0)");
        return;
    }

    for (i = 0; i < n; i++) {
        if (buffers[i]) {
            CRBufferObject *obj = (CRBufferObject *)
                crHashtableSearch(g->shared->buffersTable, buffers[i]);
            if (obj) {
                if (obj == b->arrayBuffer) 
                {
                    b->arrayBuffer = b->nullBuffer;
                    b->arrayBuffer->refCount++;
                    DIRTY(bb->dirty, g->neg_bitid);
                    DIRTY(bb->arrayBinding, g->neg_bitid);
                } 
                else if (obj == b->elementsBuffer) 
                {
                    b->elementsBuffer = b->nullBuffer;
                    b->elementsBuffer->refCount++;
                    DIRTY(bb->dirty, g->neg_bitid);
                    DIRTY(bb->elementsBinding, g->neg_bitid);
                }
#ifdef CR_ARB_pixel_buffer_object
                else if (obj == b->packBuffer) 
                {
                    b->packBuffer = b->nullBuffer;
                    b->packBuffer->refCount++;
                    DIRTY(bb->dirty, g->neg_bitid);
                    DIRTY(bb->packBinding, g->neg_bitid);
                }
                else if (obj == b->unpackBuffer) 
                {
                    b->unpackBuffer = b->nullBuffer;
                    b->unpackBuffer->refCount++;
                    DIRTY(bb->dirty, g->neg_bitid);
                    DIRTY(bb->unpackBinding, g->neg_bitid);
                }
#endif
                /* @todo check bindings with the vertex arrays */

                crHashtableDelete(g->shared->buffersTable, buffers[i], crStateFreeBufferObject);
            }
        }
    }
}
void STATE_APIENTRY
crStateBindBufferARB (GLenum target, GLuint buffer)
{
    CRContext *g = GetCurrentContext();
    CRBufferObjectState *b = &(g->bufferobject);
    CRStateBits *sb = GetCurrentBits();
    CRBufferObjectBits *bb = &(sb->bufferobject);
    CRBufferObject *oldObj, *newObj;

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

    FLUSH();

    oldObj = crStateGetBoundBufferObject(target, b);
    if (!oldObj)
    {
        crStateError(__LINE__, __FILE__, GL_INVALID_ENUM, "glBindBufferARB(target)");
        return;
    }

    if (buffer == 0) {
        newObj = b->nullBuffer;
    }
    else {
        newObj = (CRBufferObject *) crHashtableSearch(g->shared->buffersTable, buffer);
        if (!newObj) {
            CRSTATE_CHECKERR(!crHashtableIsKeyUsed(g->shared->buffersTable, buffer), GL_INVALID_OPERATION, "name is not a buffer object");
            newObj = AllocBufferObject(buffer);
            CRSTATE_CHECKERR(!newObj, GL_OUT_OF_MEMORY, "glBindBuffer");
#ifndef IN_GUEST
            diff_api.GenBuffersARB(1, &newObj->hwid);
            if (!newObj->hwid)
            {
                crWarning("GenBuffersARB failed!");
                crFree(newObj);
                return;
            }
#endif
            crHashtableAdd( g->shared->buffersTable, buffer, newObj );
        }

        CR_STATE_SHAREDOBJ_USAGE_SET(newObj, g);
    }

    newObj->refCount++;
    oldObj->refCount--;

    switch (target)
    {
        case GL_ARRAY_BUFFER_ARB:
            b->arrayBuffer = newObj;
            DIRTY(bb->dirty, g->neg_bitid);
            DIRTY(bb->arrayBinding, g->neg_bitid);
            break;
        case GL_ELEMENT_ARRAY_BUFFER_ARB:
            b->elementsBuffer = newObj;
            DIRTY(bb->dirty, g->neg_bitid);
            DIRTY(bb->elementsBinding, g->neg_bitid);
            break;
#ifdef CR_ARB_pixel_buffer_object
        case GL_PIXEL_PACK_BUFFER_ARB:
            b->packBuffer = newObj;
            DIRTY(bb->dirty, g->neg_bitid);
            DIRTY(bb->packBinding, g->neg_bitid);
            break;
        case GL_PIXEL_UNPACK_BUFFER_ARB:
            b->unpackBuffer = newObj;
            DIRTY(bb->dirty, g->neg_bitid);
            DIRTY(bb->unpackBinding, g->neg_bitid);
            break;
#endif
        default: /*can't get here*/
            CRASSERT(false);
            return;
    }

    if (oldObj->refCount <= 0) {
        /*we shouldn't reach this point*/
        CRASSERT(false);
        crHashtableDelete(g->shared->buffersTable, (unsigned long) oldObj->id, crStateFreeBufferObject);
    }

#ifdef IN_GUEST
    if (target == GL_PIXEL_PACK_BUFFER_ARB)
    {
        newObj->bResyncOnRead = GL_TRUE;
    }
#endif
}
void SERVER_DISPATCH_APIENTRY
crServerDispatchDestroyContext( GLint ctx )
{
    CRContextInfo *crCtxInfo;
    CRContext *crCtx;
    int32_t client;
    CRClientNode *pNode;
    int found=false;

    crCtxInfo = (CRContextInfo *) crHashtableSearch(cr_server.contextTable, ctx);
    if (!crCtxInfo) {
        crWarning("CRServer: DestroyContext invalid context %d", ctx);
        return;
    }
    crCtx = crCtxInfo->pContext;
    CRASSERT(crCtx);

    crDebug("CRServer: DestroyContext context %d", ctx);

    crHashtableDelete(cr_server.contextTable, ctx, NULL);
    crStateDestroyContext( crCtx );

    if (crCtxInfo->CreateInfo.pszDpyName)
        crFree(crCtxInfo->CreateInfo.pszDpyName);

    if (crCtxInfo->SpuContext >= 0)
        cr_server.head_spu->dispatch_table.DestroyContext(crCtxInfo->SpuContext);

    crFree(crCtxInfo);

    if (cr_server.curClient)
    {
        /* If we delete our current context, default back to the null context */
        if (cr_server.curClient->currentCtxInfo == crCtxInfo) {
            cr_server.curClient->currentContextNumber = -1;
            cr_server.curClient->currentCtxInfo = &cr_server.MainContextInfo;
        }

        found = crServerRemoveClientContext(cr_server.curClient, ctx);

        /*Some application call destroy context not in a thread where it was created...have do deal with it.*/
        if (!found)
        {
            for (client=0; client<cr_server.numClients; ++client)
            {
                if (cr_server.clients[client]==cr_server.curClient)
                    continue;

                found = crServerRemoveClientContext(cr_server.clients[client], ctx);

                if (found) break;
            }
        }

        if (!found)
        {
            pNode=cr_server.pCleanupClient;

            while (pNode && !found)
            {
                found = crServerRemoveClientContext(pNode->pClient, ctx);
                pNode = pNode->next;
            }
        }

        CRASSERT(found);
    }

    /*Make sure this context isn't active in other clients*/
    for (client=0; client<cr_server.numClients; ++client)
    {
        if (cr_server.clients[client]->currentCtxInfo == crCtxInfo)
        {
            cr_server.clients[client]->currentContextNumber = -1;
            cr_server.clients[client]->currentCtxInfo = &cr_server.MainContextInfo;
        }
    }

    pNode=cr_server.pCleanupClient;
    while (pNode)
    {
        if (pNode->pClient->currentCtxInfo == crCtxInfo)
        {
            pNode->pClient->currentContextNumber = -1;
            pNode->pClient->currentCtxInfo = &cr_server.MainContextInfo;
        }
        pNode = pNode->next;
    }
}