home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
AmigActive 6
/
AACD06.ISO
/
AACD
/
System
/
Mesa-3.1
/
src
/
vbxform.c
< prev
next >
Wrap
C/C++ Source or Header
|
2000-01-07
|
28KB
|
1,083 lines
/* $Id: vbxform.c,v 1.18.2.2 1999/12/12 18:30:14 keithw Exp $ */
/*
* Mesa 3-D graphics library
* Version: 3.1
*
* Copyright (C) 1999 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.
*/
#ifdef PC_HEADER
#include "all.h"
#else
#ifndef XFree86Server
#include <math.h>
#include <stdlib.h>
#include <stdio.h>
#else
#include "GL/xf86glx.h"
#endif
#include "context.h"
#include "cva.h"
#include "clip.h"
#include "eval.h"
#include "enums.h"
#include "dlist.h"
#include "fog.h"
#include "light.h"
#include "macros.h"
#include "matrix.h"
#include "mmath.h"
#include "pipeline.h"
#include "shade.h"
#include "texture.h"
#include "types.h"
#include "varray.h"
#include "vb.h"
#include "vbcull.h"
#include "vbfill.h"
#include "vbrender.h"
#include "vbxform.h"
#include "xform.h"
#endif
void gl_maybe_transform_vb( struct immediate *IM )
{
GLcontext *ctx = IM->backref;
if (ctx->NewState)
gl_update_state(ctx);
if (IM->FlushElt) {
gl_exec_array_elements( ctx, IM, IM->LastPrimitive, IM->Count );
IM->FlushElt = 0;
}
gl_compute_orflag( IM );
if (ctx->ExecuteFlag)
gl_cva_compile_cassette( ctx, IM );
else
gl_fixup_input( ctx, IM );
if (ctx->CompileFlag)
gl_compile_cassette( ctx );
else
gl_reset_input( ctx );
}
void gl_flush_vb( GLcontext *ctx, const char *where )
{
struct immediate *IM = ctx->input;
if (MESA_VERBOSE&VERBOSE_PIPELINE)
fprintf(stderr, "gl_flush_vb: %s\n", where);
gl_maybe_transform_vb( IM );
}
/* Drivers can call this inside their swapbuffers routines:
*/
void gl_internal_flush( GLcontext *ctx )
{
FLUSH_VB( ctx, "internal flush" );
}
#define RESET_VEC(v, t, s, c) (v.start = t v.data[s], v.count = c)
/*
*
*/
void gl_reset_vb( struct vertex_buffer *VB )
{
GLuint copy;
GLuint dst;
GLuint start;
struct immediate *IM = VB->IM;
GLubyte clipor = VB->ClipOrMask;
if (!VB->CullDone)
gl_fast_copy_vb( VB );
copy = VB->CopyCount;
start = 3-copy;
VB->CopyStart = start;
VB->ClipOrMask = 0;
VB->ClipAndMask = CLIP_ALL_BITS;
if (IM)
{
if (VB->Count != IM->Count && 0) {
fprintf(stderr, "Trying to copy vertices in the middle of an IM (%d/%d)!!\n",
VB->Count, IM->Count);
}
else if (VB->pipeline->copy_transformed_data) {
for (dst = start ; dst < VB_START ; dst++)
{
GLuint src = VB->Copy[dst];
if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
fprintf(stderr, "copying vertex %u to %u\n", src, dst);
COPY_4FV( VB->Clip.data[dst], VEC_ELT(VB->ClipPtr, GLfloat, src) );
COPY_4FV( VB->Win.data[dst], VB->Win.data[src] );
VB->UserClipMask[dst] = VB->UserClipMask[src];
VB->ClipMask[dst] = (GLubyte) (VB->ClipMask[src] & ~CLIP_CULLED_BIT);
VB->ClipAndMask &= VB->ClipMask[dst];
VB->ClipOrMask |= VB->ClipMask[dst];
VB->ClipMask[src] = 0; /* hack for bounds_cull_vb */
COPY_4UBV( IM->Color[dst], IM->Color[src] );
COPY_4UBV( VB->Spec[0][dst], VB->Spec[0][src] );
COPY_4UBV( VB->Spec[1][dst], VB->Spec[1][src] );
COPY_4UBV( VB->BColor.data[dst], VB->BColor.data[src] );
IM->Index[dst] = IM->Index[src];
VB->BIndex.data[dst] = VB->BIndex.data[src];
if (VB->TexCoordPtr[0] == &IM->v.TexCoord[0])
COPY_4FV( IM->TexCoord[0][dst], IM->TexCoord[0][src] );
if (VB->TexCoordPtr[1] == &IM->v.TexCoord[1])
COPY_4FV( IM->TexCoord[1][dst], IM->TexCoord[1][src] );
IM->Elt[dst] = IM->Elt[src];
VB->SavedOrFlag |= IM->Flag[src];
}
}
VB->CullDone = 0;
}
if (clipor & CLIP_USER_BIT)
MEMSET(VB->UserClipMask + VB->Start, 0, VB->Count);
VB->NormCullStart = 0;
VB->Parity = (VB->LastPrimitive^VB->Count)&1;
VB->PurgeFlags = 0;
VB->EarlyCull = 1;
VB->Culled = 0;
VB->BoundsPtr = 0;
VB->NormalLengthPtr = 0;
VB->Indirect = 0;
VB->Culled = 0;
}
/* Copy the untransformed parts of the overlapping vertices from one
* immediate struct to another (or possibly the same one).
*
* Only copy those elements which are genuinely untransformed. Others
* are done in gl_reset_vb.
*/
void gl_copy_prev_vertices( struct vertex_buffer *VB,
struct immediate *prev,
struct immediate *next )
{
GLuint dst;
GLuint flags = VB->pipeline->inputs;
if (MESA_VERBOSE&VERBOSE_CULL)
fprintf(stderr, "copy prev vertices im: prev %d next %d copystart %d\n",
prev->id, next->id, VB->CopyStart);
/* VB_START is correct as vertex copying is only required when an
* IM wraps, which means that the next VB must start at VB_START.
*/
for (dst = VB->CopyStart ; dst < VB_START ; dst++)
{
GLuint src = VB->Copy[dst];
if (MESA_VERBOSE&VERBOSE_CULL)
fprintf(stderr, "copy_prev: copy %d to %d\n", src, dst );
COPY_4FV( next->Obj[dst], prev->Obj[src] );
if ((flags&VERT_TEX0_ANY) && VB->TexCoordPtr[0] == &prev->v.TexCoord[0])
COPY_4FV( next->TexCoord[0][dst], prev->TexCoord[0][src] );
if ((flags&VERT_TEX1_ANY) && VB->TexCoordPtr[1] == &prev->v.TexCoord[1])
COPY_4FV( next->TexCoord[1][dst], prev->TexCoord[1][src] );
COPY_4UBV( next->Color[dst], prev->Color[src] );
next->Index[dst] = prev->Index[src];
next->EdgeFlag[dst] = prev->EdgeFlag[src];
next->Elt[dst] = prev->Elt[src];
VB->SavedOrFlag |= prev->Flag[src];
}
}
void RESET_IMMEDIATE( GLcontext *ctx )
{
if (ctx->VB->prev_buffer != ctx->VB->IM) {
/* Should only get here if we are trying to use the internal
* interfaces, eg gl_Vertex3f(), gl_Begin() from inside a
* display list. In this case, it is necessary to pull the
* current values into the ctx->VB.store buffer, because this
* may not have been done.
*/
FLUSH_VB( ctx, "RESET_IMMEDIATE" );
gl_reset_input( ctx );
}
}
/* Called to initialize new buffers, and to recycle old ones.
*/
void gl_reset_input( GLcontext *ctx )
{
struct immediate *IM = ctx->input;
MEMSET(IM->Flag, 0, sizeof(GLuint) * (IM->Count+2));
IM->Start = VB_START;
IM->Count = VB_START;
IM->Primitive[IM->Start] = ctx->Current.Primitive;
IM->LastPrimitive = IM->Start;
IM->BeginState = VERT_BEGIN_0;
IM->OrFlag = 0;
IM->AndFlag = ~0U;
if (0)
fprintf(stderr,
"in reset_input(IM %d), BeginState is %x, setting prim[%d] to %s\n",
IM->id,
VERT_BEGIN_0,
IM->Start, gl_lookup_enum_by_nr(ctx->Current.Primitive));
IM->ArrayAndFlags = ~ctx->Array.Flags;
IM->ArrayIncr = ctx->Array.Vertex.Enabled;
IM->ArrayEltFlush = !(ctx->CompileCVAFlag);
}
/* Preserves size information as well.
*/
static void
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]);
flag[i] |= (flag[i-1] & match);
if (flag[i] & VERT_END_VB) break;
}
}
}
/* Only needed for buffers with eval coords.
*/
static void
fixup_3f( float data[][3], GLuint flag[], GLuint start, GLuint match )
{
GLuint i = start;
for (;;) {
if ((flag[++i] & match) == 0) {
COPY_3V(data[i], data[i-1]);
flag[i] |= match;
if (flag[i] & VERT_END_VB) break;
}
}
}
static void
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_END_VB) break;
}
}
flag[i] |= match;
}
static void
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_END_VB) break;
}
}
flag[i] |= match;
}
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;
}
/* Do this instead of fixup for shared normals.
*/
static void
find_last_3f( float data[][3], GLuint flag[], GLuint match, GLuint count )
{
GLuint i = count;
for (;;)
if ((flag[--i] & match) != 0) {
COPY_3V(data[count], data[i]);
return;
}
}
static void
fixup_first_4v( GLfloat data[][4], GLuint flag[], GLuint match,
GLuint start, GLfloat *dflt )
{
GLuint i = start-1;
match |= VERT_END_VB;
while ((flag[++i]&match) == 0)
COPY_4FV(data[i], dflt);
}
static void
fixup_first_1ui( GLuint data[], GLuint flag[], GLuint match,
GLuint start, GLuint dflt )
{
GLuint i = start-1;
match |= VERT_END_VB;
while ((flag[++i]&match) == 0)
data[i] = dflt;
}
static void
fixup_first_1ub( GLubyte data[], GLuint flag[], GLuint match,
GLuint start, GLubyte dflt )
{
GLuint i = start-1;
match |= VERT_END_VB;
while ((flag[++i]&match) == 0)
data[i] = 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);
}
static GLuint vertex_sizes[16] = { 0,
1,
2, 2,
3, 3, 3, 3,
4, 4, 4, 4, 4, 4, 4, 4 };
GLuint gl_texcoord_size( GLuint flag, GLuint unit )
{
flag >>= VERT_TEX0_SHIFT + unit * NR_TEXSIZE_BITS;
return vertex_sizes[flag & 0xf];
}
static void set_vec_sizes( struct immediate *IM, GLuint orflag )
{
GLuint i;
if (orflag & VERT_OBJ_ANY) {
GLuint szflag = orflag & VERT_OBJ_234;
IM->v.Obj.size = vertex_sizes[szflag<<1];
}
for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++) {
if (orflag & VERT_TEX_ANY(i)) {
GLuint szflag = ((orflag>>(VERT_TEX0_SHIFT+i*NR_TEXSIZE_BITS))
& 0xf);
IM->v.TexCoord[i].size = vertex_sizes[szflag];
}
}
}
void gl_compute_orflag( struct immediate *IM )
{
GLuint count = IM->Count;
GLuint orflag = 0;
GLuint andflag = ~0U;
GLuint i;
IM->LastData = count-1;
/* Compute the flags for the whole buffer, even if
*/
for (i = IM->Start ; i < count ; i++) {
andflag &= IM->Flag[i];
orflag |= IM->Flag[i];
}
if (IM->Flag[i] & VERT_DATA) {
IM->LastData++;
/* andflag &= IM->Flag[i]; */ /* possibly incorrect (norm_bug.c) */
orflag |= IM->Flag[i];
}
IM->Flag[IM->LastData+1] |= VERT_END_VB;
IM->AndFlag = andflag;
IM->OrFlag = orflag;
}
void gl_fixup_input( GLcontext *ctx, struct immediate *IM )
{
GLuint count = IM->Count;
GLuint start = IM->Start;
GLuint fixup, diff;
GLuint andflag = IM->AndFlag;
GLuint orflag = IM->OrFlag;
IM->Primitive[count] = IM->Primitive[IM->LastPrimitive];
IM->NextPrimitive[IM->LastPrimitive] = count;
IM->NextPrimitive[count] = count+1;
if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
{
fprintf(stderr, "Start: %u Count: %u LastData: %u\n",
IM->Start, IM->Count, IM->LastData);
gl_print_vert_flags("Orflag", orflag);
gl_print_vert_flags("Andflag", andflag);
}
/* Array elements modify the current state - must do this before
* fixup.
*/
if (ctx->CompileCVAFlag && !(andflag & VERT_ELT))
gl_rescue_cva( ctx, IM );
if (orflag & VERT_ELT)
{
orflag = IM->OrFlag;
andflag = IM->AndFlag;
start = IM->Start;
}
fixup = ~andflag & VERT_FIXUP;
if (!ctx->CompileFlag)
fixup &= ctx->CVA.elt.inputs;
if (!ctx->ExecuteFlag)
fixup &= orflag;
if (ctx->CompileCVAFlag)
fixup &= ~ctx->CVA.pre.outputs;
if ((orflag & (VERT_OBJ_ANY|VERT_EVAL_ANY)) == 0)
fixup = 0;
if (fixup)
{
if (ctx->ExecuteFlag && (fixup & ~IM->Flag[start])) {
GLuint copy = fixup & ~IM->Flag[start];
if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
gl_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.ByteColor);
if (copy & VERT_INDEX)
IM->Index[start] = ctx->Current.Index;
if (copy & VERT_EDGE)
IM->EdgeFlag[start] = ctx->Current.EdgeFlag;
if (copy & VERT_TEX0_ANY)
COPY_4FV( IM->TexCoord[0][start], ctx->Current.Texcoord[0] );
if (copy & VERT_TEX1_ANY)
COPY_4FV( IM->TexCoord[1][start], ctx->Current.Texcoord[1] );
}
if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
gl_print_vert_flags("fixup", fixup);
if (fixup & VERT_TEX0_ANY) {
if (orflag & VERT_TEX0_ANY)
fixup_4f( IM->TexCoord[0], IM->Flag, start, VERT_TEX0_1234 );
else
fixup_first_4v( IM->TexCoord[0], IM->Flag, 0, start,
IM->TexCoord[0][start]);
}
if (fixup & VERT_TEX1_ANY) {
if (orflag & VERT_TEX1_ANY)
fixup_4f( IM->TexCoord[1], IM->Flag, start, VERT_TEX1_1234 );
else
fixup_first_4v( IM->TexCoord[1], IM->Flag, 0, start,
IM->TexCoord[1][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, 0, 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, 0, 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, 0, start, IM->Color[start] );
}
if (fixup & VERT_NORM) {
/* Only eval cannot use the Flag member to find valid normals:
*/
if (IM->OrFlag & VERT_EVAL_ANY)
fixup_3f( IM->Normal, IM->Flag, start, VERT_NORM );
else {
/* Copy-to-current requires a valid normal in the last slot:
*/
if ((IM->OrFlag & VERT_NORM) &&
!(IM->Flag[IM->LastData] & VERT_NORM))
find_last_3f( IM->Normal, IM->Flag, VERT_NORM, IM->LastData );
}
}
}
diff = count - start;
IM->v.Obj.count = diff;
IM->v.Normal.count = diff;
IM->v.TexCoord[0].count = diff;
IM->v.TexCoord[1].count = diff;
IM->v.EdgeFlag.count = diff;
IM->v.Color.count = diff;
IM->v.Index.count = diff;
/* Prune possible half-filled slot.
*/
IM->Flag[IM->LastData+1] &= ~VERT_END_VB;
IM->Flag[IM->Count] |= VERT_END_VB;
}
static void calc_normal_lengths( GLfloat *dest,
CONST GLfloat (*data)[3],
const GLuint *flags,
GLuint count )
{
GLuint i;
for (i = 0 ; i < count ; i++ )
if (flags[i] & VERT_NORM) {
GLfloat tmp = (GLfloat) LEN_3FV( data[i] );
dest[i] = 0;
if (tmp > 0)
dest[i] = 1.0F / tmp;
}
}
/* 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.
*/
void gl_fixup_cassette( GLcontext *ctx, struct immediate *IM )
{
GLuint fixup;
GLuint count = IM->Count;
GLuint start = IM->Start;
if (count == start)
return;
if (ctx->NewState)
gl_update_state( ctx );
if (ctx->Transform.Normalize && IM->LastCalcedLength < IM->Count) {
GLuint start = IM->LastCalcedLength;
if (!IM->NormalLengths)
IM->NormalLengths = (GLfloat *)MALLOC(sizeof(GLfloat) * VB_SIZE);
calc_normal_lengths( IM->NormalLengths + start,
(const GLfloat (*)[3])(IM->Normal + start),
IM->Flag + start,
IM->Count - start);
IM->LastCalcedLength = IM->Count;
}
fixup = ctx->CVA.elt.inputs & ~IM->AndFlag & VERT_FIXUP;
if (fixup) {
if (MESA_VERBOSE & VERBOSE_IMMEDIATE) {
fprintf(stderr, "start: %d count: %d\n", start, count);
gl_print_vert_flags("fixup_cassette", fixup);
}
if (fixup & VERT_TEX0_ANY)
fixup_first_4v( IM->TexCoord[0], IM->Flag, VERT_TEX0_ANY, start,
ctx->Current.Texcoord[0] );
if (fixup & VERT_TEX1_ANY)
fixup_first_4v( IM->TexCoord[1], IM->Flag, VERT_TEX1_ANY, start,
ctx->Current.Texcoord[1] );
if (fixup & VERT_EDGE)
fixup_first_1ub(IM->EdgeFlag, IM->Flag, VERT_EDGE, start,
ctx->Current.EdgeFlag );
if (fixup & VERT_INDEX)
fixup_first_1ui(IM->Index, IM->Flag, VERT_INDEX, start,
ctx->Current.Index );
if (fixup & VERT_RGBA)
fixup_first_4ub(IM->Color, IM->Flag, VERT_RGBA, start,
ctx->Current.ByteColor );
if ((fixup & VERT_NORM) && !(IM->Flag[start] & VERT_NORM)) {
COPY_3V(IM->Normal[start], ctx->Current.Normal);
if (ctx->Transform.Normalize)
IM->NormalLengths[start] = 1.0F / (GLfloat) LEN_3FV(ctx->Current.Normal);
}
}
}
static void fixup_primitives( struct vertex_buffer *VB, struct immediate *IM )
{
static GLuint increment[GL_POLYGON+2] = { 1,2,1,1,3,1,1,4,2,1,1 };
static GLuint intro[GL_POLYGON+2] = { 0,0,2,2,0,2,2,0,2,2,0 };
GLcontext *ctx = VB->ctx;
const GLuint *flags = IM->Flag;
const GLuint *in_prim = IM->Primitive;
const GLuint *in_nextprim = IM->NextPrimitive;
GLuint *out_prim = VB->IM->Primitive;
GLuint *out_nextprim = VB->IM->NextPrimitive;
GLuint count = VB->Count;
GLuint start = VB->Start;
GLuint in, out, last;
GLuint incr, prim;
GLuint transition;
GLuint interesting;
GLuint err;
/* printf("IM: %d VB->Count %d VB->Start %d current prim: %d\n", IM->id, VB->Count, VB->Start, ctx->Current.Primitive); */
if (ctx->Current.Primitive == GL_POLYGON+1) {
transition = VERT_BEGIN;
err = IM->BeginState & VERT_ERROR_1;
} else {
transition = VERT_END;
err = IM->BeginState & VERT_ERROR_0;
}
if (err) {
/* Occurred somewhere inside the vb. Don't know/care where/why.
*/
gl_error( ctx, GL_INVALID_OPERATION, "begin/end");
}
interesting = transition | VERT_END_VB;
for (in = start ; in <= count ; in = in_nextprim[in])
if (flags[in] & interesting)
break;
out = VB->CopyStart;
if (in == out) {
out_nextprim[out] = in_nextprim[in];
out_prim[out] = in_prim[in];
last = IM->LastPrimitive;
} else if (flags[in] & transition) {
out_nextprim[out] = in;
out_prim[out] = ctx->Current.Primitive;
out = in;
last = IM->LastPrimitive;
} else {
out_nextprim[out] = in;
out_prim[out] = ctx->Current.Primitive;
in++;
last = out;
}
for ( ; in <= count ; in = in_nextprim[in] ) {
out_prim[in] = in_prim[in];
out_nextprim[in] = in_nextprim[in];
}
VB->Primitive = out_prim;
VB->NextPrimitive = out_nextprim;
VB->LastPrimitive = last;
prim = ctx->Current.Primitive = (GLenum) out_prim[last];
/* Calculate whether the primitive finished on a 'good number' of
* vertices, or whether there are overflowing vertices we have to
* copy to the next buffer (in addition to the normal ones required
* by a continuing primitive).
*
* Note that GL_POLYGON+1, ie outside begin/end, has increment 1.
*/
incr = increment[prim];
if (incr != 1 && (count - last - intro[prim]))
VB->Ovf = (count - last - intro[prim]) % incr;
else
VB->Ovf = 0;
if (0)
fprintf(stderr, "prim: %s count %u last %u incr %u ovf: %u\n",
gl_prim_name[prim], count, last, incr, VB->Ovf);
}
void gl_copy_to_current( GLcontext *ctx, struct immediate *IM )
{
GLuint count = IM->LastData;
GLuint flag = IM->OrFlag;
GLuint mask = 0;
if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
gl_print_vert_flags("copy to current", flag);
if (flag & VERT_NORM)
COPY_3FV( ctx->Current.Normal, IM->Normal[count]);
if (flag & VERT_INDEX)
ctx->Current.Index = IM->Index[count];
if (flag & VERT_EDGE)
ctx->Current.EdgeFlag = IM->EdgeFlag[count];
if (flag & VERT_RGBA)
COPY_4UBV(ctx->Current.ByteColor, IM->Color[count]);
if (flag & VERT_TEX0_ANY) {
mask |= VERT_TEX0_1234;
COPY_4FV( ctx->Current.Texcoord[0], IM->TexCoord[0][count]);
}
if (flag & VERT_TEX1_ANY) {
mask |= VERT_TEX1_1234;
COPY_4FV( ctx->Current.Texcoord[1], IM->TexCoord[1][count]);
}
/* Save the texcoord size information as well.
*/
ctx->Current.Flag &= ~mask;
ctx->Current.Flag |= IM->Flag[count] & mask;
}
void gl_execute_cassette( GLcontext *ctx, struct immediate *IM )
{
struct vertex_buffer *VB = ctx->VB;
struct immediate *prev = VB->prev_buffer;
GLuint vec_start, diff;
IM->ref_count++;
if (prev != IM || IM != VB->IM) {
gl_copy_prev_vertices( VB, VB->prev_buffer, IM );
}
if (! --prev->ref_count )
gl_immediate_free( prev );
VB->prev_buffer = IM;
VB->Start = IM->Start;
VB->Count = IM->Count;
VB->Flag = IM->Flag;
VB->OrFlag = IM->OrFlag | VB->SavedOrFlag;
VB->EltPtr = &IM->v.Elt;
VB->MaterialMask = IM->MaterialMask;
VB->Material = IM->Material;
VB->CullMode = (GLubyte) ((IM->AndFlag & VERT_NORM) ? 0 : COMPACTED_NORMALS);
VB->ObjPtr = &IM->v.Obj;
VB->NormalPtr = &IM->v.Normal;
VB->ColorPtr = &IM->v.Color;
VB->Color[0] = VB->Color[1] = VB->ColorPtr;
VB->IndexPtr = &IM->v.Index;
VB->EdgeFlagPtr = &IM->v.EdgeFlag;
VB->TexCoordPtr[0] = &IM->v.TexCoord[0];
VB->TexCoordPtr[1] = &IM->v.TexCoord[1];
/* VB->BoundsPtr = IM->Bounds; */
VB->NormalLengthPtr = IM->NormalLengths;
VB->IndirectCount = VB->Count;
VB->SavedOrFlag = 0;
if (IM->Start != VB_START)
VB->CopyStart = IM->Start;
vec_start = IM->Start;
if (vec_start == VB_START && VB->pipeline->replay_copied_vertices)
vec_start = VB->CopyStart;
if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
fprintf(stderr, "reseting vectors to %d/%d .. %d\n", vec_start, IM->Start, IM->Count);
VB->LastPrimitive = IM->Start;
diff = IM->Count - vec_start;
RESET_VEC(IM->v.Obj, (GLfloat *), vec_start, diff);
RESET_VEC(IM->v.Normal, (GLfloat *), vec_start, diff);
RESET_VEC(IM->v.TexCoord[0], (GLfloat *), vec_start, diff);
RESET_VEC(IM->v.TexCoord[1], (GLfloat *), vec_start, diff);
RESET_VEC(IM->v.Index, &, vec_start, diff);
RESET_VEC(IM->v.Elt, &, vec_start, diff);
RESET_VEC(IM->v.EdgeFlag, &, vec_start, diff);
RESET_VEC(IM->v.Color, (GLubyte *), vec_start, diff);
RESET_VEC(VB->Clip, (GLfloat *), vec_start, diff);
RESET_VEC(VB->Eye, (GLfloat *), vec_start, diff);
RESET_VEC(VB->Win, (GLfloat *), vec_start, diff);
RESET_VEC(VB->BColor, (GLubyte *), vec_start, diff);
RESET_VEC(VB->BIndex, &, vec_start, diff);
if (IM != VB->IM) {
RESET_VEC(VB->IM->v.Obj, (GLfloat *), vec_start, diff);
RESET_VEC(VB->IM->v.Normal, (GLfloat *), vec_start, diff);
RESET_VEC(VB->IM->v.TexCoord[0], (GLfloat *), vec_start, diff);
RESET_VEC(VB->IM->v.TexCoord[1], (GLfloat *), vec_start, diff);
RESET_VEC(VB->IM->v.Index, &, vec_start, diff);
RESET_VEC(VB->IM->v.Elt, &, vec_start, diff);
RESET_VEC(VB->IM->v.EdgeFlag, &, vec_start, diff);
RESET_VEC(VB->IM->v.Color, (GLubyte *), vec_start, diff);
}
gl_copy_to_current( ctx, IM );
set_vec_sizes( IM, VB->OrFlag );
if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
fprintf(stderr,
"executing cassette, rows %u tc0->size == %u tc1->size == %u\n",
VB->Count,
VB->TexCoordPtr[0]->size,
VB->TexCoordPtr[1]->size);
if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
gl_print_cassette( IM );
if (IM->OrFlag & VERT_EVAL_ANY)
gl_eval_vb( VB );
if (IM->Count > IM->Start || (IM->Flag[IM->Start] & (VERT_END|VERT_BEGIN)))
fixup_primitives( VB, IM );
if (VB->IndirectCount > IM->Start)
gl_run_pipeline( VB );
else
gl_update_materials( VB );
/* This is unfortunate:
*/
if (VB->pipeline->replay_copied_vertices) {
if (!VB->CullDone)
gl_fast_copy_vb( VB );
gl_copy_prev_vertices( VB, VB->prev_buffer, IM );
}
gl_reset_vb( VB );
}
void gl_print_cassette( struct immediate *IM )
{
gl_print_cassette_flags( IM, IM->Flag );
}
void gl_print_cassette_flags( struct immediate *IM, GLuint *flags )
{
GLuint i;
GLuint andflag = IM->AndFlag;
GLuint orflag = IM->OrFlag;
GLuint state = IM->BeginState;
GLuint req = ~0;
static const char *tplate[5] = { "%s ",
"%s: %f ",
"%s: %f %f ",
"%s: %f %f %f ",
"%s: %f %f %f %f " };
fprintf(stderr, "Cassette id %d, %u rows.\n", IM->id, IM->Count - IM->Start);
gl_print_vert_flags("Contains at least one", orflag);
if (IM->Count != IM->Start)
{
gl_print_vert_flags("Contains a full complement of", andflag);
fprintf(stderr, "Final begin/end state %s/%s, errors %s/%s\n",
(state & VERT_BEGIN_0) ? "in" : "out",
(state & VERT_BEGIN_1) ? "in" : "out",
(state & VERT_ERROR_0) ? "y" : "n",
(state & VERT_ERROR_1) ? "y" : "n");
fprintf(stderr, "Obj size: %u, TexCoord0 size: %u, TexCoord1 size: %u\n",
IM->v.Obj.size,
IM->v.TexCoord[0].size,
IM->v.TexCoord[1].size);
}
for (i = IM->Start ; i <= IM->Count ; i++) {
fprintf(stderr, "%u: ", i);
if (req & VERT_OBJ_ANY) {
if (flags[i] & VERT_EVAL_C1)
fprintf(stderr, "EvalCoord %f ", IM->Obj[i][0]);
else if (flags[i] & VERT_EVAL_P1)
fprintf(stderr, "EvalPoint %.0f ", IM->Obj[i][0]);
else if (flags[i] & VERT_EVAL_C2)
fprintf(stderr, "EvalCoord %f %f ", IM->Obj[i][0], IM->Obj[i][1]);
else if (flags[i] & VERT_EVAL_P2)
fprintf(stderr, "EvalPoint %.0f %.0f ", IM->Obj[i][0], IM->Obj[i][1]);
else if (i < IM->Count && (flags[i]&VERT_OBJ_234)) {
fprintf(stderr, "(%x) ", flags[i] & VERT_OBJ_234);
fprintf(stderr, tplate[vertex_sizes[(flags[i]&VERT_OBJ_234)<<1]],
"Obj",
IM->Obj[i][0], IM->Obj[i][1], IM->Obj[i][2], IM->Obj[i][3]);
}
}
if (req & flags[i] & VERT_ELT)
fprintf(stderr, " Elt %u\t", IM->Elt[i]);
if (req & flags[i] & VERT_NORM)
fprintf(stderr, " Norm %f %f %f ",
IM->Normal[i][0], IM->Normal[i][1], IM->Normal[i][2]);
if (req & flags[i] & VERT_TEX0_ANY)
fprintf(stderr, tplate[vertex_sizes[(flags[i]>>VERT_TEX0_SHIFT)&7]],
"TC0",
IM->TexCoord[0][i][0], IM->TexCoord[0][i][1],
IM->TexCoord[0][i][2], IM->TexCoord[0][i][2]);
if (req & flags[i] & VERT_TEX1_ANY)
fprintf(stderr, tplate[vertex_sizes[(flags[i]>>(VERT_TEX0_SHIFT+4))&7]],
"TC1",
IM->TexCoord[1][i][0], IM->TexCoord[1][i][1],
IM->TexCoord[1][i][2], IM->TexCoord[1][i][2]);
if (req & flags[i] & VERT_RGBA)
fprintf(stderr, " Rgba %d %d %d %d ",
IM->Color[i][0], IM->Color[i][1],
IM->Color[i][2], IM->Color[i][3]);
if (req & flags[i] & VERT_INDEX)
fprintf(stderr, " Index %u ", IM->Index[i]);
if (req & flags[i] & VERT_EDGE)
fprintf(stderr, " Edgeflag %d ", IM->EdgeFlag[i]);
if (req & flags[i] & VERT_MATERIAL)
fprintf(stderr, " Material ");
/* The order of these two is not easily knowable, but this is
* the usually correct way to look at them.
*/
if (req & flags[i] & VERT_END)
fprintf(stderr, " END ");
if (req & flags[i] & VERT_BEGIN)
fprintf(stderr, " BEGIN(%s) ", gl_prim_name[IM->Primitive[i]]);
fprintf(stderr, "\n");
}
}