summaryrefslogtreecommitdiffstats
path: root/src/VBox/GuestHost/OpenGL/state_tracker/state_init.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/VBox/GuestHost/OpenGL/state_tracker/state_init.c')
-rw-r--r--src/VBox/GuestHost/OpenGL/state_tracker/state_init.c892
1 files changed, 892 insertions, 0 deletions
diff --git a/src/VBox/GuestHost/OpenGL/state_tracker/state_init.c b/src/VBox/GuestHost/OpenGL/state_tracker/state_init.c
new file mode 100644
index 00000000..61e73a1b
--- /dev/null
+++ b/src/VBox/GuestHost/OpenGL/state_tracker/state_init.c
@@ -0,0 +1,892 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include "state.h"
+#include "cr_mem.h"
+#include "cr_error.h"
+#include "cr_spu.h"
+
+#include <iprt/asm.h>
+
+#ifdef CHROMIUM_THREADSAFE
+static bool __isContextTLSInited = false;
+CRtsd __contextTSD;
+#else
+CRContext *__currentContext = NULL;
+#endif
+
+CRStateBits *__currentBits = NULL;
+CRContext *g_pAvailableContexts[CR_MAX_CONTEXTS];
+uint32_t g_cContexts = 0;
+
+static CRSharedState *gSharedState=NULL;
+
+static CRContext *defaultContext = NULL;
+
+GLboolean g_bVBoxEnableDiffOnMakeCurrent = GL_TRUE;
+
+
+/**
+ * Allocate a new shared state object.
+ * Contains texture objects, display lists, etc.
+ */
+static CRSharedState *
+crStateAllocShared(void)
+{
+ CRSharedState *s = (CRSharedState *) crCalloc(sizeof(CRSharedState));
+ if (s) {
+ s->textureTable = crAllocHashtable();
+ s->dlistTable = crAllocHashtable();
+ s->buffersTable = crAllocHashtable();
+ s->fbTable = crAllocHashtable();
+ s->rbTable = crAllocHashtable();
+ s->refCount = 1; /* refcount is number of contexts using this state */
+ s->saveCount = 0;
+ }
+ return s;
+}
+
+/**
+ * Callback used for crFreeHashtable().
+ */
+DECLEXPORT(void)
+crStateDeleteTextureCallback(void *texObj)
+{
+#ifndef IN_GUEST
+ diff_api.DeleteTextures(1, &((CRTextureObj *)texObj)->hwid);
+#endif
+ crStateDeleteTextureObject((CRTextureObj *) texObj);
+}
+
+typedef struct CR_STATE_RELEASEOBJ
+{
+ CRContext *pCtx;
+ CRSharedState *s;
+} CR_STATE_RELEASEOBJ, *PCR_STATE_RELEASEOBJ;
+
+void crStateOnTextureUsageRelease(CRSharedState *pS, CRTextureObj *pObj)
+{
+ if (!pObj->pinned)
+ crHashtableDelete(pS->textureTable, pObj->id, crStateDeleteTextureCallback);
+ else
+ Assert(crHashtableSearch(pS->textureTable, pObj->id));
+}
+
+static void crStateReleaseTextureInternal(CRSharedState *pS, CRContext *pCtx, CRTextureObj *pObj)
+{
+ Assert(CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj) || pObj->pinned);
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR(pObj, pCtx);
+ if (CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj))
+ return;
+
+ crStateOnTextureUsageRelease(pS, pObj);
+}
+
+DECLEXPORT(void) crStateReleaseTexture(CRContext *pCtx, CRTextureObj *pObj)
+{
+ Assert(CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj));
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR(pObj, pCtx);
+ if (CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj))
+ return;
+
+ if (!gSharedState)
+ {
+ WARN(("no global shared"));
+ return;
+ }
+
+ crStateOnTextureUsageRelease(gSharedState, pObj);
+}
+
+static void crStateReleaseBufferObjectInternal(CRSharedState *pS, CRContext *pCtx, CRBufferObject *pObj)
+{
+ Assert(CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj));
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR(pObj, pCtx);
+ if (!CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj))
+ crHashtableDelete(pS->buffersTable, pObj->id, crStateFreeBufferObject);
+}
+
+static void crStateReleaseFBOInternal(CRSharedState *pS, CRContext *pCtx, CRFramebufferObject *pObj)
+{
+ Assert(CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj));
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR(pObj, pCtx);
+ if (!CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj))
+ crHashtableDelete(pS->fbTable, pObj->id, crStateFreeFBO);
+}
+
+static void crStateReleaseRBOInternal(CRSharedState *pS, CRContext *pCtx, CRRenderbufferObject *pObj)
+{
+ Assert(CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj));
+ CR_STATE_SHAREDOBJ_USAGE_CLEAR(pObj, pCtx);
+ if (!CR_STATE_SHAREDOBJ_USAGE_IS_USED(pObj))
+ crHashtableDelete(pS->rbTable, pObj->id, crStateFreeRBO);
+}
+
+static void ReleaseTextureCallback(unsigned long key, void *data1, void *data2)
+{
+ PCR_STATE_RELEASEOBJ pData = (PCR_STATE_RELEASEOBJ)data2;
+ CRTextureObj *pObj = (CRTextureObj *)data1;
+ (void)key;
+ crStateReleaseTextureInternal(pData->s, pData->pCtx, pObj);
+}
+
+static void ReleaseBufferObjectCallback(unsigned long key, void *data1, void *data2)
+{
+ PCR_STATE_RELEASEOBJ pData = (PCR_STATE_RELEASEOBJ)data2;
+ CRBufferObject *pObj = (CRBufferObject *)data1;
+ (void)key;
+ crStateReleaseBufferObjectInternal(pData->s, pData->pCtx, pObj);
+}
+
+static void ReleaseFBOCallback(unsigned long key, void *data1, void *data2)
+{
+ PCR_STATE_RELEASEOBJ pData = (PCR_STATE_RELEASEOBJ)data2;
+ CRFramebufferObject *pObj = (CRFramebufferObject *)data1;
+ (void)key;
+ crStateReleaseFBOInternal(pData->s, pData->pCtx, pObj);
+}
+
+static void ReleaseRBOCallback(unsigned long key, void *data1, void *data2)
+{
+ PCR_STATE_RELEASEOBJ pData = (PCR_STATE_RELEASEOBJ)data2;
+ CRRenderbufferObject *pObj = (CRRenderbufferObject *)data1;
+ (void)key;
+ crStateReleaseRBOInternal(pData->s, pData->pCtx, pObj);
+}
+
+
+/**
+ * Decrement shared state's refcount and delete when it hits zero.
+ */
+#ifndef IN_GUEST
+DECLEXPORT(void) crStateFreeShared(CRContext *pContext, CRSharedState *s)
+#else
+static void crStateFreeShared(CRContext *pContext, CRSharedState *s)
+#endif
+{
+ int32_t refCount = ASMAtomicDecS32(&s->refCount);
+
+ Assert(refCount >= 0);
+ if (refCount <= 0) {
+ if (s==gSharedState)
+ {
+ gSharedState = NULL;
+ }
+ crFreeHashtable(s->textureTable, crStateDeleteTextureCallback);
+ crFreeHashtable(s->dlistTable, crFree); /* call crFree for each entry */
+ crFreeHashtable(s->buffersTable, crStateFreeBufferObject);
+ crFreeHashtable(s->fbTable, crStateFreeFBO);
+ crFreeHashtable(s->rbTable, crStateFreeRBO);
+ crFree(s);
+ }
+ else if (pContext)
+ {
+ /* evaluate usage bits*/
+ CR_STATE_RELEASEOBJ CbData;
+ CbData.pCtx = pContext;
+ CbData.s = s;
+ crHashtableWalk(s->textureTable, ReleaseTextureCallback, &CbData);
+ crHashtableWalk(s->buffersTable, ReleaseBufferObjectCallback , &CbData);
+ crHashtableWalk(s->fbTable, ReleaseFBOCallback, &CbData);
+ crHashtableWalk(s->rbTable, ReleaseRBOCallback, &CbData);
+ }
+}
+
+#ifndef IN_GUEST
+
+DECLEXPORT(CRSharedState *) crStateGlobalSharedAcquire(void)
+{
+ if (!gSharedState)
+ {
+ crWarning("No Global Shared State!");
+ return NULL;
+ }
+ ASMAtomicIncS32(&gSharedState->refCount);
+ return gSharedState;
+}
+
+DECLEXPORT(void) crStateGlobalSharedRelease(void)
+{
+ crStateFreeShared(NULL, gSharedState);
+}
+
+#endif /* IN_GUEST */
+
+DECLEXPORT(void) STATE_APIENTRY
+crStateShareContext(GLboolean value)
+{
+ CRContext *pCtx = GetCurrentContext();
+ CRASSERT(pCtx && pCtx->shared);
+
+ if (value)
+ {
+ if (pCtx->shared == gSharedState)
+ {
+ return;
+ }
+
+ crDebug("Context(%i) shared", pCtx->id);
+
+ if (!gSharedState)
+ {
+ gSharedState = pCtx->shared;
+ }
+ else
+ {
+ crStateFreeShared(pCtx, pCtx->shared);
+ pCtx->shared = gSharedState;
+ ASMAtomicIncS32(&gSharedState->refCount);
+ }
+ }
+ else
+ {
+ if (pCtx->shared != gSharedState)
+ {
+ return;
+ }
+
+ crDebug("Context(%i) unshared", pCtx->id);
+
+ if (gSharedState->refCount==1)
+ {
+ gSharedState = NULL;
+ }
+ else
+ {
+ pCtx->shared = crStateAllocShared();
+ pCtx->shared->id = pCtx->id;
+ crStateFreeShared(pCtx, gSharedState);
+ }
+ }
+}
+
+DECLEXPORT(void) STATE_APIENTRY
+crStateShareLists(CRContext *pContext1, CRContext *pContext2)
+{
+ CRASSERT(pContext1->shared);
+ CRASSERT(pContext2->shared);
+
+ if (pContext2->shared == pContext1->shared)
+ {
+ return;
+ }
+
+ crStateFreeShared(pContext1, pContext1->shared);
+ pContext1->shared = pContext2->shared;
+ ASMAtomicIncS32(&pContext2->shared->refCount);
+}
+
+DECLEXPORT(GLboolean) STATE_APIENTRY
+crStateContextIsShared(CRContext *pCtx)
+{
+ return pCtx->shared==gSharedState;
+}
+
+DECLEXPORT(void) STATE_APIENTRY
+crStateSetSharedContext(CRContext *pCtx)
+{
+ if (gSharedState)
+ {
+ crWarning("crStateSetSharedContext: shared is being changed from %p to %p", gSharedState, pCtx->shared);
+ }
+
+ gSharedState = pCtx->shared;
+}
+
+#ifdef CHROMIUM_THREADSAFE
+static void
+crStateFreeContext(CRContext *ctx);
+static DECLCALLBACK(void) crStateContextDtor(void *pvCtx)
+{
+ crStateFreeContext((CRContext*)pvCtx);
+}
+#endif
+
+/*
+ * Helper for crStateCreateContext, below.
+ */
+static CRContext *
+crStateCreateContextId(int i, const CRLimitsState *limits, GLint visBits, CRContext *shareCtx)
+{
+ CRContext *ctx;
+ int j;
+ int node32 = i >> 5;
+ int node = i & 0x1f;
+ (void)limits;
+
+ if (g_pAvailableContexts[i] != NULL)
+ {
+ crWarning("trying to create context with used id");
+ return NULL;
+ }
+
+ ctx = (CRContext *) crCalloc( sizeof( *ctx ) );
+ if (!ctx)
+ {
+ crWarning("failed to allocate context");
+ return NULL;
+ }
+ g_pAvailableContexts[i] = ctx;
+ ++g_cContexts;
+ CRASSERT(g_cContexts < RT_ELEMENTS(g_pAvailableContexts));
+ ctx->id = i;
+#ifdef CHROMIUM_THREADSAFE
+ VBoxTlsRefInit(ctx, crStateContextDtor);
+#endif
+ ctx->flush_func = NULL;
+ for (j=0;j<CR_MAX_BITARRAY;j++){
+ if (j == node32) {
+ ctx->bitid[j] = (1 << node);
+ } else {
+ ctx->bitid[j] = 0;
+ }
+ ctx->neg_bitid[j] = ~(ctx->bitid[j]);
+ }
+
+ if (shareCtx) {
+ CRASSERT(shareCtx->shared);
+ ctx->shared = shareCtx->shared;
+ ASMAtomicIncS32(&ctx->shared->refCount);
+ }
+ else {
+ ctx->shared = crStateAllocShared();
+ ctx->shared->id = ctx->id;
+ }
+
+ /* use Chromium's OpenGL defaults */
+ crStateLimitsInit( &(ctx->limits) );
+ crStateExtensionsInit( &(ctx->limits), &(ctx->extensions) );
+
+ crStateBufferObjectInit( ctx ); /* must precede client state init! */
+ crStateClientInit( ctx );
+
+ crStateBufferInit( ctx );
+ crStateCurrentInit( ctx );
+ crStateEvaluatorInit( ctx );
+ crStateFogInit( ctx );
+ crStateHintInit( ctx );
+ crStateLightingInit( ctx );
+ crStateLineInit( ctx );
+ crStateListsInit( ctx );
+ crStateMultisampleInit( ctx );
+ crStateOcclusionInit( ctx );
+ crStatePixelInit( ctx );
+ crStatePolygonInit( ctx );
+ crStatePointInit( ctx );
+ crStateProgramInit( ctx );
+ crStateRegCombinerInit( ctx );
+ crStateStencilInit( ctx );
+ crStateTextureInit( ctx );
+ crStateTransformInit( ctx );
+ crStateViewportInit ( ctx );
+ crStateFramebufferObjectInit(ctx);
+ crStateGLSLInit(ctx);
+
+ /* This has to come last. */
+ crStateAttribInit( &(ctx->attrib) );
+
+ ctx->renderMode = GL_RENDER;
+
+ /* Initialize values that depend on the visual mode */
+ if (visBits & CR_DOUBLE_BIT) {
+ ctx->limits.doubleBuffer = GL_TRUE;
+ }
+ if (visBits & CR_RGB_BIT) {
+ ctx->limits.redBits = 8;
+ ctx->limits.greenBits = 8;
+ ctx->limits.blueBits = 8;
+ if (visBits & CR_ALPHA_BIT) {
+ ctx->limits.alphaBits = 8;
+ }
+ }
+ else {
+ ctx->limits.indexBits = 8;
+ }
+ if (visBits & CR_DEPTH_BIT) {
+ ctx->limits.depthBits = 24;
+ }
+ if (visBits & CR_STENCIL_BIT) {
+ ctx->limits.stencilBits = 8;
+ }
+ if (visBits & CR_ACCUM_BIT) {
+ ctx->limits.accumRedBits = 16;
+ ctx->limits.accumGreenBits = 16;
+ ctx->limits.accumBlueBits = 16;
+ if (visBits & CR_ALPHA_BIT) {
+ ctx->limits.accumAlphaBits = 16;
+ }
+ }
+ if (visBits & CR_STEREO_BIT) {
+ ctx->limits.stereo = GL_TRUE;
+ }
+ if (visBits & CR_MULTISAMPLE_BIT) {
+ ctx->limits.sampleBuffers = 1;
+ ctx->limits.samples = 4;
+ ctx->multisample.enabled = GL_TRUE;
+ }
+
+ if (visBits & CR_OVERLAY_BIT) {
+ ctx->limits.level = 1;
+ }
+
+ return ctx;
+}
+
+/** @todo crStateAttribDestroy*/
+static void
+crStateFreeContext(CRContext *ctx)
+{
+#ifndef DEBUG_misha
+ CRASSERT(g_pAvailableContexts[ctx->id] == ctx);
+#endif
+ if (g_pAvailableContexts[ctx->id] == ctx)
+ {
+ g_pAvailableContexts[ctx->id] = NULL;
+ --g_cContexts;
+ CRASSERT(g_cContexts < RT_ELEMENTS(g_pAvailableContexts));
+ }
+ else
+ {
+#ifndef DEBUG_misha
+ crWarning("freeing context %p, id(%d) not being in the context list", ctx, ctx->id);
+#endif
+ }
+
+ crStateClientDestroy( ctx );
+ crStateLimitsDestroy( &(ctx->limits) );
+ crStateBufferObjectDestroy( ctx );
+ crStateEvaluatorDestroy( ctx );
+ crStateListsDestroy( ctx );
+ crStateLightingDestroy( ctx );
+ crStateOcclusionDestroy( ctx );
+ crStateProgramDestroy( ctx );
+ crStateTextureDestroy( ctx );
+ crStateTransformDestroy( ctx );
+ crStateFreeShared(ctx, ctx->shared);
+ crStateFramebufferObjectDestroy(ctx);
+ crStateGLSLDestroy(ctx);
+ if (ctx->buffer.pFrontImg) crFree(ctx->buffer.pFrontImg);
+ if (ctx->buffer.pBackImg) crFree(ctx->buffer.pBackImg);
+ crFree( ctx );
+}
+
+#ifdef CHROMIUM_THREADSAFE
+# ifndef RT_OS_WINDOWS
+static void crStateThreadTlsDtor(void *pvValue)
+{
+ CRContext *pCtx = (CRContext*)pvValue;
+ VBoxTlsRefRelease(pCtx);
+}
+# endif
+#endif
+
+/*
+ * Allocate the state (dirty) bits data structures.
+ * This should be called before we create any contexts.
+ * We'll also create the default/NULL context at this time and make
+ * it the current context by default. This means that if someone
+ * tries to set GL state before calling MakeCurrent() they'll be
+ * modifying the default state object, and not segfaulting on a NULL
+ * pointer somewhere.
+ */
+void crStateInit(void)
+{
+ unsigned int i;
+
+ /* Purely initialize the context bits */
+ if (!__currentBits) {
+ __currentBits = (CRStateBits *) crCalloc( sizeof(CRStateBits) );
+ crStateClientInitBits( &(__currentBits->client) );
+ crStateLightingInitBits( &(__currentBits->lighting) );
+ } else
+ {
+#ifndef DEBUG_misha
+ crWarning("State tracker is being re-initialized..\n");
+#endif
+ }
+
+ for (i=0;i<CR_MAX_CONTEXTS;i++)
+ g_pAvailableContexts[i] = NULL;
+ g_cContexts = 0;
+
+#ifdef CHROMIUM_THREADSAFE
+ if (!__isContextTLSInited)
+ {
+# ifndef RT_OS_WINDOWS
+ /* tls destructor is implemented for all platforms except windows*/
+ crInitTSDF(&__contextTSD, crStateThreadTlsDtor);
+# else
+ /* windows should do cleanup via DllMain THREAD_DETACH notification */
+ crInitTSD(&__contextTSD);
+# endif
+ __isContextTLSInited = 1;
+ }
+#endif
+
+ if (defaultContext) {
+ /* Free the default/NULL context.
+ * Ensures context bits are reset */
+#ifdef CHROMIUM_THREADSAFE
+ SetCurrentContext(NULL);
+ VBoxTlsRefRelease(defaultContext);
+#else
+ crStateFreeContext(defaultContext);
+ __currentContext = NULL;
+#endif
+ }
+
+ /* Reset diff_api */
+ crMemZero(&diff_api, sizeof(SPUDispatchTable));
+
+ Assert(!gSharedState);
+ gSharedState = NULL;
+
+ /* Allocate the default/NULL context */
+ CRASSERT(g_pAvailableContexts[0] == NULL);
+ defaultContext = crStateCreateContextId(0, NULL, CR_RGB_BIT, NULL);
+ CRASSERT(g_pAvailableContexts[0] == defaultContext);
+ CRASSERT(g_cContexts == 1);
+#ifdef CHROMIUM_THREADSAFE
+ SetCurrentContext(defaultContext);
+#else
+ __currentContext = defaultContext;
+#endif
+}
+
+void crStateDestroy(void)
+{
+ int i;
+ if (__currentBits)
+ {
+ crStateClientDestroyBits(&(__currentBits->client));
+ crStateLightingDestroyBits(&(__currentBits->lighting));
+ crFree(__currentBits);
+ __currentBits = NULL;
+ }
+
+ SetCurrentContext(NULL);
+
+ for (i = CR_MAX_CONTEXTS-1; i >= 0; i--)
+ {
+ if (g_pAvailableContexts[i])
+ {
+#ifdef CHROMIUM_THREADSAFE
+ if (VBoxTlsRefIsFunctional(g_pAvailableContexts[i]))
+ VBoxTlsRefRelease(g_pAvailableContexts[i]);
+#else
+ crStateFreeContext(g_pAvailableContexts[i]);
+#endif
+ }
+ }
+
+ /* default context was stored in g_pAvailableContexts[0], so it was destroyed already */
+ defaultContext = NULL;
+
+
+#ifdef CHROMIUM_THREADSAFE
+ crFreeTSD(&__contextTSD);
+ __isContextTLSInited = 0;
+#endif
+}
+
+/*
+ * Notes on context switching and the "default context".
+ *
+ * See the paper "Tracking Graphics State for Networked Rendering"
+ * by Ian Buck, Greg Humphries and Pat Hanrahan for background
+ * information about how the state tracker and context switching
+ * works.
+ *
+ * When we make a new context current, we call crStateSwitchContext()
+ * in order to transform the 'from' context into the 'to' context
+ * (i.e. the old context to the new context). The transformation
+ * is accomplished by calling GL functions through the 'diff_api'
+ * so that the downstream GL machine (represented by the __currentContext
+ * structure) is updated to reflect the new context state. Finally,
+ * we point __currentContext to the new context.
+ *
+ * A subtle problem we have to deal with is context destruction.
+ * This issue arose while testing with Glean. We found that when
+ * the currently bound context was getting destroyed that state
+ * tracking was incorrect when a subsequent new context was activated.
+ * In DestroyContext, the __hwcontext was being set to NULL and effectively
+ * going away. Later in MakeCurrent we had no idea what the state of the
+ * downstream GL machine was (since __hwcontext was gone). This meant
+ * we had nothing to 'diff' against and the downstream GL machine was
+ * in an unknown state.
+ *
+ * The solution to this problem is the "default/NULL" context. The
+ * default context is created the first time CreateContext is called
+ * and is never freed. Whenever we get a crStateMakeCurrent(NULL) call
+ * or destroy the currently bound context in crStateDestroyContext()
+ * we call crStateSwitchContext() to switch to the default context and
+ * then set the __currentContext pointer to point to the default context.
+ * This ensures that the dirty bits are updated and the diff_api functions
+ * are called to keep the downstream GL machine in a known state.
+ * Finally, the __hwcontext variable is no longer needed now.
+ *
+ * Yeah, this is kind of a mind-bender, but it really solves the problem
+ * pretty cleanly.
+ *
+ * -Brian
+ */
+
+
+CRContext *
+crStateCreateContext(const CRLimitsState *limits, GLint visBits, CRContext *share)
+{
+ return crStateCreateContextEx(limits, visBits, share, -1);
+}
+
+CRContext *
+crStateCreateContextEx(const CRLimitsState *limits, GLint visBits, CRContext *share, GLint presetID)
+{
+ /* Must have created the default context via crStateInit() first */
+ CRASSERT(defaultContext);
+
+ if (presetID>0)
+ {
+ if(g_pAvailableContexts[presetID])
+ {
+ crWarning("requesting to create context with already allocated id");
+ return NULL;
+ }
+ }
+ else
+ {
+ int i;
+
+ for (i = 1 ; i < CR_MAX_CONTEXTS ; i++)
+ {
+ if (!g_pAvailableContexts[i])
+ {
+ presetID = i;
+ break;
+ }
+ }
+
+ if (presetID<=0)
+ {
+ crError( "Out of available contexts in crStateCreateContexts (max %d)",
+ CR_MAX_CONTEXTS );
+ /* never get here */
+ return NULL;
+ }
+ }
+
+ return crStateCreateContextId(presetID, limits, visBits, share);
+}
+
+void crStateDestroyContext( CRContext *ctx )
+{
+ CRContext *current = GetCurrentContext();
+
+ if (current == ctx) {
+ /* destroying the current context - have to be careful here */
+ CRASSERT(defaultContext);
+ /* Check to see if the differencer exists first,
+ we may not have one, aka the packspu */
+ if (diff_api.AlphaFunc)
+ crStateSwitchContext(current, defaultContext);
+#ifdef CHROMIUM_THREADSAFE
+ SetCurrentContext(defaultContext);
+#else
+ __currentContext = defaultContext;
+#endif
+ /* ensure matrix state is also current */
+ crStateMatrixMode(defaultContext->transform.matrixMode);
+ }
+
+#ifdef CHROMIUM_THREADSAFE
+ VBoxTlsRefMarkDestroy(ctx);
+# ifdef IN_GUEST
+ if (VBoxTlsRefCountGet(ctx) > 1 && ctx->shared == gSharedState)
+ {
+ /* we always need to free the global shared state to prevent the situation when guest thinks the shared objects are still valid, while host destroys them */
+ crStateFreeShared(ctx, ctx->shared);
+ ctx->shared = crStateAllocShared();
+ }
+# endif
+ VBoxTlsRefRelease(ctx);
+#else
+ crStateFreeContext(ctx);
+#endif
+}
+
+GLboolean crStateEnableDiffOnMakeCurrent(GLboolean fEnable)
+{
+ GLboolean bOld = g_bVBoxEnableDiffOnMakeCurrent;
+ g_bVBoxEnableDiffOnMakeCurrent = fEnable;
+ return bOld;
+}
+
+void crStateMakeCurrent( CRContext *ctx )
+{
+ CRContext *current = GetCurrentContext();
+ CRContext *pLocalCtx = ctx;
+
+ if (pLocalCtx == NULL)
+ pLocalCtx = defaultContext;
+
+ if (current == pLocalCtx)
+ return; /* no-op */
+
+ CRASSERT(pLocalCtx);
+
+ if (g_bVBoxEnableDiffOnMakeCurrent && current) {
+ /* Check to see if the differencer exists first,
+ we may not have one, aka the packspu */
+ if (diff_api.AlphaFunc)
+ crStateSwitchContext( current, pLocalCtx );
+ }
+
+#ifdef CHROMIUM_THREADSAFE
+ SetCurrentContext(pLocalCtx);
+#else
+ __currentContext = pLocalCtx;
+#endif
+
+ /* ensure matrix state is also current */
+ crStateMatrixMode(pLocalCtx->transform.matrixMode);
+}
+
+
+/*
+ * As above, but don't call crStateSwitchContext().
+ */
+static void crStateSetCurrentEx( CRContext *ctx, GLboolean fCleanupDefault )
+{
+ CRContext *current = GetCurrentContext();
+ CRContext *pLocalCtx = ctx;
+
+ if (pLocalCtx == NULL && !fCleanupDefault)
+ pLocalCtx = defaultContext;
+
+ if (current == pLocalCtx)
+ return; /* no-op */
+
+#ifdef CHROMIUM_THREADSAFE
+ SetCurrentContext(pLocalCtx);
+#else
+ __currentContext = pLocalCtx;
+#endif
+
+ if (pLocalCtx)
+ {
+ /* ensure matrix state is also current */
+ crStateMatrixMode(pLocalCtx->transform.matrixMode);
+ }
+}
+
+void crStateSetCurrent( CRContext *ctx )
+{
+ crStateSetCurrentEx( ctx, GL_FALSE );
+}
+
+void crStateCleanupCurrent()
+{
+ crStateSetCurrentEx( NULL, GL_TRUE );
+}
+
+
+CRContext *crStateGetCurrent(void)
+{
+ return GetCurrentContext();
+}
+
+
+void crStateUpdateColorBits(void)
+{
+ /* This is a hack to force updating the 'current' attribs */
+ CRStateBits *sb = GetCurrentBits();
+ FILLDIRTY(sb->current.dirty);
+ FILLDIRTY(sb->current.vertexAttrib[VERT_ATTRIB_COLOR0]);
+}
+
+
+void STATE_APIENTRY
+crStateChromiumParameteriCR( GLenum target, GLint value )
+{
+ /* This no-op function helps smooth code-gen */
+ (void)target; (void)value;
+}
+
+void STATE_APIENTRY
+crStateChromiumParameterfCR( GLenum target, GLfloat value )
+{
+ /* This no-op function helps smooth code-gen */
+ (void)target; (void)value;
+}
+
+void STATE_APIENTRY
+crStateChromiumParametervCR( GLenum target, GLenum type, GLsizei count, const GLvoid *values )
+{
+ /* This no-op function helps smooth code-gen */
+ (void)target; (void)type; (void)count; (void)values;
+}
+
+void STATE_APIENTRY
+crStateGetChromiumParametervCR( GLenum target, GLuint index, GLenum type, GLsizei count, GLvoid *values )
+{
+ /* This no-op function helps smooth code-gen */
+ (void)target; (void)index; (void)type; (void)count; (void)values;
+}
+
+void STATE_APIENTRY
+crStateReadPixels( GLint x, GLint y, GLsizei width, GLsizei height,
+ GLenum format, GLenum type, GLvoid *pixels )
+{
+ /* This no-op function helps smooth code-gen */
+ (void)x; (void)y; (void)width; (void)height; (void)format; (void)type; (void)pixels;
+}
+
+void crStateVBoxDetachThread(void)
+{
+ /* release the context ref so that it can be freed */
+ SetCurrentContext(NULL);
+}
+
+
+void crStateVBoxAttachThread(void)
+{
+}
+
+#if 0 /* who's refering to these? */
+
+GLint crStateVBoxCreateContext( GLint con, const char * dpyName, GLint visual, GLint shareCtx )
+{
+ (void)con; (void)dpyName; (void)visual; (void)shareCtx;
+ return 0;
+}
+
+GLint crStateVBoxWindowCreate( GLint con, const char *dpyName, GLint visBits )
+{
+ (void)con; (void)dpyName; (void)visBits;
+ return 0;
+}
+
+void crStateVBoxWindowDestroy( GLint con, GLint window )
+{
+ (void)con; (void)window;
+}
+
+GLint crStateVBoxConCreate(struct VBOXUHGSMI *pHgsmi)
+{
+ (void)pHgsmi;
+ return 0;
+}
+
+void crStateVBoxConDestroy(GLint con)
+{
+ (void)con;
+}
+
+void crStateVBoxConFlush(GLint con)
+{
+ (void)con;
+}
+
+#endif /* unused? */