summaryrefslogtreecommitdiffstats
path: root/src/VBox/Additions/common/crOpenGL/pack/packspu_client.c
diff options
context:
space:
mode:
authorDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 03:01:46 +0000
committerDaniel Baumann <daniel.baumann@progress-linux.org>2024-05-06 03:01:46 +0000
commitf8fe689a81f906d1b91bb3220acde2a4ecb14c5b (patch)
tree26484e9d7e2c67806c2d1760196ff01aaa858e8c /src/VBox/Additions/common/crOpenGL/pack/packspu_client.c
parentInitial commit. (diff)
downloadvirtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.tar.xz
virtualbox-f8fe689a81f906d1b91bb3220acde2a4ecb14c5b.zip
Adding upstream version 6.0.4-dfsg.upstream/6.0.4-dfsgupstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/VBox/Additions/common/crOpenGL/pack/packspu_client.c')
-rw-r--r--src/VBox/Additions/common/crOpenGL/pack/packspu_client.c910
1 files changed, 910 insertions, 0 deletions
diff --git a/src/VBox/Additions/common/crOpenGL/pack/packspu_client.c b/src/VBox/Additions/common/crOpenGL/pack/packspu_client.c
new file mode 100644
index 00000000..19c11880
--- /dev/null
+++ b/src/VBox/Additions/common/crOpenGL/pack/packspu_client.c
@@ -0,0 +1,910 @@
+/* Copyright (c) 2001, Stanford University
+ * All rights reserved
+ *
+ * See the file LICENSE.txt for information on redistributing this software.
+ */
+
+#include "packspu.h"
+#include "cr_packfunctions.h"
+#include "cr_glstate.h"
+#include "packspu_proto.h"
+#include "cr_mem.h"
+
+void PACKSPU_APIENTRY packspu_FogCoordPointerEXT( GLenum type, GLsizei stride, const GLvoid *pointer )
+{
+#if CR_ARB_vertex_buffer_object
+ GET_CONTEXT(ctx);
+ if (ctx->clientState->extensions.ARB_vertex_buffer_object) {
+ if (pack_spu.swap)
+ crPackFogCoordPointerEXTSWAP( type, stride, pointer );
+ else
+ crPackFogCoordPointerEXT( type, stride, pointer );
+ }
+#endif
+ crStateFogCoordPointerEXT( type, stride, pointer );
+}
+
+void PACKSPU_APIENTRY packspu_ColorPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
+{
+#if CR_ARB_vertex_buffer_object
+ GET_CONTEXT(ctx);
+ if (ctx->clientState->extensions.ARB_vertex_buffer_object) {
+ if (pack_spu.swap)
+ crPackColorPointerSWAP( size, type, stride, pointer );
+ else
+ crPackColorPointer( size, type, stride, pointer );
+ }
+#endif
+ crStateColorPointer( size, type, stride, pointer );
+}
+
+void PACKSPU_APIENTRY packspu_SecondaryColorPointerEXT( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
+{
+#if CR_ARB_vertex_buffer_object
+ GET_CONTEXT(ctx);
+ if (ctx->clientState->extensions.ARB_vertex_buffer_object) {
+ if (pack_spu.swap)
+ crPackSecondaryColorPointerEXTSWAP( size, type, stride, pointer );
+ else
+ crPackSecondaryColorPointerEXT( size, type, stride, pointer );
+ }
+#endif
+ crStateSecondaryColorPointerEXT( size, type, stride, pointer );
+}
+
+void PACKSPU_APIENTRY packspu_VertexPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
+{
+#if CR_ARB_vertex_buffer_object
+ GET_CONTEXT(ctx);
+ CRASSERT(ctx->clientState->extensions.ARB_vertex_buffer_object);
+ if (ctx->clientState->extensions.ARB_vertex_buffer_object) {
+ if (pack_spu.swap)
+ crPackVertexPointerSWAP( size, type, stride, pointer );
+ else
+ crPackVertexPointer( size, type, stride, pointer );
+ }
+#endif
+ crStateVertexPointer( size, type, stride, pointer );
+}
+
+void PACKSPU_APIENTRY packspu_TexCoordPointer( GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
+{
+#if CR_ARB_vertex_buffer_object
+ GET_CONTEXT(ctx);
+ if (ctx->clientState->extensions.ARB_vertex_buffer_object) {
+ if (pack_spu.swap)
+ crPackTexCoordPointerSWAP( size, type, stride, pointer );
+ else
+ crPackTexCoordPointer( size, type, stride, pointer );
+ }
+#endif
+ crStateTexCoordPointer( size, type, stride, pointer );
+}
+
+void PACKSPU_APIENTRY packspu_NormalPointer( GLenum type, GLsizei stride, const GLvoid *pointer )
+{
+#if CR_ARB_vertex_buffer_object
+ GET_CONTEXT(ctx);
+ if (ctx->clientState->extensions.ARB_vertex_buffer_object) {
+ if (pack_spu.swap)
+ crPackNormalPointerSWAP( type, stride, pointer );
+ else
+ crPackNormalPointer( type, stride, pointer );
+ }
+#endif
+ crStateNormalPointer( type, stride, pointer );
+}
+
+void PACKSPU_APIENTRY packspu_EdgeFlagPointer( GLsizei stride, const GLvoid *pointer )
+{
+#if CR_ARB_vertex_buffer_object
+ GET_CONTEXT(ctx);
+ if (ctx->clientState->extensions.ARB_vertex_buffer_object) {
+ if (pack_spu.swap)
+ crPackEdgeFlagPointerSWAP( stride, pointer );
+ else
+ crPackEdgeFlagPointer( stride, pointer );
+ }
+#endif
+ crStateEdgeFlagPointer( stride, pointer );
+}
+
+void PACKSPU_APIENTRY packspu_VertexAttribPointerARB( GLuint index, GLint size, GLenum type, GLboolean normalized, GLsizei stride, const GLvoid *pointer )
+{
+#if CR_ARB_vertex_buffer_object
+ GET_CONTEXT(ctx);
+ if (ctx->clientState->extensions.ARB_vertex_buffer_object) {
+ if (pack_spu.swap)
+ crPackVertexAttribPointerARBSWAP( index, size, type, normalized, stride, pointer );
+ else
+ crPackVertexAttribPointerARB( index, size, type, normalized, stride, pointer );
+ }
+#endif
+ crStateVertexAttribPointerARB( index, size, type, normalized, stride, pointer );
+}
+
+void PACKSPU_APIENTRY packspu_VertexAttribPointerNV( GLuint index, GLint size, GLenum type, GLsizei stride, const GLvoid *pointer )
+{
+#if CR_ARB_vertex_buffer_object
+ GET_CONTEXT(ctx);
+ if (ctx->clientState->extensions.ARB_vertex_buffer_object) {
+ if (pack_spu.swap)
+ crPackVertexAttribPointerNVSWAP( index, size, type, stride, pointer );
+ else
+ crPackVertexAttribPointerNV( index, size, type, stride, pointer );
+ }
+#endif
+ crStateVertexAttribPointerNV( index, size, type, stride, pointer );
+}
+
+void PACKSPU_APIENTRY packspu_IndexPointer( GLenum type, GLsizei stride, const GLvoid *pointer )
+{
+#if CR_ARB_vertex_buffer_object
+ GET_CONTEXT(ctx);
+ if (ctx->clientState->extensions.ARB_vertex_buffer_object) {
+ if (pack_spu.swap)
+ crPackIndexPointerSWAP( type, stride, pointer );
+ else
+ crPackIndexPointer( type, stride, pointer );
+ }
+#endif
+ crStateIndexPointer(type, stride, pointer);
+}
+
+void PACKSPU_APIENTRY packspu_GetPointerv( GLenum pname, GLvoid **params )
+{
+ crStateGetPointerv( pname, params );
+}
+
+void PACKSPU_APIENTRY packspu_InterleavedArrays( GLenum format, GLsizei stride, const GLvoid *pointer )
+{
+#if CR_ARB_vertex_buffer_object
+ GET_CONTEXT(ctx);
+ if (ctx->clientState->extensions.ARB_vertex_buffer_object) {
+ if (pack_spu.swap)
+ crPackInterleavedArraysSWAP( format, stride, pointer );
+ else
+ crPackInterleavedArrays( format, stride, pointer );
+ }
+#endif
+
+ /*crDebug("packspu_InterleavedArrays");*/
+
+ crStateInterleavedArrays( format, stride, pointer );
+}
+
+#ifdef DEBUG_misha
+/* debugging */
+//# define CR_FORCE_ZVA_SERVER_ARRAY
+#endif
+# define CR_FORCE_ZVA_EXPAND
+
+
+static GLboolean packspuZvaCreate(ContextInfo *pCtx, const GLfloat *pValue, GLuint cValues)
+{
+ ZvaBufferInfo *pInfo = &pCtx->zvaBufferInfo;
+ GLuint cbValue = 4 * sizeof (*pValue);
+ GLuint cbValues = cValues * cbValue;
+ GLfloat *pBuffer;
+ uint8_t *pu8Buf;
+ GLuint i;
+
+ /* quickly sort out if we can use the current value */
+ if (pInfo->idBuffer
+ && pInfo->cValues >= cValues
+ && !crMemcmp(pValue, &pInfo->Value, cbValue))
+ return GL_FALSE;
+
+ pBuffer = (GLfloat*)crAlloc(cbValues);
+ if (!pBuffer)
+ {
+ WARN(("crAlloc for pBuffer failed"));
+ return GL_FALSE;
+ }
+
+ pu8Buf = (uint8_t *)pBuffer;
+ for (i = 0; i < cValues; ++i)
+ {
+ crMemcpy(pu8Buf, pValue, cbValue);
+ pu8Buf += cbValue;
+ }
+
+ /* */
+ if (!pInfo->idBuffer)
+ {
+ pack_spu.self.GenBuffersARB(1, &pInfo->idBuffer);
+ Assert(pInfo->idBuffer);
+ }
+
+ pack_spu.self.BindBufferARB(GL_ARRAY_BUFFER_ARB, pInfo->idBuffer);
+
+ if (pInfo->cbBuffer < cbValues)
+ {
+ pack_spu.self.BufferDataARB(GL_ARRAY_BUFFER_ARB, cbValues, pBuffer, GL_DYNAMIC_DRAW_ARB);
+ pInfo->cbBuffer = cbValues;
+ }
+ else
+ {
+ pack_spu.self.BufferSubDataARB(GL_ARRAY_BUFFER_ARB, 0, cbValues, pBuffer);
+ }
+
+ pInfo->cValues = cValues;
+ crMemcpy(&pInfo->Value, pValue, cbValue);
+
+ crFree(pBuffer);
+
+ return GL_TRUE;
+}
+
+typedef struct
+{
+ ContextInfo *pCtx;
+ GLuint idBuffer;
+ CRClientPointer cp;
+} CR_ZVA_RESTORE_CTX;
+
+static void packspuZvaEnable(ContextInfo *pCtx, const GLfloat *pValue, GLuint cValues, CR_ZVA_RESTORE_CTX *pRestoreCtx)
+{
+ CRContext *g = pCtx->clientState;
+
+ Assert(0);
+
+#ifdef DEBUG
+ {
+ CRContext *pCurState = crStateGetCurrent();
+
+ Assert(g == pCurState);
+ }
+#endif
+
+ pRestoreCtx->pCtx = pCtx;
+ pRestoreCtx->idBuffer = g->bufferobject.arrayBuffer ? g->bufferobject.arrayBuffer->id : 0;
+ pRestoreCtx->cp = g->client.array.a[0];
+
+ Assert(!pRestoreCtx->cp.enabled);
+
+ /* buffer ref count mechanism does not work actually atm,
+ * still ensure the buffer does not get destroyed if we fix it in the future */
+ if (pRestoreCtx->cp.buffer)
+ pRestoreCtx->cp.buffer->refCount++;
+
+ packspuZvaCreate(pCtx, pValue, cValues);
+
+ pack_spu.self.BindBufferARB(GL_ARRAY_BUFFER_ARB, pCtx->zvaBufferInfo.idBuffer);
+
+ pack_spu.self.VertexAttribPointerARB(0, 4, GL_FLOAT,
+ GL_FALSE, /*normalized*/
+ 0, /*stride*/
+ NULL /*addr*/);
+
+ pack_spu.self.EnableVertexAttribArrayARB(0);
+}
+
+static void packspuZvaDisable(CR_ZVA_RESTORE_CTX *pRestoreCtx)
+{
+ if (pRestoreCtx->cp.buffer)
+ pack_spu.self.BindBufferARB(GL_ARRAY_BUFFER_ARB, pRestoreCtx->cp.buffer->id);
+ else
+ pack_spu.self.BindBufferARB(GL_ARRAY_BUFFER_ARB, 0);
+
+ pack_spu.self.VertexAttribPointerARB(0, pRestoreCtx->cp.size, pRestoreCtx->cp.type,
+ pRestoreCtx->cp.normalized, /*normalized*/
+ pRestoreCtx->cp.stride, /*stride*/
+ pRestoreCtx->cp.p);
+
+ if (pRestoreCtx->cp.enabled)
+ pack_spu.self.EnableVertexAttribArrayARB(0);
+ else
+ pack_spu.self.DisableVertexAttribArrayARB(0);
+
+ if (pRestoreCtx->cp.buffer)
+ {
+ if (pRestoreCtx->cp.buffer->id != pRestoreCtx->idBuffer)
+ pack_spu.self.BindBufferARB(GL_ARRAY_BUFFER_ARB, pRestoreCtx->idBuffer);
+
+ /* we have increased the refcount above, decrease it back */
+ pRestoreCtx->cp.buffer->refCount--;
+ }
+ else
+ {
+ if (pRestoreCtx->idBuffer)
+ pack_spu.self.BindBufferARB(GL_ARRAY_BUFFER_ARB, pRestoreCtx->idBuffer);
+ }
+
+#ifdef DEBUG
+ {
+ CRContext *g = pRestoreCtx->pCtx->clientState;
+ CRContext *pCurState = crStateGetCurrent();
+
+ Assert(g == pCurState);
+
+ Assert(pRestoreCtx->cp.p == g->client.array.a[0].p);
+ Assert(pRestoreCtx->cp.size == g->client.array.a[0].size);
+ Assert(pRestoreCtx->cp.type == g->client.array.a[0].type);
+ Assert(pRestoreCtx->cp.stride == g->client.array.a[0].stride);
+ Assert(pRestoreCtx->cp.enabled == g->client.array.a[0].enabled);
+ Assert(pRestoreCtx->cp.normalized == g->client.array.a[0].normalized);
+ Assert(pRestoreCtx->cp.bytesPerIndex == g->client.array.a[0].bytesPerIndex);
+# ifdef CR_ARB_vertex_buffer_object
+ Assert(pRestoreCtx->cp.buffer == g->client.array.a[0].buffer);
+# endif
+# ifdef CR_EXT_compiled_vertex_array
+ Assert(pRestoreCtx->cp.locked == g->client.array.a[0].locked);
+# endif
+ Assert(pRestoreCtx->idBuffer == (g->bufferobject.arrayBuffer ? g->bufferobject.arrayBuffer->id : 0));
+ }
+#endif
+}
+
+void PACKSPU_APIENTRY
+packspu_ArrayElement( GLint index )
+{
+/** @todo cash guest/host pointers calculation and use appropriate path here without crStateUseServerArrays call*/
+#if 1
+ GLboolean serverArrays = GL_FALSE;
+ GLuint cZvaValues = 0;
+ GLfloat aAttrib[4];
+
+#if CR_ARB_vertex_buffer_object
+ {
+ GET_CONTEXT(ctx);
+ /*crDebug("packspu_ArrayElement index:%i", index);*/
+ if (ctx->clientState->extensions.ARB_vertex_buffer_object)
+ {
+ serverArrays = crStateUseServerArrays();
+ if (ctx->fCheckZerroVertAttr)
+ cZvaValues = crStateNeedDummyZeroVertexArray(thread->currentContext->clientState, &thread->packer->current, aAttrib);
+ }
+ }
+#endif
+
+ if (serverArrays
+#ifdef CR_FORCE_ZVA_EXPAND
+ && !cZvaValues
+#endif
+ ) {
+ CR_ZVA_RESTORE_CTX RestoreCtx;
+ GET_CONTEXT(ctx);
+ CRClientState *clientState = &(ctx->clientState->client);
+
+ Assert(cZvaValues < UINT32_MAX/2);
+
+ /* LockArraysEXT can not be executed between glBegin/glEnd pair, it also
+ * leads to vertexpointers being adjusted on the host side between glBegin/glEnd calls which
+ * produces unpredictable results. Locking is done before the glBegin call instead.
+ */
+ CRASSERT(!clientState->array.locked || clientState->array.synced);
+
+ if (cZvaValues)
+ packspuZvaEnable(ctx, aAttrib, cZvaValues, &RestoreCtx);
+
+ /* Send the DrawArrays command over the wire */
+ if (pack_spu.swap)
+ crPackArrayElementSWAP( index );
+ else
+ crPackArrayElement( index );
+
+ if (cZvaValues)
+ packspuZvaDisable(&RestoreCtx);
+ }
+ else {
+ /* evaluate locally */
+ GET_CONTEXT(ctx);
+ CRClientState *clientState = &(ctx->clientState->client);
+
+#ifdef CR_FORCE_ZVA_SERVER_ARRAY
+ CR_ZVA_RESTORE_CTX RestoreCtx;
+
+ if (cZvaValues && cZvaValues < UINT32_MAX/2)
+ packspuZvaEnable(ctx, aAttrib, cZvaValues, &RestoreCtx);
+#endif
+
+ if (pack_spu.swap)
+ crPackExpandArrayElementSWAP( index, clientState, cZvaValues ? aAttrib : NULL );
+ else
+ crPackExpandArrayElement( index, clientState, cZvaValues ? aAttrib : NULL );
+
+#ifdef CR_FORCE_ZVA_SERVER_ARRAY
+ if (cZvaValues && cZvaValues < UINT32_MAX/2)
+ packspuZvaDisable(&RestoreCtx);
+#endif
+ }
+#else
+ GET_CONTEXT(ctx);
+ CRClientState *clientState = &(ctx->clientState->client);
+ crPackExpandArrayElement(index, clientState, NULL);
+#endif
+}
+
+/*#define CR_USE_LOCKARRAYS*/
+#ifdef CR_USE_LOCKARRAYS
+# error "check Zero Vertex Attrib hack is supported properly!"
+#endif
+
+void PACKSPU_APIENTRY
+packspu_DrawElements( GLenum mode, GLsizei count, GLenum type, const GLvoid *indices )
+{
+ GLboolean serverArrays = GL_FALSE;
+ GLuint cZvaValues = 0;
+ GLfloat aAttrib[4];
+
+#if CR_ARB_vertex_buffer_object
+ GLboolean lockedArrays = GL_FALSE;
+ CRBufferObject *elementsBuffer;
+ {
+ GET_CONTEXT(ctx);
+ elementsBuffer = crStateGetCurrent()->bufferobject.elementsBuffer;
+ /*crDebug("DrawElements count=%d, indices=%p", count, indices);*/
+ if (ctx->clientState->extensions.ARB_vertex_buffer_object)
+ {
+ serverArrays = crStateUseServerArrays();
+ if (ctx->fCheckZerroVertAttr)
+ cZvaValues = crStateNeedDummyZeroVertexArray(thread->currentContext->clientState, &thread->packer->current, aAttrib);
+ }
+ }
+
+# ifdef CR_USE_LOCKARRAYS
+ if (!serverArrays && !ctx->clientState->client.array.locked && (count>3)
+ && (!elementsBuffer || !elementsBuffer->id))
+ {
+ GLuint min, max;
+ GLsizei i;
+
+ switch (type)
+ {
+ case GL_UNSIGNED_BYTE:
+ {
+ GLubyte *pIdx = (GLubyte *)indices;
+ min = max = pIdx[0];
+ for (i=0; i<count; ++i)
+ {
+ if (pIdx[i]<min) min = pIdx[i];
+ else if (pIdx[i]>max) max = pIdx[i];
+ }
+ break;
+ }
+ case GL_UNSIGNED_SHORT:
+ {
+ GLushort *pIdx = (GLushort *)indices;
+ min = max = pIdx[0];
+ for (i=0; i<count; ++i)
+ {
+ if (pIdx[i]<min) min = pIdx[i];
+ else if (pIdx[i]>max) max = pIdx[i];
+ }
+ break;
+ }
+ case GL_UNSIGNED_INT:
+ {
+ GLuint *pIdx = (GLuint *)indices;
+ min = max = pIdx[0];
+ for (i=0; i<count; ++i)
+ {
+ if (pIdx[i]<min) min = pIdx[i];
+ else if (pIdx[i]>max) max = pIdx[i];
+ }
+ break;
+ }
+ default: crError("Unknown type 0x%x", type);
+ }
+
+ if ((max-min)<(GLuint)(2*count))
+ {
+ crStateLockArraysEXT(min, max-min+1);
+
+ serverArrays = crStateUseServerArrays();
+ if (serverArrays)
+ {
+ lockedArrays = GL_TRUE;
+ }
+ else
+ {
+ crStateUnlockArraysEXT();
+ }
+ }
+ }
+# endif
+#endif
+
+ if (serverArrays
+#ifdef CR_FORCE_ZVA_EXPAND
+ && !cZvaValues
+#endif
+ ) {
+ CR_ZVA_RESTORE_CTX RestoreCtx;
+ GET_CONTEXT(ctx);
+ CRClientState *clientState = &(ctx->clientState->client);
+
+ Assert(cZvaValues < UINT32_MAX/2);
+
+ if (cZvaValues)
+ packspuZvaEnable(ctx, aAttrib, cZvaValues, &RestoreCtx);
+
+ /*Note the comment in packspu_LockArraysEXT*/
+ if (clientState->array.locked && !clientState->array.synced)
+ {
+ crPackLockArraysEXT(clientState->array.lockFirst, clientState->array.lockCount);
+ clientState->array.synced = GL_TRUE;
+ }
+
+ /* Send the DrawArrays command over the wire */
+ if (pack_spu.swap)
+ crPackDrawElementsSWAP( mode, count, type, indices );
+ else
+ crPackDrawElements( mode, count, type, indices );
+
+ if (cZvaValues)
+ packspuZvaDisable(&RestoreCtx);
+ }
+ else {
+ /* evaluate locally */
+ GET_CONTEXT(ctx);
+ CRClientState *clientState = &(ctx->clientState->client);
+
+#ifdef CR_FORCE_ZVA_SERVER_ARRAY
+ CR_ZVA_RESTORE_CTX RestoreCtx;
+
+ if (cZvaValues && cZvaValues < UINT32_MAX/2)
+ packspuZvaEnable(ctx, aAttrib, cZvaValues, &RestoreCtx);
+#endif
+
+ if (pack_spu.swap)
+ crPackExpandDrawElementsSWAP( mode, count, type, indices, clientState, cZvaValues ? aAttrib : NULL );
+ else
+ {
+ //packspu_Begin(mode);
+ crPackExpandDrawElements( mode, count, type, indices, clientState, cZvaValues ? aAttrib : NULL );
+ //packspu_End();
+ }
+
+#ifdef CR_FORCE_ZVA_SERVER_ARRAY
+ if (cZvaValues && cZvaValues < UINT32_MAX/2)
+ packspuZvaDisable(&RestoreCtx);
+#endif
+ }
+
+#if CR_ARB_vertex_buffer_object
+ if (lockedArrays)
+ {
+ packspu_UnlockArraysEXT();
+ }
+#endif
+}
+
+
+void PACKSPU_APIENTRY
+packspu_DrawRangeElements( GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices )
+{
+ GLboolean serverArrays = GL_FALSE;
+ GLuint cZvaValues = 0;
+ GLfloat aAttrib[4];
+
+#if CR_ARB_vertex_buffer_object
+ {
+ GET_CONTEXT(ctx);
+ /*crDebug("DrawRangeElements count=%d", count);*/
+ if (ctx->clientState->extensions.ARB_vertex_buffer_object)
+ {
+ serverArrays = crStateUseServerArrays();
+ if (ctx->fCheckZerroVertAttr)
+ cZvaValues = crStateNeedDummyZeroVertexArray(thread->currentContext->clientState, &thread->packer->current, aAttrib);
+ }
+ }
+#endif
+
+ if (serverArrays
+#ifdef CR_FORCE_ZVA_EXPAND
+ && !cZvaValues
+#endif
+ ) {
+ CR_ZVA_RESTORE_CTX RestoreCtx;
+ GET_CONTEXT(ctx);
+ CRClientState *clientState = &(ctx->clientState->client);
+
+ Assert(cZvaValues < UINT32_MAX/2);
+
+ if (cZvaValues)
+ packspuZvaEnable(ctx, aAttrib, cZvaValues, &RestoreCtx);
+
+ /*Note the comment in packspu_LockArraysEXT*/
+ if (clientState->array.locked && !clientState->array.synced)
+ {
+ crPackLockArraysEXT(clientState->array.lockFirst, clientState->array.lockCount);
+ clientState->array.synced = GL_TRUE;
+ }
+
+ /* Send the DrawRangeElements command over the wire */
+ if (pack_spu.swap)
+ crPackDrawRangeElementsSWAP( mode, start, end, count, type, indices );
+ else
+ crPackDrawRangeElements( mode, start, end, count, type, indices );
+
+ if (cZvaValues)
+ packspuZvaDisable(&RestoreCtx);
+ }
+ else {
+ /* evaluate locally */
+ GET_CONTEXT(ctx);
+ CRClientState *clientState = &(ctx->clientState->client);
+#ifdef CR_FORCE_ZVA_SERVER_ARRAY
+ CR_ZVA_RESTORE_CTX RestoreCtx;
+
+ if (cZvaValues && cZvaValues < UINT32_MAX/2)
+ packspuZvaEnable(ctx, aAttrib, cZvaValues, &RestoreCtx);
+#endif
+
+ if (pack_spu.swap)
+ crPackExpandDrawRangeElementsSWAP( mode, start, end, count, type, indices, clientState, cZvaValues ? aAttrib : NULL );
+ else
+ {
+ crPackExpandDrawRangeElements( mode, start, end, count, type, indices, clientState, cZvaValues ? aAttrib : NULL );
+ }
+
+#ifdef CR_FORCE_ZVA_SERVER_ARRAY
+ if (cZvaValues && cZvaValues < UINT32_MAX/2)
+ packspuZvaDisable(&RestoreCtx);
+#endif
+ }
+}
+
+
+void PACKSPU_APIENTRY
+packspu_DrawArrays( GLenum mode, GLint first, GLsizei count )
+{
+ GLboolean serverArrays = GL_FALSE;
+ GLuint cZvaValues = 0;
+ GLfloat aAttrib[4];
+
+#if CR_ARB_vertex_buffer_object
+ GLboolean lockedArrays = GL_FALSE;
+ {
+ GET_CONTEXT(ctx);
+ /*crDebug("DrawArrays count=%d", count);*/
+ if (ctx->clientState->extensions.ARB_vertex_buffer_object)
+ {
+ serverArrays = crStateUseServerArrays();
+ if (ctx->fCheckZerroVertAttr)
+ cZvaValues = crStateNeedDummyZeroVertexArray(thread->currentContext->clientState, &thread->packer->current, aAttrib);
+ }
+ }
+
+# ifdef CR_USE_LOCKARRAYS
+ if (!serverArrays && !ctx->clientState->client.array.locked && (count>3))
+ {
+ crStateLockArraysEXT(first, count);
+ serverArrays = crStateUseServerArrays();
+ if (serverArrays)
+ {
+ lockedArrays = GL_TRUE;
+ }
+ else
+ {
+ crStateUnlockArraysEXT();
+ }
+ }
+# endif
+#endif
+
+ if (serverArrays
+#ifdef CR_FORCE_ZVA_EXPAND
+ && !cZvaValues
+#endif
+ )
+ {
+ CR_ZVA_RESTORE_CTX RestoreCtx;
+ GET_CONTEXT(ctx);
+ CRClientState *clientState = &(ctx->clientState->client);
+
+ Assert(cZvaValues < UINT32_MAX/2);
+
+ if (cZvaValues)
+ packspuZvaEnable(ctx, aAttrib, cZvaValues, &RestoreCtx);
+
+ /*Note the comment in packspu_LockArraysEXT*/
+ if (clientState->array.locked && !clientState->array.synced)
+ {
+ crPackLockArraysEXT(clientState->array.lockFirst, clientState->array.lockCount);
+ clientState->array.synced = GL_TRUE;
+ }
+
+ /* Send the DrawArrays command over the wire */
+ if (pack_spu.swap)
+ crPackDrawArraysSWAP( mode, first, count );
+ else
+ crPackDrawArrays( mode, first, count );
+
+ if (cZvaValues)
+ packspuZvaDisable(&RestoreCtx);
+ }
+ else
+ {
+ /* evaluate locally */
+ GET_CONTEXT(ctx);
+ CRClientState *clientState = &(ctx->clientState->client);
+#ifdef CR_FORCE_ZVA_SERVER_ARRAY
+ CR_ZVA_RESTORE_CTX RestoreCtx;
+
+ if (cZvaValues && cZvaValues < UINT32_MAX/2)
+ packspuZvaEnable(ctx, aAttrib, cZvaValues, &RestoreCtx);
+#endif
+
+ if (pack_spu.swap)
+ crPackExpandDrawArraysSWAP( mode, first, count, clientState, cZvaValues ? aAttrib : NULL );
+ else
+ crPackExpandDrawArrays( mode, first, count, clientState, cZvaValues ? aAttrib : NULL );
+
+#ifdef CR_FORCE_ZVA_SERVER_ARRAY
+ if (cZvaValues && cZvaValues < UINT32_MAX/2)
+ packspuZvaDisable(&RestoreCtx);
+#endif
+
+ }
+
+#if CR_ARB_vertex_buffer_object
+ if (lockedArrays)
+ {
+ packspu_UnlockArraysEXT();
+ }
+#endif
+}
+
+
+#ifdef CR_EXT_multi_draw_arrays
+void PACKSPU_APIENTRY packspu_MultiDrawArraysEXT( GLenum mode, GLint *first, GLsizei *count, GLsizei primcount )
+{
+ GLint i;
+ for (i = 0; i < primcount; i++) {
+ if (count[i] > 0) {
+ packspu_DrawArrays(mode, first[i], count[i]);
+ }
+ }
+}
+
+void PACKSPU_APIENTRY packspu_MultiDrawElementsEXT( GLenum mode, const GLsizei *count, GLenum type, const GLvoid **indices, GLsizei primcount )
+{
+ GLint i;
+ for (i = 0; i < primcount; i++) {
+ if (count[i] > 0) {
+ packspu_DrawElements(mode, count[i], type, indices[i]);
+ }
+ }
+}
+#endif
+
+
+void PACKSPU_APIENTRY packspu_EnableClientState( GLenum array )
+{
+ crStateEnableClientState(array);
+ crPackEnableClientState(array);
+}
+
+void PACKSPU_APIENTRY packspu_DisableClientState( GLenum array )
+{
+ crStateDisableClientState(array);
+ crPackDisableClientState(array);
+}
+
+void PACKSPU_APIENTRY packspu_ClientActiveTextureARB( GLenum texUnit )
+{
+ crStateClientActiveTextureARB(texUnit);
+ crPackClientActiveTextureARB(texUnit);
+}
+
+void PACKSPU_APIENTRY packspu_EnableVertexAttribArrayARB(GLuint index)
+{
+ crStateEnableVertexAttribArrayARB(index);
+ crPackEnableVertexAttribArrayARB(index);
+}
+
+
+void PACKSPU_APIENTRY packspu_DisableVertexAttribArrayARB(GLuint index)
+{
+ crStateDisableVertexAttribArrayARB(index);
+ crPackDisableVertexAttribArrayARB(index);
+}
+
+void PACKSPU_APIENTRY packspu_Enable( GLenum cap )
+{
+ if (cap!=GL_LIGHT_MODEL_TWO_SIDE)
+ {
+ crStateEnable(cap);
+
+ if (pack_spu.swap)
+ crPackEnableSWAP(cap);
+ else
+ crPackEnable(cap);
+ }
+ else
+ {
+ static int g_glmts1_warn=0;
+ if (!g_glmts1_warn)
+ {
+ crWarning("glEnable(GL_LIGHT_MODEL_TWO_SIDE) converted to valid glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,1)");
+ g_glmts1_warn=1;
+ }
+ crStateLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
+ crPackLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 1);
+ }
+}
+
+
+void PACKSPU_APIENTRY packspu_Disable( GLenum cap )
+{
+ if (cap!=GL_LIGHT_MODEL_TWO_SIDE)
+ {
+ crStateDisable(cap);
+
+ if (pack_spu.swap)
+ crPackDisableSWAP(cap);
+ else
+ crPackDisable(cap);
+ }
+ else
+ {
+ static int g_glmts0_warn=0;
+ if (!g_glmts0_warn)
+ {
+ crWarning("glDisable(GL_LIGHT_MODEL_TWO_SIDE) converted to valid glLightModeli(GL_LIGHT_MODEL_TWO_SIDE,0)");
+ g_glmts0_warn=1;
+ }
+ crStateLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
+ crPackLightModeli(GL_LIGHT_MODEL_TWO_SIDE, 0);
+ }
+}
+
+GLboolean PACKSPU_APIENTRY packspu_IsEnabled(GLenum cap)
+{
+ GLboolean res = crStateIsEnabled(cap);
+#ifdef DEBUG
+ {
+ GET_THREAD(thread);
+ int writeback = 1;
+ GLboolean return_val = (GLboolean) 0;
+ crPackIsEnabled(cap, &return_val, &writeback);
+ packspuFlush( (void *) thread );
+ CRPACKSPU_WRITEBACK_WAIT(thread, writeback);
+ CRASSERT(return_val==res);
+ }
+#endif
+
+ return res;
+}
+
+void PACKSPU_APIENTRY packspu_PushClientAttrib( GLbitfield mask )
+{
+ crStatePushClientAttrib(mask);
+ crPackPushClientAttrib(mask);
+}
+
+void PACKSPU_APIENTRY packspu_PopClientAttrib( void )
+{
+ crStatePopClientAttrib();
+ crPackPopClientAttrib();
+}
+
+void PACKSPU_APIENTRY packspu_LockArraysEXT(GLint first, GLint count)
+{
+ if (first>=0 && count>0)
+ {
+ crStateLockArraysEXT(first, count);
+ /*Note: this is a workaround for quake3 based apps.
+ It's modifying vertex data between glLockArraysEXT and glDrawElements calls,
+ so we'd pass data to host right before the glDrawSomething or glBegin call.
+ */
+ /*crPackLockArraysEXT(first, count);*/
+ }
+ else crDebug("Ignoring packspu_LockArraysEXT: first:%i, count:%i", first, count);
+}
+
+void PACKSPU_APIENTRY packspu_UnlockArraysEXT()
+{
+ GET_CONTEXT(ctx);
+ CRClientState *clientState = &(ctx->clientState->client);
+
+ if (clientState->array.locked && clientState->array.synced)
+ {
+ crPackUnlockArraysEXT();
+ }
+
+ crStateUnlockArraysEXT();
+}