Esempio n. 1
0
/*
 * Allocate a new ThreadInfo structure, setup a connection to the
 * server, allocate/init a packer context, bind this ThreadInfo to
 * the calling thread with crSetTSD().
 * We'll always call this function at least once even if we're not
 * using threads.
 */
ThreadInfo *replicatespuNewThread( CRthread id )
{
	ThreadInfo *thread;

#ifdef CHROMIUM_THREADSAFE_notyet
	crLockMutex(&_ReplicateMutex);
#else
	CRASSERT(replicate_spu.numThreads == 0);
#endif

	CRASSERT(replicate_spu.numThreads < MAX_THREADS);
	thread = &(replicate_spu.thread[replicate_spu.numThreads]);

	thread->id = id;
	thread->currentContext = NULL;

	/* connect to the server */
	thread->server.name = crStrdup( replicate_spu.name );
	thread->server.buffer_size = replicate_spu.buffer_size;
	if (replicate_spu.numThreads == 0) {
		replicatespuConnectToServer( &(thread->server) );
		CRASSERT(thread->server.conn);
		replicate_spu.swap = thread->server.conn->swap;
	}
	else {
		/* a new pthread */
		replicatespuFlushAll( &(replicate_spu.thread[0]) );
		crNetNewClient( replicate_spu.thread[0].server.conn, &(thread->server));
		CRASSERT(thread->server.conn);
	}

	/* packer setup */
	CRASSERT(thread->packer == NULL);
	thread->packer = crPackNewContext( replicate_spu.swap );
	CRASSERT(thread->packer);
	crPackInitBuffer( &(thread->buffer), crNetAlloc(thread->server.conn),
				thread->server.conn->buffer_size, thread->server.conn->mtu );
	thread->buffer.canBarf = thread->server.conn->Barf ? GL_TRUE : GL_FALSE;
	crPackSetBuffer( thread->packer, &thread->buffer );
	crPackFlushFunc( thread->packer, replicatespuFlush );
	crPackFlushArg( thread->packer, (void *) thread );
	crPackSendHugeFunc( thread->packer, replicatespuHuge );
	crPackSetContext( thread->packer );

#ifdef CHROMIUM_THREADSAFE_notyet
	crSetTSD(&_ReplicateTSD, thread);
#endif

	replicate_spu.numThreads++;

#ifdef CHROMIUM_THREADSAFE_notyet
	crUnlockMutex(&_ReplicateMutex);
#endif
	return thread;
}
Esempio n. 2
0
void PACKSPU_APIENTRY packspu_VBoxWindowDestroy( GLint con, GLint window )
{
    if (CRPACKSPU_IS_WDDM_CRHGSMI())
    {
        GET_THREAD(thread);
        if (con)
        {
            CRPackContext * curPacker = crPackGetContext();
            CRASSERT(!thread || !thread->bInjectThread);
            thread = GET_THREAD_VAL_ID(con);
            crPackSetContext(thread->packer);
            crPackWindowDestroy(window);
            if (curPacker != thread->packer)
                crPackSetContext(curPacker);
            return;
        }
        CRASSERT(thread);
        CRASSERT(thread->bInjectThread);
    }
    crPackWindowDestroy(window);
}
Esempio n. 3
0
void PACKSPU_APIENTRY packspu_VBoxPackSetInjectThread(void)
{
    crLockMutex(&_PackMutex);
    {
        int i;
        GET_THREAD(thread);
        CRASSERT(!thread);
        CRASSERT((pack_spu.numThreads>0) && (pack_spu.numThreads<MAX_THREADS));

        for (i=0; i<MAX_THREADS; ++i)
        {
            if (!pack_spu.thread[i].inUse)
            {
                thread = &pack_spu.thread[i];
                break;
            }
        }
        CRASSERT(thread);

        thread->inUse = GL_TRUE;
        thread->id = crThreadID();
        thread->currentContext = NULL;
        thread->bInjectThread = GL_TRUE;

        thread->netServer.name = crStrdup(pack_spu.name);
        thread->netServer.buffer_size = 64 * 1024;

        crNetNewClient(pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn, &(thread->netServer));
        CRASSERT(thread->netServer.conn);

        CRASSERT(thread->packer == NULL);
        thread->packer = crPackNewContext( pack_spu.swap );
        CRASSERT(thread->packer);
        crPackInitBuffer(&(thread->buffer), crNetAlloc(thread->netServer.conn),
                         thread->netServer.conn->buffer_size, thread->netServer.conn->mtu);
        thread->buffer.canBarf = thread->netServer.conn->Barf ? GL_TRUE : GL_FALSE;

        crPackSetBuffer( thread->packer, &thread->buffer );
        crPackFlushFunc( thread->packer, packspuFlush );
        crPackFlushArg( thread->packer, (void *) thread );
        crPackSendHugeFunc( thread->packer, packspuHuge );
        crPackSetContext( thread->packer );

        crSetTSD(&_PackTSD, thread);

        pack_spu.numThreads++;
    }
    crUnlockMutex(&_PackMutex);
}
Esempio n. 4
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;
	}
}
Esempio n. 5
0
GLint PACKSPU_APIENTRY packspu_WindowCreate( const char *dpyName, GLint visBits )
{
    GET_THREAD(thread);
    static int num_calls = 0;
    int writeback = pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network;
    GLint return_val = (GLint) 0;

    if (!thread) {
        thread = packspuNewThread( crThreadID() );
    }
    CRASSERT(thread);
    CRASSERT(thread->packer);

    crPackSetContext(thread->packer);

    if (pack_spu.swap)
    {
        crPackWindowCreateSWAP( dpyName, visBits, &return_val, &writeback );
    }
    else
    {
        crPackWindowCreate( dpyName, visBits, &return_val, &writeback );
    }
    packspuFlush(thread);
    if (!(thread->netServer.conn->actual_network))
    {
        return num_calls++;
    }
    else
    {
        while (writeback)
            crNetRecv();
        if (pack_spu.swap)
        {
            return_val = (GLint) SWAP32(return_val);
        }
        return return_val;
    }
}
Esempio n. 6
0
void PACKSPU_APIENTRY packspu_VBoxDetachThread()
{
    int i;
    GET_THREAD(thread);

    if (thread)
    {
        crLockMutex(&_PackMutex);

        for (i=0; i<MAX_THREADS; ++i)
        {
            if (pack_spu.thread[i].inUse && thread==&pack_spu.thread[i]
                && thread->id==crThreadID() && thread->netServer.conn)
            {
                CRASSERT(pack_spu.numThreads>0);

                packspuFlush((void *) thread);

                if (pack_spu.thread[i].packer)
                {
                    CR_LOCK_PACKER_CONTEXT(thread->packer);
                    crPackSetContext(NULL);
                    CR_UNLOCK_PACKER_CONTEXT(thread->packer);
                    crPackDeleteContext(pack_spu.thread[i].packer);
                }
                crNetFreeConnection(pack_spu.thread[i].netServer.conn);

                pack_spu.numThreads--;
                /*note can't shift the array here, because other threads have TLS references to array elements*/
                crMemZero(&pack_spu.thread[i], sizeof(ThreadInfo));

                crSetTSD(&_PackTSD, NULL);

                if (i==pack_spu.idxThreadInUse)
                {
                    for (i=0; i<MAX_THREADS; ++i)
                    {
                        if (pack_spu.thread[i].inUse)
                        {
                            pack_spu.idxThreadInUse=i;
                            break;
                        }
                    }
                }

                break;
            }
        }

        for (i=0; i<CR_MAX_CONTEXTS; ++i)
        {
            ContextInfo *ctx = &pack_spu.context[i];
            if (ctx->currentThread == thread)
            {
                CRASSERT(ctx->fAutoFlush);
                ctx->currentThread = NULL;
            }
        }

        crUnlockMutex(&_PackMutex);
    }

    crStateVBoxDetachThread();
}
Esempio n. 7
0
GLint PACKSPU_APIENTRY packspu_VBoxPackSetInjectThread(struct VBOXUHGSMI *pHgsmi)
{
    GLint con = 0;
    int i;
    GET_THREAD(thread);
    CRASSERT(!thread);
    crLockMutex(&_PackMutex);
    {
        CRASSERT(CRPACKSPU_IS_WDDM_CRHGSMI() || (pack_spu.numThreads>0));
        CRASSERT(pack_spu.numThreads<MAX_THREADS);
        for (i=0; i<MAX_THREADS; ++i)
        {
            if (!pack_spu.thread[i].inUse)
            {
                thread = &pack_spu.thread[i];
                break;
            }
        }
        CRASSERT(thread);

        thread->inUse = GL_TRUE;
        if (!CRPACKSPU_IS_WDDM_CRHGSMI())
            thread->id = crThreadID();
        else
            thread->id = THREAD_OFFSET_MAGIC + i;
        thread->currentContext = NULL;
        thread->bInjectThread = GL_TRUE;

        thread->netServer.name = crStrdup(pack_spu.name);
        thread->netServer.buffer_size = 64 * 1024;

        packspuConnectToServer(&(thread->netServer)
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
                , pHgsmi
#endif
        );
        CRASSERT(thread->netServer.conn);

        CRASSERT(thread->packer == NULL);
        thread->packer = crPackNewContext( pack_spu.swap );
        CRASSERT(thread->packer);
        crPackInitBuffer(&(thread->buffer), crNetAlloc(thread->netServer.conn),
                         thread->netServer.conn->buffer_size, thread->netServer.conn->mtu);
        thread->buffer.canBarf = thread->netServer.conn->Barf ? GL_TRUE : GL_FALSE;

        crPackSetBuffer( thread->packer, &thread->buffer );
        crPackFlushFunc( thread->packer, packspuFlush );
        crPackFlushArg( thread->packer, (void *) thread );
        crPackSendHugeFunc( thread->packer, packspuHuge );
        crPackSetContext( thread->packer );

        crSetTSD(&_PackTSD, thread);

        pack_spu.numThreads++;
    }
    crUnlockMutex(&_PackMutex);

    if (CRPACKSPU_IS_WDDM_CRHGSMI())
    {
        CRASSERT(thread->id - THREAD_OFFSET_MAGIC < RT_ELEMENTS(pack_spu.thread)
                && GET_THREAD_VAL_ID(thread->id) == thread);
        con = thread->id;
    }
    return con;
}
Esempio n. 8
0
GLint PACKSPU_APIENTRY packspu_VBoxWindowCreate( GLint con, const char *dpyName, GLint visBits )
{
    GET_THREAD(thread);
    static int num_calls = 0;
    int writeback = CRPACKSPU_IS_WDDM_CRHGSMI() ? 1 : pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn->actual_network;
    GLint return_val = (GLint) 0;
    ThreadInfo *curThread = thread;
    GLint retVal;

    if (CRPACKSPU_IS_WDDM_CRHGSMI())
    {
        if (!con)
        {
            crError("connection expected!");
            return 0;
        }
        thread = GET_THREAD_VAL_ID(con);
    }
    else
    {
        CRASSERT(!con);
        if (!thread) {
            thread = packspuNewThread(
#if defined(VBOX_WITH_CRHGSMI) && defined(IN_GUEST)
                NULL
#endif
                );
        }
    }
    CRASSERT(thread);
    CRASSERT(thread->packer);
    CRASSERT(crPackGetContext() == (curThread ? curThread->packer : NULL));

    crPackSetContext(thread->packer);

    if (pack_spu.swap)
    {
        crPackWindowCreateSWAP( dpyName, visBits, &return_val, &writeback );
    }
    else
    {
        crPackWindowCreate( dpyName, visBits, &return_val, &writeback );
    }
    packspuFlush(thread);
    if (!(thread->netServer.conn->actual_network))
    {
        retVal = num_calls++;
    }
    else
    {
        CRPACKSPU_WRITEBACK_WAIT(thread, writeback);
        if (pack_spu.swap)
        {
            return_val = (GLint) SWAP32(return_val);
        }
        retVal = return_val;
    }

    if (CRPACKSPU_IS_WDDM_CRHGSMI())
    {
        if (thread != curThread)
        {
            if (curThread)
                crPackSetContext(curThread->packer);
            else
                crPackSetContext(NULL);
        }
    }

    return retVal;
}
Esempio n. 9
0
void REPLICATESPU_APIENTRY
replicatespu_MakeCurrent( GLint window, GLint nativeWindow, GLint ctx )
{
	unsigned int i;
	unsigned int show_window = 0;
	WindowInfo *winInfo = (WindowInfo *) crHashtableSearch( replicate_spu.windowTable, window );
	ContextInfo *newCtx = (ContextInfo *) crHashtableSearch( replicate_spu.contextTable, ctx );
	GET_THREAD(thread);

	if (!winInfo) {
		crWarning("Replicate SPU: Invalid window ID %d passed to MakeCurrent", window);
		return;
	}

	if (thread)
		replicatespuFlushAll( (void *)thread );

	if (!thread) {
		thread = replicatespuNewThread( crThreadID() );
	}
	CRASSERT(thread);
	CRASSERT(thread->packer);

	if (newCtx && winInfo) {
		newCtx->currentWindow = winInfo;

#if 000
		/* This appears to be obsolete code */
		if (replicate_spu.render_to_crut_window && !nativeWindow) {
			char response[8096];
			CRConnection *conn = crMothershipConnect();
			if (!conn) {
				crError("Replicate SPU: Couldn't connect to the mothership to get CRUT drawable-- "
								"I have no idea what to do!");
			}
			crMothershipGetParam( conn, "crut_drawable", response );
			nativeWindow = crStrToInt(response);
			crDebug("Replicate SPU: using CRUT drawable: 0x%x", nativeWindow);
			crMothershipDisconnect(conn);
		}
#endif

		if (replicate_spu.glx_display
				&& winInfo
				&& winInfo->nativeWindow != nativeWindow)
		{
			winInfo->nativeWindow = nativeWindow;
			replicatespuMonitorWindow(winInfo);
			replicatespuRePositionWindow(winInfo);
			show_window = 1;
		}

		CRASSERT(newCtx->State);  /* verify valid */

		crPackSetContext( thread->packer );
	}

	/*
	 * Send the MakeCurrent to all crservers (vnc viewers)
	 */
	for (i = 0; i < CR_MAX_REPLICANTS; i++) {
		const GLint serverWin = winInfo ? winInfo->id[i] : -1;
		const GLint serverCtx = newCtx ? newCtx->rserverCtx[i] : -1;

		if (!IS_CONNECTED(replicate_spu.rserver[i].conn))
				continue;

		/* Note: app's native window ID not needed on server side; pass zero */
		if (replicate_spu.swap)
			crPackMakeCurrentSWAP(serverWin, 0, serverCtx);
		else
			crPackMakeCurrent(serverWin, 0, serverCtx);

		if (show_window) {
			/* We may find that the window was mapped before we
			 * called MakeCurrent, if that's the case then ensure
			 * the remote end gets the WindowShow event */
			if (winInfo->viewable) {
				if (replicate_spu.swap)
					crPackWindowShowSWAP(serverWin, GL_TRUE);
				else
					crPackWindowShow(serverWin, GL_TRUE);
			}
		}

		replicatespuFlushOne(thread, i);
	}

	if (newCtx) {
		crStateMakeCurrent( newCtx->State );
		crDLMSetCurrentState(newCtx->dlmState);
	}
	else {
		crStateMakeCurrent( NULL );
		crDLMSetCurrentState(NULL);
	}

	thread->currentContext = newCtx;
}
Esempio n. 10
0
GLint REPLICATESPU_APIENTRY
replicatespu_WindowCreate( const char *dpyName, GLint visBits )
{
	unsigned int i;
	static GLint freeWinID = 400;
	WindowInfo *winInfo = (WindowInfo *) crCalloc(sizeof(WindowInfo));
	GET_THREAD(thread);

	if (!winInfo)
		return -1;

	if (thread)
		replicatespuFlushAll( (void *) thread );
	else
		thread = replicatespuNewThread( crThreadID() );

	replicatespuFlushAll( (void *) thread );
	crPackSetContext( thread->packer );

#ifdef CHROMIUM_THREADSAFE_notyet
	crLockMutex(&_ReplicateMutex);
#endif

	for (i = 1; i < CR_MAX_REPLICANTS; i++) {
		if (IS_CONNECTED(replicate_spu.rserver[i].conn)) {
			int writeback = 1;
			int return_val = -1;

			if (replicate_spu.swap)
				crPackWindowCreateSWAP( dpyName, visBits, &return_val, &writeback );
			else
				crPackWindowCreate( dpyName, visBits, &return_val, &writeback );

			replicatespuFlushOne(thread, i);

			while (writeback)
				crNetRecv();

			if (replicate_spu.swap)
				return_val = (GLint) SWAP32(return_val);

			if (return_val < 0)
				crWarning("Replicate SPU: server %d returned window id -1", i);

			/* XXX temp */
			crDebug("Replicate SPU: Window create, server %d returned %d", i, return_val);
			winInfo->id[i] = return_val;
		}
		else {
			winInfo->id[i] = -1;
		}
	}

	winInfo->visBits = visBits;
	winInfo->width = 0;
	winInfo->height = 0;
	winInfo->nativeWindow = 0;
	winInfo->viewable = GL_FALSE; 

	crHashtableAdd(replicate_spu.windowTable, freeWinID, winInfo);

#ifdef CHROMIUM_THREADSAFE_notyet
	crUnlockMutex(&_ReplicateMutex);
#endif

	return freeWinID++;
}
Esempio n. 11
0
GLint PACKSPU_APIENTRY
packspu_CreateContext( const char *dpyName, GLint visual, GLint shareCtx )
{
    GET_THREAD(thread);
    int writeback = 1;
    GLint serverCtx = (GLint) -1;
    int slot;

#ifdef CHROMIUM_THREADSAFE
    crLockMutex(&_PackMutex);
#endif

    if (!thread) {
        thread = packspuNewThread(crThreadID());
    }
    CRASSERT(thread);
    CRASSERT(thread->packer);

    if (shareCtx > 0) {
        /* translate to server ctx id */
        shareCtx -= MAGIC_OFFSET;
        if (shareCtx >= 0 && shareCtx < pack_spu.numContexts) {
            shareCtx = pack_spu.context[shareCtx].serverCtx;
        }
    }

    crPackSetContext( thread->packer );

    /* Pack the command */
    if (pack_spu.swap)
        crPackCreateContextSWAP( dpyName, visual, shareCtx, &serverCtx, &writeback );
    else
        crPackCreateContext( dpyName, visual, shareCtx, &serverCtx, &writeback );

    /* Flush buffer and get return value */
    packspuFlush(thread);
    if (!(thread->netServer.conn->actual_network))
    {
        /* HUMUNGOUS HACK TO MATCH SERVER NUMBERING
         *
         * The hack exists solely to make file networking work for now.  This
         * is totally gross, but since the server expects the numbers to start
         * from 5000, we need to write them out this way.  This would be
         * marginally less gross if the numbers (500 and 5000) were maybe
         * some sort of #define'd constants somewhere so the client and the
         * server could be aware of how each other were numbering things in
         * cases like file networking where they actually
         * care. 
         *
         *  -Humper 
         *
         */
        serverCtx = 5000;
    }
    else {
        while (writeback)
            crNetRecv();

        if (pack_spu.swap) {
            serverCtx = (GLint) SWAP32(serverCtx);
        }
        if (serverCtx < 0) {
#ifdef CHROMIUM_THREADSAFE
            crUnlockMutex(&_PackMutex);
#endif
            crWarning("Failure in packspu_CreateContext");
            return -1;  /* failed */
        }
    }

    /* find an empty context slot */
    for (slot = 0; slot < pack_spu.numContexts; slot++) {
        if (!pack_spu.context[slot].clientState) {
            /* found empty slot */
            break;
        }
    }
    if (slot == pack_spu.numContexts) {
        pack_spu.numContexts++;
    }

    /* Fill in the new context info */
    /* XXX fix-up sharedCtx param here */
    pack_spu.context[slot].clientState = crStateCreateContext(NULL, visual, NULL);
    pack_spu.context[slot].clientState->bufferobject.retainBufferData = GL_TRUE;
    pack_spu.context[slot].serverCtx = serverCtx;

#ifdef CHROMIUM_THREADSAFE
    crUnlockMutex(&_PackMutex);
#endif

    return MAGIC_OFFSET + slot;
}
Esempio n. 12
0
/*
 * Allocate a new ThreadInfo structure, setup a connection to the
 * server, allocate/init a packer context, bind this ThreadInfo to
 * the calling thread with crSetTSD().
 * We'll always call this function at least once even if we're not
 * using threads.
 */
ThreadInfo *packspuNewThread( unsigned long id )
{
    ThreadInfo *thread=NULL;
    int i;

#ifdef CHROMIUM_THREADSAFE
    crLockMutex(&_PackMutex);
#else
    CRASSERT(pack_spu.numThreads == 0);
#endif

    CRASSERT(pack_spu.numThreads < MAX_THREADS);
    for (i=0; i<MAX_THREADS; ++i)
    {
        if (!pack_spu.thread[i].inUse)
        {
            thread = &pack_spu.thread[i];
            break;
        }
    }
    CRASSERT(thread);

    thread->inUse = GL_TRUE;
    thread->id = id;
    thread->currentContext = NULL;
    thread->bInjectThread = GL_FALSE;

    /* connect to the server */
    thread->netServer.name = crStrdup( pack_spu.name );
    thread->netServer.buffer_size = pack_spu.buffer_size;
    if (pack_spu.numThreads == 0) {
        packspuConnectToServer( &(thread->netServer) );
        if (!thread->netServer.conn) {
            return NULL;
        }
        pack_spu.swap = thread->netServer.conn->swap;
    }
    else {
        /* a new pthread */
        crNetNewClient(pack_spu.thread[pack_spu.idxThreadInUse].netServer.conn, &(thread->netServer));
        CRASSERT(thread->netServer.conn);
    }

    /* packer setup */
    CRASSERT(thread->packer == NULL);
    thread->packer = crPackNewContext( pack_spu.swap );
    CRASSERT(thread->packer);
    crPackInitBuffer( &(thread->buffer), crNetAlloc(thread->netServer.conn),
                thread->netServer.conn->buffer_size, thread->netServer.conn->mtu );
    thread->buffer.canBarf = thread->netServer.conn->Barf ? GL_TRUE : GL_FALSE;
    crPackSetBuffer( thread->packer, &thread->buffer );
    crPackFlushFunc( thread->packer, packspuFlush );
    crPackFlushArg( thread->packer, (void *) thread );
    crPackSendHugeFunc( thread->packer, packspuHuge );
    crPackSetContext( thread->packer );

#ifdef CHROMIUM_THREADSAFE
    crSetTSD(&_PackTSD, thread);
#endif

    pack_spu.numThreads++;

#ifdef CHROMIUM_THREADSAFE
    crUnlockMutex(&_PackMutex);
#endif
    return thread;
}
Esempio n. 13
0
void PACKSPU_APIENTRY packspu_MakeCurrent( GLint window, GLint nativeWindow, GLint ctx )
{
    GET_THREAD(thread);
    GLint serverCtx;
    ContextInfo *newCtx;

    if (!thread) {
        thread = packspuNewThread( crThreadID() );
    }
    CRASSERT(thread);
    CRASSERT(thread->packer);

    if (ctx) {
        const int slot = ctx - MAGIC_OFFSET;

        CRASSERT(slot >= 0);
        CRASSERT(slot < pack_spu.numContexts);

        newCtx = &pack_spu.context[slot];
        CRASSERT(newCtx->clientState);  /* verify valid */

        if (newCtx->fAutoFlush)
        {
            if (newCtx->currentThread && newCtx->currentThread != thread)
            {
                crLockMutex(&_PackMutex);
                /* do a flush for the previusly assigned thread
                 * to ensure all commands issued there are submitted */
                if (newCtx->currentThread
                    && newCtx->currentThread->inUse
                    && newCtx->currentThread->netServer.conn
                    && newCtx->currentThread->packer && newCtx->currentThread->packer->currentBuffer)
                {
                    packspuFlush((void *) newCtx->currentThread);
                }
                crUnlockMutex(&_PackMutex);
            }
            newCtx->currentThread = thread;
        }

        thread->currentContext = newCtx;

        crPackSetContext( thread->packer );
        crStateMakeCurrent( newCtx->clientState );
        //crStateSetCurrentPointers(newCtx->clientState, &thread->packer->current);
        serverCtx = pack_spu.context[slot].serverCtx;
    }
    else {
        thread->currentContext = NULL;
        crStateMakeCurrent( NULL );
        newCtx = NULL;
        serverCtx = 0;
    }

    if (pack_spu.swap)
        crPackMakeCurrentSWAP( window, nativeWindow, serverCtx );
    else
        crPackMakeCurrent( window, nativeWindow, serverCtx );

    {
        GET_THREAD(t);
        (void) t;
        CRASSERT(t);
    }
}