-/* $Id: t_imm_fixup.c,v 1.2 2000/12/28 22:11:05 keithw Exp $ */
+/* $Id: t_imm_fixup.c,v 1.20 2001/06/04 16:09:28 keithw Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.5
*
- * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
+ * Copyright (C) 1999-2001 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
/*
* Authors:
- * Keith Whitwell <keithw@valinux.com>
+ * Keith Whitwell <keithw@valinux.com>
*/
#include "context.h"
#include "enums.h"
#include "dlist.h"
+#include "colormac.h"
+#include "light.h"
#include "macros.h"
#include "mem.h"
#include "mmath.h"
#include "state.h"
-#include "texture.h"
#include "mtypes.h"
#include "math/m_matrix.h"
#include "t_context.h"
#include "t_imm_alloc.h"
#include "t_imm_debug.h"
+#include "t_imm_elt.h"
#include "t_imm_fixup.h"
#include "t_pipeline.h"
+static const GLuint increment[GL_POLYGON+2] = { 1,2,1,1,3,1,1,4,2,1,1 };
+static const GLuint intro[GL_POLYGON+2] = { 0,0,2,2,0,2,2,0,2,2,0 };
-static void
-fixup_4f( GLfloat data[][4], GLuint flag[], GLuint start, GLuint match )
+void
+_tnl_fixup_4f( GLfloat data[][4], GLuint flag[], GLuint start, GLuint match )
{
GLuint i = start;
}
}
-static void
-fixup_3f( float data[][3], GLuint flag[], GLuint start, GLuint match )
+void
+_tnl_fixup_3f( float data[][3], GLuint flag[], GLuint start, GLuint match )
{
GLuint i = start;
}
-static void
-fixup_1ui( GLuint *data, GLuint flag[], GLuint start, GLuint match )
+void
+_tnl_fixup_1ui( GLuint *data, GLuint flag[], GLuint start, GLuint match )
{
GLuint i = start;
}
-static void
-fixup_1f( GLfloat *data, GLuint flag[], GLuint start, GLuint match )
+void
+_tnl_fixup_1f( GLfloat *data, GLuint flag[], GLuint start, GLuint match )
{
GLuint i = start;
flag[i] |= match;
}
-static void
-fixup_1ub( GLubyte *data, GLuint flag[], GLuint start, GLuint match )
+void
+_tnl_fixup_1ub( GLubyte *data, GLuint flag[], GLuint start, GLuint match )
{
GLuint i = start;
}
-static void
-fixup_4ub( GLubyte data[][4], GLuint flag[], GLuint start, GLuint match )
-{
- GLuint i = start;
-
- for (;;) {
- if ((flag[++i] & match) == 0) {
- COPY_4UBV(data[i], data[i-1]);
- if (flag[i] & VERT_END_VB) break;
- }
- }
- flag[i] |= match;
-}
-
-
static void
fixup_first_4f( GLfloat data[][4], GLuint flag[], GLuint match,
GLuint start, GLfloat *dflt )
}
-static void
-fixup_first_4ub( GLubyte data[][4], GLuint flag[], GLuint match,
- GLuint start, GLubyte dflt[4] )
-{
- GLuint i = start-1;
- match |= VERT_END_VB;
-
- while ((flag[++i]&match) == 0)
- COPY_4UBV(data[i], dflt);
-}
-
-
void _tnl_fixup_input( GLcontext *ctx, struct immediate *IM )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
fixup = ~andflag & VERT_FIXUP;
- if (!ctx->CompileFlag)
+ if (!ctx->CompileFlag)
fixup &= tnl->pipeline.inputs;
if (!ctx->ExecuteFlag)
if (fixup) {
GLuint copy = fixup & ~IM->Flag[start];
-
+
/* Equivalent to a lazy copy-from-current when setting up the
* immediate.
*/
if (ctx->ExecuteFlag && copy) {
-/* _tnl_print_vert_flags("copy from current", copy); */
+
+ if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
+ _tnl_print_vert_flags("copy from current", copy);
if (copy & VERT_NORM) {
COPY_3V( IM->Normal[start], ctx->Current.Normal );
}
if (copy & VERT_RGBA) {
- COPY_4UBV( IM->Color[start], ctx->Current.Color);
+ COPY_4FV( IM->Color[start], ctx->Current.Color);
}
if (copy & VERT_SPEC_RGB)
- COPY_4UBV( IM->SecondaryColor[start], ctx->Current.SecondaryColor);
+ COPY_4FV( IM->SecondaryColor[start], ctx->Current.SecondaryColor);
if (copy & VERT_FOG_COORD)
IM->FogCoord[start] = ctx->Current.FogCoord;
if (copy & VERT_INDEX)
IM->Index[start] = ctx->Current.Index;
-
+
if (copy & VERT_EDGE)
IM->EdgeFlag[start] = ctx->Current.EdgeFlag;
}
if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
-/* _tnl_print_vert_flags("fixup", fixup); */
+ _tnl_print_vert_flags("fixup", fixup);
if (fixup & VERT_TEX_ANY) {
GLuint i;
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
if (fixup & VERT_TEX(i)) {
- if (orflag & VERT_TEX(i))
- fixup_4f( IM->TexCoord[i], IM->Flag, start, VERT_TEX(i) );
+ if (orflag & VERT_TEX(i))
+ _tnl_fixup_4f( IM->TexCoord[i], IM->Flag, start,
+ VERT_TEX(i) );
else
fixup_first_4f( IM->TexCoord[i], IM->Flag, VERT_END_VB, start,
IM->TexCoord[i][start]);
}
}
}
- }
-
- if (fixup & VERT_EDGE) {
- if (orflag & VERT_EDGE)
- fixup_1ub( IM->EdgeFlag, IM->Flag, start, VERT_EDGE );
- else
- fixup_first_1ub( IM->EdgeFlag, IM->Flag, VERT_END_VB, start,
- IM->EdgeFlag[start] );
- }
-
- if (fixup & VERT_INDEX) {
- if (orflag & VERT_INDEX)
- fixup_1ui( IM->Index, IM->Flag, start, VERT_INDEX );
- else
- fixup_first_1ui( IM->Index, IM->Flag, VERT_END_VB, start, IM->Index[start] );
- }
+
- if (fixup & VERT_RGBA) {
- if (orflag & VERT_RGBA)
- fixup_4ub( IM->Color, IM->Flag, start, VERT_RGBA );
- else
- fixup_first_4ub( IM->Color, IM->Flag, VERT_END_VB, start, IM->Color[start] );
- }
+ if (fixup & VERT_EDGE) {
+ if (orflag & VERT_EDGE)
+ _tnl_fixup_1ub( IM->EdgeFlag, IM->Flag, start, VERT_EDGE );
+ else
+ fixup_first_1ub( IM->EdgeFlag, IM->Flag, VERT_END_VB, start,
+ IM->EdgeFlag[start] );
+ }
- if (fixup & VERT_SPEC_RGB) {
- if (orflag & VERT_SPEC_RGB)
- fixup_4ub( IM->SecondaryColor, IM->Flag, start, VERT_SPEC_RGB );
- else
- fixup_first_4ub( IM->SecondaryColor, IM->Flag, VERT_END_VB, start,
- IM->SecondaryColor[start] );
- }
+ if (fixup & VERT_INDEX) {
+ if (orflag & VERT_INDEX)
+ _tnl_fixup_1ui( IM->Index, IM->Flag, start, VERT_INDEX );
+ else
+ fixup_first_1ui( IM->Index, IM->Flag, VERT_END_VB, start,
+ IM->Index[start] );
+ }
- if (fixup & VERT_FOG_COORD) {
- if (orflag & VERT_FOG_COORD)
- fixup_1f( IM->FogCoord, IM->Flag, start, VERT_FOG_COORD );
- else
- fixup_first_1f( IM->FogCoord, IM->Flag, VERT_END_VB, start,
- IM->FogCoord[start] );
- }
+ if (fixup & VERT_RGBA) {
+ if (orflag & VERT_RGBA)
+ _tnl_fixup_4f( IM->Color, IM->Flag, start, VERT_RGBA );
+ /* No need for else case as the drivers understand stride
+ * zero here. (TODO - propogate this)
+ */
+ }
+
+ if (fixup & VERT_SPEC_RGB) {
+ if (orflag & VERT_SPEC_RGB)
+ _tnl_fixup_4f( IM->SecondaryColor, IM->Flag, start,
+ VERT_SPEC_RGB );
+ else
+ fixup_first_4f( IM->SecondaryColor, IM->Flag, VERT_END_VB, start,
+ IM->SecondaryColor[start] );
+ }
+
+ if (fixup & VERT_FOG_COORD) {
+ if (orflag & VERT_FOG_COORD)
+ _tnl_fixup_1f( IM->FogCoord, IM->Flag, start, VERT_FOG_COORD );
+ else
+ fixup_first_1f( IM->FogCoord, IM->Flag, VERT_END_VB, start,
+ IM->FogCoord[start] );
+ }
- if (fixup & VERT_NORM) {
- if (orflag & VERT_NORM)
- fixup_3f( IM->Normal, IM->Flag, start, VERT_NORM );
- else
- fixup_first_3f( IM->Normal, IM->Flag, VERT_END_VB, start,
- IM->Normal[start] );
+ if (fixup & VERT_NORM) {
+ if (orflag & VERT_NORM)
+ _tnl_fixup_3f( IM->Normal, IM->Flag, start, VERT_NORM );
+ else
+ fixup_first_3f( IM->Normal, IM->Flag, VERT_END_VB, start,
+ IM->Normal[start] );
+ }
}
-
+
/* Prune possible half-filled slot.
*/
IM->Flag[IM->LastData+1] &= ~VERT_END_VB;
IM->Flag[IM->Count] |= VERT_END_VB;
+
+ /* Materials:
+ */
+ if (IM->MaterialOrMask & ~IM->MaterialAndMask) {
+ GLuint vulnerable = IM->MaterialOrMask;
+ GLuint i = IM->Start;
+
+ do {
+ while (!(IM->Flag[i] & VERT_MATERIAL))
+ i++;
+
+ vulnerable &= ~IM->MaterialMask[i];
+ _mesa_copy_material_pairs( IM->Material[i],
+ ctx->Light.Material,
+ vulnerable );
+
+
+ } while (vulnerable);
+ }
}
IMM_SIZE * 2 );
next->MaterialMask = (GLuint *) MALLOC( sizeof(GLuint) * IMM_SIZE );
}
-
- next->MaterialMask[dst] = prev->MaterialMask[src];
+
+ next->MaterialMask[dst] = prev->MaterialOrMask;
MEMCPY(next->Material[dst], prev->Material[src], 2*sizeof(GLmaterial));
}
+static GLboolean is_fan_like[GL_POLYGON+1] = {
+ GL_FALSE,
+ GL_FALSE,
+ GL_TRUE, /* line loop */
+ GL_FALSE,
+ GL_FALSE,
+ GL_FALSE,
+ GL_TRUE, /* tri fan */
+ GL_FALSE,
+ GL_FALSE,
+ GL_TRUE /* polygon */
+};
/* Copy the untransformed data from the shared vertices of a primitive
* primitives.
*
* Have to be careful with the transitions between display list
- * replay, compile and normal execute modes.
+ * replay, compile and normal execute modes.
*/
-static void copy_vertices( GLcontext *ctx,
- struct immediate *next,
- struct immediate *prev,
- GLuint count,
- GLuint *elts )
+void _tnl_copy_immediate_vertices( GLcontext *ctx, struct immediate *next )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct immediate *prev = tnl->ExecCopySource;
+ struct vertex_arrays *inputs = &tnl->imm_inputs;
+ GLuint count = tnl->ExecCopyCount;
+ GLuint *elts = tnl->ExecCopyElts;
GLuint offset = IMM_MAX_COPIED_VERTS - count;
GLuint i;
- next->CopyStart = next->Start - count;
-
- /* Copy the vertices
- */
- for (i = 0 ; i < count ; i++)
- {
- GLuint src = elts[i+offset];
- GLuint dst = next->CopyStart+i;
+ if (!prev) {
+ ASSERT(tnl->ExecCopyCount == 0);
+ return;
+ }
- COPY_4FV( next->Obj[dst], prev->Obj[src] );
- COPY_3FV( next->Normal[dst], prev->Normal[src] );
- COPY_4UBV( next->Color[dst], prev->Color[src] );
+ next->CopyStart = next->Start - count;
- if (prev->OrFlag & VERT_TEX_ANY) {
- GLuint i;
- for (i = 0 ; i < prev->MaxTextureUnits ; i++) {
- if (prev->OrFlag & VERT_TEX(i))
- COPY_4FV( next->TexCoord[i][dst], prev->TexCoord[i][src] );
- }
+ if ((prev->CopyOrFlag & VERT_DATA) == VERT_ELT &&
+ ctx->Array.LockCount &&
+ ctx->Array.Vertex.Enabled)
+ {
+ /* Copy Elt values only
+ */
+ for (i = 0 ; i < count ; i++)
+ {
+ GLuint src = elts[i+offset];
+ GLuint dst = next->CopyStart+i;
+ next->Elt[dst] = prev->Elt[src];
+ next->Flag[dst] = VERT_ELT;
}
-
- if (prev->Flag[src] & VERT_MATERIAL)
- copy_material(next, prev, dst, src);
-
- next->Elt[dst] = prev->Elt[src];
- next->EdgeFlag[dst] = prev->EdgeFlag[src];
- next->Index[dst] = prev->Index[src];
- COPY_4UBV( next->SecondaryColor[dst], prev->SecondaryColor[src] );
- next->FogCoord[dst] = prev->FogCoord[src];
- next->Flag[dst] = (prev->CopyOrFlag & VERT_FIXUP);
- next->CopyOrFlag |= prev->Flag[src]; /* redundant for current_im */
- next->CopyAndFlag &= prev->Flag[src]; /* redundant for current_im */
+ next->CopyOrFlag |= VERT_ELT;
+ next->CopyAndFlag &= VERT_ELT;
}
-
- /* Only needed when copying to a compiled cassette
- */
- if (next->NormalLengths) {
+ else {
+ /* prev->CopyOrFlag is hacked to include values generated by eval:
+ */
+ GLuint copy = tnl->pipeline.inputs & prev->CopyOrFlag;
+ GLuint flag;
+
+ if (is_fan_like[ctx->Driver.CurrentExecPrimitive]) {
+ next->TexSize |= tnl->ExecCopyTexSize;
+ next->CopyOrFlag |= (prev->CopyOrFlag & VERT_FIXUP);
+ next->CopyAndFlag &= (prev->CopyOrFlag & VERT_FIXUP);
+ flag = (prev->CopyOrFlag & VERT_FIXUP);
+ }
+ else {
+ /* Don't let an early 'glColor', etc. poison the elt path.
+ */
+ next->CopyAndFlag &= (prev->OrFlag & VERT_FIXUP);
+ flag = (prev->OrFlag & VERT_FIXUP);
+ }
+
+
+ /* Copy whole vertices
+ */
for (i = 0 ; i < count ; i++)
{
GLuint src = elts[i+offset];
+ GLuint isrc = src - prev->CopyStart;
GLuint dst = next->CopyStart+i;
- if (prev->NormalLengths)
- next->NormalLengths[dst] = prev->NormalLengths[src];
- else
- next->NormalLengths[dst] = 1.0/LEN_3FV(prev->Normal[src]);
- }
- }
+ /* Values subject to eval must be copied out of the 'inputs'
+ * struct. (Copied rows should not be evaluated twice).
+ *
+ * Note these pointers are null when inactive.
+ */
+ COPY_4FV( next->Obj[dst], inputs->Obj.data[isrc] );
- ASSERT(prev == tnl->ExecCopySource);
+ if (copy & VERT_NORM)
+ COPY_3FV( next->Normal[dst], inputs->Normal.data[isrc] );
-/* fprintf(stderr, "%s id %d refcount %d\n", __FUNCTION__, */
-/* tnl->ExecCopySource->id, tnl->ExecCopySource->ref_count-1); */
+ if (copy & VERT_RGBA)
+ COPY_4FV( next->Color[dst],
+ ((GLfloat (*)[4])inputs->Color.Ptr)[isrc] );
- if (--tnl->ExecCopySource->ref_count == 0)
- _tnl_free_immediate( tnl->ExecCopySource );
-
- next->ref_count++;
- tnl->ExecCopySource = next;
-/* fprintf(stderr, "%s id %d refcount %d\n", __FUNCTION__, */
-/* next->id, next->ref_count); */
- tnl->ExecCopyElts[0] = next->Start-3;
- tnl->ExecCopyElts[1] = next->Start-2;
- tnl->ExecCopyElts[2] = next->Start-1;
-}
+ if (copy & VERT_INDEX)
+ next->Index[dst] = inputs->Index.data[isrc];
-/* Copy vertices to an empty immediate struct.
- */
-void _tnl_copy_immediate_vertices( GLcontext *ctx, struct immediate *IM )
-{
- TNLcontext *tnl = TNL_CONTEXT(ctx);
+ if (copy & VERT_TEX_ANY) {
+ GLuint i;
+ for (i = 0 ; i < prev->MaxTextureUnits ; i++) {
+ if (copy & VERT_TEX(i))
+ COPY_4FV( next->TexCoord[i][dst],
+ inputs->TexCoord[i].data[isrc] );
+ }
+ }
- ASSERT(IM == TNL_CURRENT_IM(ctx));
- ASSERT(IM->Count == IM->Start);
+ /* Remaining values should be the same in the 'input' struct and the
+ * original immediate.
+ */
+ if (copy & (VERT_ELT|VERT_EDGE|VERT_SPEC_RGB|VERT_FOG_COORD|
+ VERT_MATERIAL)) {
- /* Need to push this in now as it won't be computed anywhere else/
- */
- IM->TexSize = tnl->ExecCopyTexSize;
-
- /* A wrapped primitive. We may be copying into a revived
- * display list immediate, or onto the front of a new execute-mode
- * immediate.
- */
- copy_vertices( ctx, IM,
- tnl->ExecCopySource,
- tnl->ExecCopyCount,
- tnl->ExecCopyElts );
-
- if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
- /* Immediates are built by default to be correct in this state,
- * and copying to the first slots of an immediate doesn't remove
- * this property.
- */
- ASSERT(tnl->ExecCopyTexSize == 0);
- ASSERT(tnl->ExecCopyCount == 0);
- ASSERT(IM->CopyStart == IM->Start);
+ if (prev->Flag[src] & VERT_MATERIAL)
+ copy_material(next, prev, dst, src);
+
+ next->Elt[dst] = prev->Elt[src];
+ next->EdgeFlag[dst] = prev->EdgeFlag[src];
+ COPY_4FV( next->SecondaryColor[dst], prev->SecondaryColor[src] );
+ next->FogCoord[dst] = prev->FogCoord[src];
+ }
+
+ next->Flag[dst] = flag;
+ next->OrFlag |= prev->Flag[src]; /* for non-fanlike prims,
+ otherwise redundant */
+ }
}
- /* Copy the primitive information:
- */
- IM->Primitive[IM->CopyStart] = (ctx->Driver.CurrentExecPrimitive | PRIM_LAST);
- IM->LastPrimitive = IM->CopyStart;
- if (tnl->ExecParity)
- IM->Primitive[IM->CopyStart] |= PRIM_PARITY;
+ if (--tnl->ExecCopySource->ref_count == 0)
+ _tnl_free_immediate( tnl->ExecCopySource );
+
+ tnl->ExecCopySource = 0;
+ tnl->ExecCopyCount = 0;
}
-
+
/* Revive a compiled immediate struct - propogate new 'Current'
* values. Often this is redundant because the current values were
if (count == start)
return;
- IM->CopyOrFlag = IM->OrFlag; /* redundant for current_im */
- IM->CopyAndFlag = IM->AndFlag; /* redundant for current_im */
+ IM->CopyOrFlag = IM->OrFlag;
+ IM->CopyAndFlag = IM->AndFlag;
IM->CopyTexSize = IM->TexSize | tnl->ExecCopyTexSize;
- copy_vertices( ctx, IM,
- tnl->ExecCopySource,
- tnl->ExecCopyCount,
- tnl->ExecCopyElts );
+ _tnl_copy_immediate_vertices( ctx, IM );
if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
- ASSERT(tnl->ExecCopyTexSize == 0);
- ASSERT(tnl->ExecCopyCount == 0);
ASSERT(IM->CopyStart == IM->Start);
}
+ /* Naked array elements can be copied into the first cassette in a
+ * display list. Need to translate them away:
+ */
+ if (IM->CopyOrFlag & VERT_ELT) {
+ ASSERT(IM->CopyStart < IM->Start);
+ _tnl_translate_array_elts( ctx, IM, IM->CopyStart, IM->Start );
+ }
+
fixup = tnl->pipeline.inputs & ~IM->Flag[start] & VERT_FIXUP;
if (fixup) {
ctx->Current.Index );
if (fixup & VERT_RGBA)
- fixup_first_4ub(IM->Color, IM->Flag, VERT_RGBA, start,
- ctx->Current.Color );
+ if (IM->CopyOrFlag & VERT_RGBA)
+ fixup_first_4f(IM->Color, IM->Flag, VERT_RGBA, start,
+ ctx->Current.Color );
if (fixup & VERT_SPEC_RGB)
- fixup_first_4ub(IM->SecondaryColor, IM->Flag, VERT_SPEC_RGB, start,
- ctx->Current.SecondaryColor );
+ fixup_first_4f(IM->SecondaryColor, IM->Flag, VERT_SPEC_RGB, start,
+ ctx->Current.SecondaryColor );
if (fixup & VERT_FOG_COORD)
fixup_first_1f(IM->FogCoord, IM->Flag, VERT_FOG_COORD, start,
if (fixup & VERT_NORM) {
fixup_first_3f(IM->Normal, IM->Flag, VERT_NORM, start,
ctx->Current.Normal );
- if (IM->NormalLengths)
- fixup_first_1f(IM->NormalLengths, IM->Flag, VERT_NORM, start,
- 1.0F / (GLfloat) LEN_3FV(ctx->Current.Normal) );
}
}
-
- /* Can potentially overwrite primitive details - need to save the
- * first slot:
+ /* Materials:
*/
- tnl->DlistPrimitive = IM->Primitive[IM->Start];
- tnl->DlistPrimitiveLength = IM->PrimitiveLength[IM->Start];
- tnl->DlistLastPrimitive = IM->LastPrimitive;
-
- /* The first primitive may be different from what was recorded in
- * the immediate struct. Consider an immediate that starts with a
- * glBegin, compiled in a display list, which is called from within
- * an existing Begin/End object.
- */
- if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
- GLuint i;
+ if (IM->MaterialOrMask & ~IM->MaterialAndMask) {
+ GLuint vulnerable = IM->MaterialOrMask;
+ GLuint i = IM->Start;
- if (IM->BeginState & VERT_ERROR_1)
- gl_error( ctx, GL_INVALID_OPERATION, "begin/end");
+ do {
+ while (!(IM->Flag[i] & VERT_MATERIAL))
+ i++;
- for (i = IM->Start ; i <= IM->Count ; i += IM->PrimitiveLength[i])
- if (IM->Flag[i] & (VERT_BEGIN|VERT_END_VB))
- break;
+ vulnerable &= ~IM->MaterialMask[i];
+ _mesa_copy_material_pairs( IM->Material[i],
+ ctx->Light.Material,
+ vulnerable );
- /* Would like to just ignore vertices upto this point. Can't
- * set copystart because it might skip materials?
- */
- ASSERT(IM->Start == IM->CopyStart);
- if (i > IM->CopyStart) {
- IM->Primitive[IM->CopyStart] = GL_POLYGON+1;
- IM->PrimitiveLength[IM->CopyStart] = i - IM->CopyStart;
- if (IM->Flag[i] & VERT_END_VB) {
- IM->Primitive[IM->CopyStart] |= PRIM_LAST;
- IM->LastPrimitive = IM->CopyStart;
- }
- }
- /* Shouldn't immediates be set up to have this structure *by default*?
- */
- } else {
- GLuint i;
- if (IM->BeginState & VERT_ERROR_0)
- gl_error( ctx, GL_INVALID_OPERATION, "begin/end");
-
- if (IM->CopyStart == IM->Start &&
- IM->Flag[IM->Start] & (VERT_END|VERT_END_VB))
- {
- }
- else
- {
- IM->Primitive[IM->CopyStart] = ctx->Driver.CurrentExecPrimitive;
- if (tnl->ExecParity)
- IM->Primitive[IM->CopyStart] |= PRIM_PARITY;
-
-
- for (i = IM->Start ; i <= IM->Count ; i += IM->PrimitiveLength[i])
- if (IM->Flag[i] & (VERT_END|VERT_END_VB)) {
- IM->PrimitiveLength[IM->CopyStart] = i - IM->CopyStart;
- if (IM->Flag[i] & VERT_END_VB) {
- IM->Primitive[IM->CopyStart] |= PRIM_LAST;
- IM->LastPrimitive = IM->CopyStart;
- }
- if (IM->Flag[i] & VERT_END) {
- IM->Primitive[IM->CopyStart] |= PRIM_END;
- }
- break;
- }
- }
+ } while (vulnerable);
}
-
- if (IM->Primitive[IM->LastPrimitive] & PRIM_END)
- ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1;
- else
- ctx->Driver.CurrentExecPrimitive =
- IM->Primitive[IM->LastPrimitive] & PRIM_MODE_MASK;
}
-/* Undo any changes potentially made to the immediate in the range
- * IM->Start..IM->Count above.
- */
-void _tnl_restore_compiled_cassette( GLcontext *ctx, struct immediate *IM )
-{
- TNLcontext *tnl = TNL_CONTEXT(ctx);
- IM->Primitive[IM->Start] = tnl->DlistPrimitive;
- IM->PrimitiveLength[IM->Start] = tnl->DlistPrimitiveLength;
-}
-
-
static void copy_none( TNLcontext *tnl, GLuint start, GLuint count, GLuint ovf)
{
-/* Figure out what vertices need to be copied next time.
+/* Figure out what vertices need to be copied next time.
*/
void
_tnl_get_exec_copy_verts( GLcontext *ctx, struct immediate *IM )
{
- static const GLuint increment[GL_POLYGON+2] = { 1,2,1,1,3,1,1,4,2,1,1 };
- static const GLuint intro[GL_POLYGON+2] = { 0,0,2,2,0,2,2,0,2,2,0 };
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint last = IM->LastPrimitive;
GLuint pincr = increment[prim];
GLuint pintro = intro[prim];
GLuint ovf = 0;
-
- if (tnl->ExecCopySource != IM) {
-/* fprintf(stderr, "%s id %d refcount %d\n", __FUNCTION__, */
-/* tnl->ExecCopySource->id, tnl->ExecCopySource->ref_count-1); */
- if (--tnl->ExecCopySource->ref_count == 0)
- _tnl_free_immediate( tnl->ExecCopySource );
- IM->ref_count++;
- tnl->ExecCopySource = IM;
-/* fprintf(stderr, "%s id %d refcount %d\n", __FUNCTION__, */
-/* tnl->ExecCopySource->id, tnl->ExecCopySource->ref_count); */
- }
+/* fprintf(stderr, "_tnl_get_exec_copy_verts %s\n", */
+/* _mesa_lookup_enum_by_nr(prim)); */
+
+ ASSERT(tnl->ExecCopySource == 0);
if (prim == GL_POLYGON+1) {
tnl->ExecCopyCount = 0;
tnl->ExecCopyTexSize = 0;
tnl->ExecParity = 0;
} else {
+ /* Remember this immediate as the one to copy from.
+ */
+ IM->ref_count++;
+ tnl->ExecCopySource = IM;
tnl->ExecCopyCount = 0;
tnl->ExecCopyTexSize = IM->CopyTexSize;
tnl->ExecParity = IM->PrimitiveLength[IM->LastPrimitive] & 1;
if (pincr != 1 && (IM->Count - last - pintro))
ovf = (IM->Count - last - pintro) % pincr;
-
+
if (last < IM->Count)
copy_tab[prim]( tnl, last, IM->Count, ovf );
}
}
-/* If we receive evalcoords in an immediate struct for maps which
- * don't have a vertex enabled, need to do an additional fixup, as
- * those rows containing evalcoords must now be ignored. The
- * evalcoords may still generate colors, normals, etc, so have to
- * respect the relative order between calls to EvalCoord and Normal
- * etc.
- *
- * Generate the index list that will be used to render this immediate
- * struct.
- *
- * Finally, generate a new primitives list for rendering the indices.
+/* Recalculate ExecCopyElts, ExecParity, etc.
*/
-#if 0
-void _tnl_fixup_purged_eval( GLcontext *ctx,
- GLuint fixup, GLuint purge )
+void
+_tnl_get_purged_copy_verts( GLcontext *ctx, struct immediate *IM )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
- struct tnl_eval_store *store = &tnl->eval;
- GLuint *flags = tnl->vb.Flag;
- GLuint i, j, nextprim;
- GLuint fixup_fence = purge|VERT_OBJ;
- GLuint good_index = (VERT_EVAL_ANY & ~purge)|VERT_OBJ;
- GLuint prim_length = 0, lastprim = 0, nextprim = 0;
- if (fixup & VERT_TEX0)
- fixup_4f( store->TexCoord, flags, 0, VERT_TEX0|fixup_fence );
+ if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) {
+ GLuint last = IM->LastPrimitive;
+ GLenum prim = IM->Primitive[last];
+ GLuint pincr = increment[prim];
+ GLuint pintro = intro[prim];
+ GLuint ovf = 0, i;
- if (fixup & VERT_INDEX)
- fixup_1ui( store->Index, flags, 0, VERT_INDEX|fixup_fence );
+ tnl->ExecCopyCount = 0;
+ tnl->ExecParity = IM->PrimitiveLength[last] & 1;
- if (fixup & VERT_RGBA)
- fixup_4ub( store->Color, flags, 0, VERT_RGBA|fixup_fence );
+ if (pincr != 1 && (IM->Count - last - pintro))
+ ovf = (IM->Count - last - pintro) % pincr;
- if (fixup & VERT_NORM)
- fixup_3f( store->Normal, flags, 0, VERT_NORM|fixup_fence );
+ if (last < IM->Count)
+ copy_tab[prim]( tnl, last, IM->Count, ovf );
- for (i = 0, j = 0 ; i < tnl->vb.Count ; i++) {
- if (flags[i] & good_index) {
- store->Elts[j++] = i;
- prim_length++;
- }
- if (i == nextprim) {
- VB->PrimitiveLength[lastprim] = prim_length;
- VB->Primitive[j] = VB->Primitive[i];
- nextprim += lastprimlen;
- lastprim = i;
- lastprimlen = VB->PrimitiveLength[i];
- }
+ for (i = 0 ; i < tnl->ExecCopyCount ; i++)
+ tnl->ExecCopyElts[i] = IM->Elt[tnl->ExecCopyElts[i]];
}
-
- VB->Elts = store->Elts;
+}
- /* What about copying??? No immediate exists with the right
- * vertices in place...
- */
- if (tnl->CurrentPrimitive != GL_POLYGON+1) {
+
+void _tnl_upgrade_current_data( GLcontext *ctx,
+ GLuint required,
+ GLuint flags )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ struct immediate *IM = (struct immediate *)VB->import_source;
+
+ ASSERT(IM);
+
+/* _tnl_print_vert_flags("_tnl_upgrade_client_data", required); */
+
+ if ((required & VERT_RGBA) && (VB->ColorPtr[0]->Flags & CA_CLIENT_DATA)) {
+ struct gl_client_array *tmp = &tnl->imm_inputs.Color;
+ GLuint start = IM->CopyStart;
+
+ tmp->Ptr = IM->Color + start;
+ tmp->StrideB = 4 * sizeof(GLfloat);
+ tmp->Flags = 0;
+
+ COPY_4FV( IM->Color[start], ctx->Current.Color);
+
+ ASSERT(IM->Flag[IM->LastData+1] & VERT_END_VB);
+
+ fixup_first_4f( IM->Color, IM->Flag, VERT_END_VB, start,
+ IM->Color[start] );
+
+ VB->importable_data &= ~VERT_RGBA;
}
}
-#endif
+