void TILESORTSPU_APIENTRY tilesortspu_Begin( GLenum mode )
{
	GET_CONTEXT(ctx);
	CRTransformState *t = &(ctx->transform);
	CRCurrentState *c = &(ctx->current);
	GLenum dlMode = thread->currentContext->displayListMode;
	if (dlMode != GL_FALSE) {
	    /* Just compiling or creating display lists */
	    if (tilesort_spu.lazySendDLists) crDLMCompileBegin(mode);
	    else if (tilesort_spu.swap) crPackBeginSWAP(mode);
	    else crPackBegin(mode);
	    return;
	}

	/* We have to set this every time because a flush from 
	 * the state tracker will turn off its flusher. */

	thread->pinchState.beginOp = thread->packer->buffer.opcode_current;
	thread->pinchState.beginData = thread->packer->buffer.data_current;
	thread->pinchState.wind = 0;
	thread->pinchState.isLoop = 0;

	crStateFlushFunc( tilesortspuFlush_callback );
	if (tilesort_spu.swap)
	{
		crPackBeginSWAP( mode );
	}
	else
	{
		crPackBegin( mode );
	}
	crStateBegin( mode );
	if (! t->modelViewProjectionValid)
	{
		/* Make sure that the state tracker has the very very 
		 * latest composite modelview + projection matrix 
		 * computed, since we're going to need it. */
		crStateTransformUpdateTransform( t );
	}
	c->current->vtx_count_begin = c->current->vtx_count;
}
void REPLICATESPU_APIENTRY replicatespu_Begin( GLenum mode )
{
	GET_THREAD(thread);
	CRPackBuffer *buf = &thread->BeginEndBuffer;

	CRASSERT( mode >= GL_POINTS && mode <= GL_POLYGON );

	if (thread->currentContext->displayListMode != GL_FALSE) {
		crDLMCompileBegin(mode);
	}
	if (replicate_spu.swap)
	{
		crPackBeginSWAP( mode );
	}
	else
	{
		crPackBegin( mode );
	}

	if ( thread->server.conn->Barf ) {
		thread->BeginEndMode = mode;
		thread->BeginEndState = -1;
		if ( mode == GL_LINES || mode == GL_TRIANGLES || mode == GL_QUADS || mode == GL_POLYGON )
		{
			CRASSERT(!buf->pack);

			crPackReleaseBuffer( thread->packer );
			buf->pack = crNetAlloc( thread->server.conn );
			crPackInitBuffer( buf, buf->pack, thread->server.conn->buffer_size, thread->server.conn->mtu );
			buf->holds_BeginEnd = 1;
			buf->in_BeginEnd = 1;
			crPackSetBuffer( thread->packer, buf );

			thread->BeginEndState = 0;
		}
	}
}
void
crPackExpandDrawArrays(GLenum mode, GLint first, GLsizei count, CRClientState *c)
{
    int i;

    if (count < 0)
    {
        __PackError(__LINE__, __FILE__, GL_INVALID_VALUE, "crPackDrawArrays(negative count)");
        return;
    }

    if (mode > GL_POLYGON)
    {
        __PackError(__LINE__, __FILE__, GL_INVALID_ENUM, "crPackDrawArrays(bad mode)");
        return;
    }

    crPackBegin(mode);
    for (i=0; i<count; i++)
    {
        crPackExpandArrayElement(first + i, c);
    }
    crPackEnd();
}
/**
 * Expand glDrawElements into crPackBegin/Vertex/End, etc commands.
 * Note: if mode==999, don't call glBegin/glEnd.
 */
void
crPackExpandDrawElements(GLenum mode, GLsizei count, GLenum type,
                                                 const GLvoid *indices, CRClientState *c)
{
    int i;
    GLubyte *p = (GLubyte *)indices;
#ifdef CR_ARB_vertex_buffer_object
    CRBufferObject *elementsBuffer = crStateGetCurrent()->bufferobject.elementsBuffer;
#endif

    if (count < 0)
    {
        __PackError(__LINE__, __FILE__, GL_INVALID_VALUE,
                                "crPackDrawElements(negative count)");
        return;
    }

    if (mode > GL_POLYGON && mode != 999)
    {
        __PackError(__LINE__, __FILE__, GL_INVALID_ENUM,
                                "crPackDrawElements(bad mode)");
        return;
    }

    if (type != GL_UNSIGNED_BYTE &&
            type != GL_UNSIGNED_SHORT &&
            type != GL_UNSIGNED_INT)
    {
        __PackError(__LINE__, __FILE__, GL_INVALID_ENUM,
                                "crPackDrawElements(bad type)");
        return;
    }

#ifdef CR_ARB_vertex_buffer_object
    if (elementsBuffer && elementsBuffer->data)
    {
        p = (unsigned char *)(elementsBuffer->data) + (unsigned long)p;
    }
#endif

    if (mode != 999)
        crPackBegin(mode);

    //crDebug("crPackExpandDrawElements mode:0x%x, count:%d, type:0x%x", mode, count, type);

    switch (type)
    {
        case GL_UNSIGNED_BYTE:
            for (i=0; i<count; i++)
            {
                crPackExpandArrayElement((GLint) *p++, c);
            }
            break;
        case GL_UNSIGNED_SHORT:
            for (i=0; i<count; i++)
            {
                crPackExpandArrayElement((GLint) * (GLushort *) p, c);
                p+=sizeof (GLushort);
            }
            break;
        case GL_UNSIGNED_INT:
            for (i=0; i<count; i++)
            {
                crPackExpandArrayElement((GLint) * (GLuint *) p, c);
                p+=sizeof (GLuint);
            }
            break;
        default:
            crError( "this can't happen: array_spu.self.DrawElements" );
            break;
    }

    if (mode != 999)
        crPackEnd();
}