Go to most recent revision |
Blame |
Last modification |
View Log
| RSS feed
/* $Id: t_imm_fixup.c,v 1.1 2003-02-28 11:48:07 pj Exp $ */
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 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"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
/*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "glheader.h"
#include "context.h"
#include "enums.h"
#include "dlist.h"
#include "colormac.h"
#include "light.h"
#include "macros.h"
#include "imports.h"
#include "mmath.h"
#include "state.h"
#include "mtypes.h"
#include "math/m_matrix.h"
#include "math/m_xform.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_imm_exec.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 };
void
_tnl_fixup_4f( GLfloat data[][4], GLuint flag[], GLuint start, GLuint match )
{
GLuint i = start;
for (;;) {
if ((flag[++i] & match) == 0) {
COPY_4FV(data[i], data[i-1]);
if (flag[i] & VERT_BIT_END_VB) break;
}
}
}
void
_tnl_fixup_3f( float data[][3], GLuint flag[], GLuint start, GLuint match )
{
GLuint i = start;
for (;;) {
if ((flag[++i] & match) == 0) {
/* _mesa_debug(NULL, "_tnl_fixup_3f copy to %p values %f %f %f\n", */
/* data[i], */
/* data[i-1][0], */
/* data[i-1][1], */
/* data[i-1][2]); */
COPY_3V(data[i], data[i-1]);
if (flag[i] & VERT_BIT_END_VB) break;
}
}
}
void
_tnl_fixup_1ui( GLuint *data, GLuint flag[], GLuint start, GLuint match )
{
GLuint i = start;
for (;;) {
if ((flag[++i] & match) == 0) {
data[i] = data[i-1];
if (flag[i] & VERT_BIT_END_VB) break;
}
}
flag[i] |= match;
}
void
_tnl_fixup_1f( GLfloat *data, GLuint flag[], GLuint start, GLuint match )
{
GLuint i = start;
for (;;) {
if ((flag[++i] & match) == 0) {
data[i] = data[i-1];
if (flag[i] & VERT_BIT_END_VB) break;
}
}
flag[i] |= match;
}
void
_tnl_fixup_1ub( GLubyte *data, GLuint flag[], GLuint start, GLuint match )
{
GLuint i = start;
for (;;) {
if ((flag[++i] & match) == 0) {
data[i] = data[i-1];
if (flag[i] & VERT_BIT_END_VB) break;
}
}
flag[i] |= match;
}
static void
fixup_first_4f( GLfloat data[][4], GLuint flag[], GLuint match,
GLuint start, GLfloat *dflt )
{
GLuint i = start-1;
match |= VERT_BIT_END_VB;
while ((flag[++i]&match) == 0)
COPY_4FV(data[i], dflt);
}
#if 0
static void
fixup_first_3f( GLfloat data[][3], GLuint flag[], GLuint match,
GLuint start, GLfloat *dflt )
{
GLuint i = start-1;
match |= VERT_BIT_END_VB;
/* _mesa_debug(NULL, "fixup_first_3f default: %f %f %f start: %d\n", */
/* dflt[0], dflt[1], dflt[2], start); */
while ((flag[++i]&match) == 0)
COPY_3FV(data[i], dflt);
}
#endif
static void
fixup_first_1ui( GLuint data[], GLuint flag[], GLuint match,
GLuint start, GLuint dflt )
{
GLuint i = start-1;
match |= VERT_BIT_END_VB;
while ((flag[++i]&match) == 0)
data[i] = dflt;
}
#if 00
static void
fixup_first_1f( GLfloat data[], GLuint flag[], GLuint match,
GLuint start, GLfloat dflt )
{
GLuint i = start-1;
match |= VERT_BIT_END_VB;
while ((flag[++i]&match) == 0)
data[i] = dflt;
}
#endif
static void
fixup_first_1ub( GLubyte data[], GLuint flag[], GLuint match,
GLuint start, GLubyte dflt )
{
GLuint i = start-1;
match |= VERT_BIT_END_VB;
while ((flag[++i]&match) == 0)
data[i] = dflt;
}
/*
* Copy vertex attributes from the ctx->Current group into the immediate
* struct at the given position according to copyMask.
*/
static void copy_from_current( GLcontext *ctx, struct immediate *IM,
GLuint pos, GLuint copyMask )
{
GLuint attrib, attribBit;
if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
_tnl_print_vert_flags("copy from current", copyMask);
#if 0
if (copyMask & VERT_BIT_NORMAL) {
COPY_4V(IM->Attrib[VERT_ATTRIB_NORMAL][pos],
ctx->Current.Attrib[VERT_ATTRIB_NORMAL]);
}
if (copyMask & VERT_BIT_COLOR0) {
COPY_4FV( IM->Attrib[VERT_ATTRIB_COLOR0][pos],
ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
}
if (copyMask & VERT_BIT_COLOR1)
COPY_4FV( IM->Attrib[VERT_ATTRIB_COLOR1][pos],
ctx->Current.Attrib[VERT_ATTRIB_COLOR1]);
if (copyMask & VERT_BIT_FOG)
IM->Attrib[VERT_ATTRIB_FOG][pos][0] = ctx->Current.Attrib[VERT_ATTRIB_FOG][0];
if (copyMask & VERT_BITS_TEX_ANY) {
GLuint i;
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
if (copyMask & VERT_BIT_TEX(i))
COPY_4FV(IM->Attrib[VERT_ATTRIB_TEX0 + i][pos],
ctx->Current.Attrib[VERT_ATTRIB_TEX0 + i]);
}
}
#else
for (attrib = 0, attribBit = 1; attrib < 16; attrib++, attribBit <<= 1) {
if (copyMask & attribBit) {
COPY_4FV( IM->Attrib[attrib][pos], ctx->Current.Attrib[attrib]);
}
}
#endif
if (copyMask & VERT_BIT_INDEX)
IM->Index[pos] = ctx->Current.Index;
if (copyMask & VERT_BIT_EDGEFLAG)
IM->EdgeFlag[pos] = ctx->Current.EdgeFlag;
}
void _tnl_fixup_input( GLcontext *ctx, struct immediate *IM )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint start = IM->CopyStart;
GLuint andflag = IM->CopyAndFlag;
GLuint orflag = IM->CopyOrFlag | IM->Evaluated;
GLuint fixup;
IM->CopyTexSize = IM->TexSize;
/* _mesa_debug(ctx, "Fixup input, Start: %u Count: %u LastData: %u\n", */
/* IM->Start, IM->Count, IM->LastData); */
/* _tnl_print_vert_flags("Orflag", orflag); */
/* _tnl_print_vert_flags("Andflag", andflag); */
fixup = ~andflag & VERT_BITS_FIXUP;
if (!ctx->CompileFlag)
fixup &= tnl->pipeline.inputs;
if (!ctx->ExecuteFlag)
fixup &= orflag;
if ((orflag & (VERT_BIT_POS|VERT_BITS_EVAL_ANY)) == 0)
fixup = 0;
if (fixup) {
GLuint copy = fixup & ~IM->Flag[start];
/* Equivalent to a lazy copy-from-current when setting up the
* immediate.
*/
if (ctx->ExecuteFlag && copy)
copy_from_current( ctx, IM, start, copy );
if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
_tnl_print_vert_flags("fixup", fixup);
/* XXX replace these conditionals with a loop over the 16
* vertex attributes.
*/
if (fixup & VERT_BITS_TEX_ANY) {
GLuint i;
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
if (fixup & VERT_BIT_TEX(i)) {
if (orflag & VERT_BIT_TEX(i))
_tnl_fixup_4f( IM->Attrib[VERT_ATTRIB_TEX0 + i], IM->Flag,
start, VERT_BIT_TEX(i) );
else
fixup_first_4f( IM->Attrib[VERT_ATTRIB_TEX0 + i], IM->Flag,
VERT_BIT_END_VB, start,
IM->Attrib[VERT_ATTRIB_TEX0 + i][start]);
}
}
}
if (fixup & VERT_BIT_EDGEFLAG) {
if (orflag & VERT_BIT_EDGEFLAG)
_tnl_fixup_1ub( IM->EdgeFlag, IM->Flag, start, VERT_BIT_EDGEFLAG );
else
fixup_first_1ub( IM->EdgeFlag, IM->Flag, VERT_BIT_END_VB, start,
IM->EdgeFlag[start] );
}
if (fixup & VERT_BIT_INDEX) {
if (orflag & VERT_BIT_INDEX)
_tnl_fixup_1ui( IM->Index, IM->Flag, start, VERT_BIT_INDEX );
else
fixup_first_1ui( IM->Index, IM->Flag, VERT_BIT_END_VB, start,
IM->Index[start] );
}
if (fixup & VERT_BIT_COLOR0) {
if (orflag & VERT_BIT_COLOR0)
_tnl_fixup_4f( IM->Attrib[VERT_ATTRIB_COLOR0], IM->Flag, start,
VERT_BIT_COLOR0 );
/* No need for else case as the drivers understand stride
* zero here. (TODO - propogate this)
*/
}
if (fixup & VERT_BIT_COLOR1) {
if (orflag & VERT_BIT_COLOR1)
_tnl_fixup_4f( IM->Attrib[VERT_ATTRIB_COLOR1], IM->Flag, start,
VERT_BIT_COLOR1 );
else
fixup_first_4f( IM->Attrib[VERT_ATTRIB_COLOR1], IM->Flag, VERT_BIT_END_VB, start,
IM->Attrib[VERT_ATTRIB_COLOR1][start] );
}
if (fixup & VERT_BIT_FOG) {
if (orflag & VERT_BIT_FOG)
_tnl_fixup_4f( IM->Attrib[VERT_ATTRIB_FOG], IM->Flag,
start, VERT_BIT_FOG );
else
fixup_first_4f( IM->Attrib[VERT_ATTRIB_FOG], IM->Flag, VERT_BIT_END_VB,
start, IM->Attrib[VERT_ATTRIB_FOG][start] );
}
if (fixup & VERT_BIT_NORMAL) {
if (orflag & VERT_BIT_NORMAL)
_tnl_fixup_4f( IM->Attrib[VERT_ATTRIB_NORMAL], IM->Flag, start,
VERT_BIT_NORMAL );
else
fixup_first_4f( IM->Attrib[VERT_ATTRIB_NORMAL], IM->Flag,
VERT_BIT_END_VB, start,
IM->Attrib[VERT_ATTRIB_NORMAL][start] );
}
}
/* Prune possible half-filled slot.
*/
IM->Flag[IM->LastData+1] &= ~VERT_BIT_END_VB;
IM->Flag[IM->Count] |= VERT_BIT_END_VB;
/* Materials:
*/
if (IM->MaterialOrMask & ~IM->MaterialAndMask) {
GLuint vulnerable = IM->MaterialOrMask;
GLuint i = IM->Start;
do {
while (!(IM->Flag[i] & VERT_BIT_MATERIAL))
i++;
vulnerable &= ~IM->MaterialMask[i];
_mesa_copy_material_pairs( IM->Material[i],
ctx->Light.Material,
vulnerable );
++i;
} while (vulnerable);
}
}
static void
copy_material( struct immediate *next,
struct immediate *prev,
GLuint dst, GLuint src )
{
/* _mesa_debug(NULL, "%s\n", __FUNCTION__); */
if (next->Material == 0) {
next->Material = (struct gl_material (*)[2])
MALLOC( sizeof(struct gl_material) * IMM_SIZE * 2 );
next->MaterialMask = (GLuint *) MALLOC( sizeof(GLuint) * IMM_SIZE );
}
next->MaterialMask[dst] = prev->MaterialOrMask;
MEMCPY(next->Material[dst], prev->Material[src],
2 * sizeof(struct gl_material));
}
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
* that wraps over two immediate structs. This is done prior to
* set_immediate so that prev and next may point to the same
* structure. In general it's difficult to avoid this copy on long
* primitives.
*
* Have to be careful with the transitions between display list
* replay, compile and normal execute modes.
*/
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;
if (!prev) {
ASSERT(tnl->ExecCopyCount == 0);
return;
}
next->CopyStart = next->Start - count;
if ((prev->CopyOrFlag & VERT_BITS_DATA) == VERT_BIT_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_BIT_ELT;
elts[i+offset] = dst;
}
/* _mesa_debug(ctx, "ADDING VERT_BIT_ELT!\n"); */
next->CopyOrFlag |= VERT_BIT_ELT;
next->CopyAndFlag &= VERT_BIT_ELT;
}
else {
GLuint copy = tnl->pipeline.inputs & (prev->CopyOrFlag|prev->Evaluated);
GLuint flag;
if (is_fan_like[ctx->Driver.CurrentExecPrimitive]) {
flag = ((prev->CopyOrFlag|prev->Evaluated) & VERT_BITS_FIXUP);
next->CopyOrFlag |= flag;
}
else {
/* Don't let an early 'glColor', etc. poison the elt path.
*/
flag = ((prev->OrFlag|prev->Evaluated) & VERT_BITS_FIXUP);
}
next->TexSize |= tnl->ExecCopyTexSize;
next->CopyAndFlag &= flag;
/* _tnl_print_vert_flags("copy vertex components", copy); */
/* _tnl_print_vert_flags("prev copyorflag", prev->CopyOrFlag); */
/* _tnl_print_vert_flags("flag", flag); */
/* Copy whole vertices
*/
for (i = 0 ; i < count ; i++)
{
GLuint src = elts[i+offset];
GLuint isrc = src - prev->CopyStart;
GLuint dst = next->CopyStart+i;
/* 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->Attrib[VERT_ATTRIB_POS][dst],
inputs->Obj.data[isrc] );
if (copy & VERT_BIT_NORMAL) {
/* _mesa_debug(ctx, "copy vert norm %d to %d (%p): %f %f %f\n", */
/* isrc, dst, */
/* next->Normal[dst], */
/* inputs->Normal.data[isrc][0], */
/* inputs->Normal.data[isrc][1], */
/* inputs->Normal.data[isrc][2]); */
COPY_3FV( next->Attrib[VERT_ATTRIB_NORMAL][dst], inputs->Normal.data[isrc] );
}
if (copy & VERT_BIT_COLOR0)
COPY_4FV( next->Attrib[VERT_ATTRIB_COLOR0][dst],
((GLfloat (*)[4])inputs->Color.Ptr)[isrc] );
if (copy & VERT_BIT_INDEX)
next->Index[dst] = inputs->Index.data[isrc];
if (copy & VERT_BITS_TEX_ANY) {
GLuint i;
for (i = 0 ; i < prev->MaxTextureUnits ; i++) {
if (copy & VERT_BIT_TEX(i))
COPY_4FV( next->Attrib[VERT_ATTRIB_TEX0 + i][dst],
inputs->TexCoord[i].data[isrc] );
}
}
/* Remaining values should be the same in the 'input' struct and the
* original immediate.
*/
if (copy & (VERT_BIT_ELT|VERT_BIT_EDGEFLAG|VERT_BIT_COLOR1|VERT_BIT_FOG|
VERT_BIT_MATERIAL)) {
if (prev->Flag[src] & VERT_BIT_MATERIAL)
copy_material(next, prev, dst, src);
next->Elt[dst] = prev->Elt[src];
next->EdgeFlag[dst] = prev->EdgeFlag[src];
COPY_4FV( next->Attrib[VERT_ATTRIB_COLOR1][dst],
prev->Attrib[VERT_ATTRIB_COLOR1][src] );
COPY_4FV( next->Attrib[VERT_ATTRIB_FOG][dst],
prev->Attrib[VERT_ATTRIB_FOG][src] );
}
next->Flag[dst] = flag;
next->CopyOrFlag |= prev->Flag[src] & (VERT_BITS_FIXUP|
VERT_BIT_MATERIAL|
VERT_BIT_POS);
elts[i+offset] = dst;
}
}
if (--tnl->ExecCopySource->ref_count == 0)
_tnl_free_immediate( ctx, tnl->ExecCopySource );
tnl->ExecCopySource = next; next->ref_count++;
}
/* Revive a compiled immediate struct - propogate new 'Current'
* values. Often this is redundant because the current values were
* known and fixed up at compile time (or in the first execution of
* the cassette).
*/
void _tnl_fixup_compiled_cassette( GLcontext *ctx, struct immediate *IM )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint fixup;
GLuint start = IM->Start;
/* _mesa_debug(ctx, "%s\n", __FUNCTION__); */
IM->Evaluated = 0;
IM->CopyOrFlag = IM->OrFlag;
IM->CopyAndFlag = IM->AndFlag;
IM->CopyTexSize = IM->TexSize | tnl->ExecCopyTexSize;
_tnl_copy_immediate_vertices( ctx, IM );
if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
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_BIT_ELT) {
GLuint copy = tnl->pipeline.inputs & ~ctx->Array._Enabled;
GLuint i;
ASSERT(IM->CopyStart < IM->Start);
_tnl_translate_array_elts( ctx, IM, IM->CopyStart, IM->Start );
for (i = IM->CopyStart ; i < IM->Start ; i++)
copy_from_current( ctx, IM, i, copy );
_tnl_copy_to_current( ctx, IM, ctx->Array._Enabled, IM->Start );
}
fixup = tnl->pipeline.inputs & ~IM->Flag[start] & VERT_BITS_FIXUP;
/* _tnl_print_vert_flags("fixup compiled", fixup); */
if (fixup) {
/* XXX try to replace this code with a loop over the 16 vertex
* attributes.
*/
if (fixup & VERT_BIT_NORMAL) {
fixup_first_4f(IM->Attrib[VERT_ATTRIB_NORMAL], IM->Flag,
VERT_BIT_NORMAL, start,
ctx->Current.Attrib[VERT_ATTRIB_NORMAL] );
}
if (fixup & VERT_BIT_COLOR0) {
if (IM->CopyOrFlag & VERT_BIT_COLOR0)
fixup_first_4f(IM->Attrib[VERT_ATTRIB_COLOR0], IM->Flag,
VERT_BIT_COLOR0, start,
ctx->Current.Attrib[VERT_ATTRIB_COLOR0] );
else
fixup &= ~VERT_BIT_COLOR0;
}
if (fixup & VERT_BIT_COLOR1)
fixup_first_4f(IM->Attrib[VERT_ATTRIB_COLOR1], IM->Flag,
VERT_BIT_COLOR1, start,
ctx->Current.Attrib[VERT_ATTRIB_COLOR1] );
if (fixup & VERT_BIT_FOG)
fixup_first_4f( IM->Attrib[VERT_ATTRIB_FOG], IM->Flag,
VERT_BIT_FOG, start,
ctx->Current.Attrib[VERT_ATTRIB_FOG] );
if (fixup & VERT_BITS_TEX_ANY) {
GLuint i;
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
if (fixup & VERT_BIT_TEX(i))
fixup_first_4f( IM->Attrib[VERT_ATTRIB_TEX0 + i], IM->Flag,
VERT_BIT_TEX(i), start,
ctx->Current.Attrib[VERT_ATTRIB_TEX0 + i] );
}
}
if (fixup & VERT_BIT_EDGEFLAG)
fixup_first_1ub(IM->EdgeFlag, IM->Flag, VERT_BIT_EDGEFLAG, start,
ctx->Current.EdgeFlag );
if (fixup & VERT_BIT_INDEX)
fixup_first_1ui(IM->Index, IM->Flag, VERT_BIT_INDEX, start,
ctx->Current.Index );
IM->CopyOrFlag |= fixup;
}
/* Materials:
*/
if (IM->MaterialOrMask & ~IM->MaterialAndMask) {
GLuint vulnerable = IM->MaterialOrMask;
GLuint i = IM->Start;
do {
while (!(IM->Flag[i] & VERT_BIT_MATERIAL))
i++;
vulnerable &= ~IM->MaterialMask[i];
_mesa_copy_material_pairs( IM->Material[i],
ctx->Light.Material,
vulnerable );
++i;
} while (vulnerable);
}
}
static void copy_none( TNLcontext *tnl, GLuint start, GLuint count, GLuint ovf)
{
(void) (start && ovf && tnl && count);
}
static void copy_last( TNLcontext *tnl, GLuint start, GLuint count, GLuint ovf)
{
(void) start; (void) ovf;
tnl->ExecCopyCount = 1;
tnl->ExecCopyElts[2] = count-1;
}
static void copy_first_and_last( TNLcontext *tnl, GLuint start, GLuint count,
GLuint ovf)
{
(void) ovf;
tnl->ExecCopyCount = 2;
tnl->ExecCopyElts[1] = start;
tnl->ExecCopyElts[2] = count-1;
}
static void copy_last_two( TNLcontext *tnl, GLuint start, GLuint count,
GLuint ovf )
{
(void) start;
tnl->ExecCopyCount = 2+ovf;
tnl->ExecCopyElts[0] = count-3;
tnl->ExecCopyElts[1] = count-2;
tnl->ExecCopyElts[2] = count-1;
}
static void copy_overflow( TNLcontext *tnl, GLuint start, GLuint count,
GLuint ovf )
{
(void) start;
tnl->ExecCopyCount = ovf;
tnl->ExecCopyElts[0] = count-3;
tnl->ExecCopyElts[1] = count-2;
tnl->ExecCopyElts[2] = count-1;
}
typedef void (*copy_func)( TNLcontext *tnl, GLuint start, GLuint count,
GLuint ovf );
static copy_func copy_tab[GL_POLYGON+2] =
{
copy_none,
copy_overflow,
copy_first_and_last,
copy_last,
copy_overflow,
copy_last_two,
copy_first_and_last,
copy_overflow,
copy_last_two,
copy_first_and_last,
copy_none
};
/* Figure out what vertices need to be copied next time.
*/
void
_tnl_get_exec_copy_verts( GLcontext *ctx, struct immediate *IM )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLuint last = IM->LastPrimitive;
GLuint prim = ctx->Driver.CurrentExecPrimitive;
GLuint pincr = increment[prim];
GLuint pintro = intro[prim];
GLuint ovf = 0;
/* _mesa_debug(ctx, "_tnl_get_exec_copy_verts %s\n", */
/* _mesa_lookup_enum_by_nr(prim)); */
if (tnl->ExecCopySource)
if (--tnl->ExecCopySource->ref_count == 0)
_tnl_free_immediate( ctx, tnl->ExecCopySource );
if (prim == GL_POLYGON+1) {
tnl->ExecCopySource = 0;
tnl->ExecCopyCount = 0;
tnl->ExecCopyTexSize = 0;
tnl->ExecParity = 0;
} else {
/* Remember this immediate as the one to copy from.
*/
tnl->ExecCopySource = IM; IM->ref_count++;
tnl->ExecCopyCount = 0;
tnl->ExecCopyTexSize = IM->CopyTexSize;
if (IM->LastPrimitive != IM->CopyStart)
tnl->ExecParity = 0;
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 );
}
}
/* Recalculate ExecCopyElts, ExecParity, etc.
*/
void
_tnl_get_purged_copy_verts( GLcontext *ctx, struct immediate *IM )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
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;
tnl->ExecCopyCount = 0;
if (IM->LastPrimitive != IM->CopyStart)
tnl->ExecParity = 0;
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 );
for (i = 0 ; i < tnl->ExecCopyCount ; i++)
tnl->ExecCopyElts[i] = IM->Elt[tnl->ExecCopyElts[i]];
}
}
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_BIT_COLOR0) && (VB->ColorPtr[0]->Flags & CA_CLIENT_DATA)) {
struct gl_client_array *tmp = &tnl->imm_inputs.Color;
GLuint start = IM->CopyStart;
tmp->Ptr = IM->Attrib[VERT_ATTRIB_COLOR0] + start;
tmp->StrideB = 4 * sizeof(GLfloat);
tmp->Flags = 0;
COPY_4FV( IM->Attrib[VERT_ATTRIB_COLOR0][start],
ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
/*
ASSERT(IM->Flag[IM->LastData+1] & VERT_BIT_END_VB);
*/
fixup_first_4f( IM->Attrib[VERT_ATTRIB_COLOR0], IM->Flag,
VERT_BIT_END_VB,
start, IM->Attrib[VERT_ATTRIB_COLOR0][start] );
VB->importable_data &= ~VERT_BIT_COLOR0;
}
}