-/* $Id: t_imm_exec.c,v 1.8 2001/01/14 06:14:21 keithw Exp $ */
+/* $Id: t_imm_exec.c,v 1.35 2002/01/22 14:35:16 brianp Exp $ */
/*
* Mesa 3-D graphics library
- * Version: 3.5
+ * Version: 4.1
*
- * Copyright (C) 1999-2000 Brian Paul All Rights Reserved.
+ * 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"),
* 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 <keithw@valinux.com>
*/
+/**
+ * \file vpexec.c
+ * \brief Setup to execute immediate-mode vertex data.
+ * \author Keith Whitwell
+ */
#include "glheader.h"
+#include "colormac.h"
#include "context.h"
#include "enums.h"
#include "dlist.h"
#include "mmath.h"
#include "light.h"
#include "state.h"
-#include "texture.h"
#include "mtypes.h"
#include "math/m_matrix.h"
-/* Called to initialize new buffers, and to recycle old ones.
- */
-void _tnl_reset_input( GLcontext *ctx,
- GLuint start,
- GLuint beginstate,
- GLuint savedbeginstate )
+static void reset_input( GLcontext *ctx,
+ GLuint start,
+ GLuint beginstate,
+ GLuint savedbeginstate )
{
struct immediate *IM = TNL_CURRENT_IM(ctx);
if (start < IM->Count+2)
MEMSET(IM->Flag + start, 0, sizeof(GLuint) * (IM->Count+2-start));
- IM->CopyStart = IM->Start = IM->Count = start;
- IM->Primitive[IM->Start] = (ctx->Driver.CurrentExecPrimitive | PRIM_LAST);
- IM->LastPrimitive = IM->Start;
- IM->BeginState = beginstate;
+ IM->Start = start;
+ IM->Count = start;
+ IM->LastMaterial = start;
+ IM->BeginState = beginstate;
IM->SavedBeginState = savedbeginstate;
IM->TexSize = 0;
+ IM->MaterialOrMask = 0;
+
+ if (IM->MaterialMask)
+ IM->MaterialMask[IM->Start] = 0;
IM->ArrayEltFlags = ~ctx->Array._Enabled;
IM->ArrayEltIncr = ctx->Array.Vertex.Enabled ? 1 : 0;
- IM->ArrayEltFlush = !ctx->Array.LockCount;
+ IM->ArrayEltFlush = ctx->Array.LockCount ? FLUSH_ELT_LAZY : FLUSH_ELT_EAGER;
}
+
+void _tnl_reset_exec_input( GLcontext *ctx,
+ GLuint start,
+ GLuint beginstate,
+ GLuint savedbeginstate )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct immediate *IM = TNL_CURRENT_IM(ctx);
+
+ reset_input( ctx, start, beginstate, savedbeginstate );
+ IM->CopyStart = start - tnl->ExecCopyCount;
+
+ IM->Primitive[IM->CopyStart] = ctx->Driver.CurrentExecPrimitive;
+ if (tnl->ExecParity)
+ IM->Primitive[IM->CopyStart] |= PRIM_PARITY;
+
+ IM->LastPrimitive = IM->CopyStart;
+}
-static void copy_to_current( GLcontext *ctx, struct immediate *IM,
- GLuint flag )
+void _tnl_reset_compile_input( GLcontext *ctx,
+ GLuint start,
+ GLuint beginstate,
+ GLuint savedbeginstate )
{
- GLuint count = IM->LastData;
+ struct immediate *IM = TNL_CURRENT_IM(ctx);
+
+ reset_input( ctx, start, beginstate, savedbeginstate );
+ IM->CopyStart = start;
+ IM->LastPrimitive = IM->Start;
+}
+
+/**
+ * Copy the last specified normal, color, texcoord, edge flag, etc
+ * from the immediate struct into the ctx->Current attribute group.
+ */
+void _tnl_copy_to_current( GLcontext *ctx, struct immediate *IM,
+ GLuint flag, GLuint count )
+{
if (MESA_VERBOSE&VERBOSE_IMMEDIATE)
_tnl_print_vert_flags("copy to current", flag);
- if (flag & VERT_NORM)
- COPY_3FV( ctx->Current.Normal, IM->Normal[count]);
-
- if (flag & VERT_INDEX)
+ /* XXX should be able to replace these conditions with a loop over
+ * the 16 vertex attributes.
+ */
+ if (flag & VERT_BIT_NORMAL)
+ COPY_4FV( ctx->Current.Attrib[VERT_ATTRIB_NORMAL],
+ IM->Attrib[VERT_ATTRIB_NORMAL][count]);
+
+ if (flag & VERT_BIT_INDEX)
ctx->Current.Index = IM->Index[count];
- if (flag & VERT_EDGE)
+ if (flag & VERT_BIT_EDGEFLAG)
ctx->Current.EdgeFlag = IM->EdgeFlag[count];
- if (flag & VERT_RGBA)
- COPY_4UBV(ctx->Current.Color, IM->Color[count]);
+ if (flag & VERT_BIT_COLOR0) {
+ COPY_4FV(ctx->Current.Attrib[VERT_ATTRIB_COLOR0],
+ IM->Attrib[VERT_ATTRIB_COLOR0][count]);
+ if (ctx->Light.ColorMaterialEnabled) {
+ _mesa_update_color_material( ctx,
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR0] );
+ _mesa_validate_all_lighting_tables( ctx );
+ }
+ }
- if (flag & VERT_SPEC_RGB)
- COPY_4UBV(ctx->Current.SecondaryColor, IM->SecondaryColor[count]);
+ if (flag & VERT_BIT_COLOR1)
+ COPY_4FV(ctx->Current.Attrib[VERT_ATTRIB_COLOR1],
+ IM->Attrib[VERT_ATTRIB_COLOR1][count]);
- if (flag & VERT_FOG_COORD)
- ctx->Current.FogCoord = IM->FogCoord[count];
+ if (flag & VERT_BIT_FOG)
+ ctx->Current.Attrib[VERT_ATTRIB_FOG][0] = IM->Attrib[VERT_ATTRIB_FOG][count][0];
- if (flag & VERT_TEX_ANY) {
+ if (flag & VERT_BITS_TEX_ANY) {
GLuint i;
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) {
- if (flag & VERT_TEX(i)) {
- COPY_4FV( ctx->Current.Texcoord[0], IM->TexCoord[0][count]);
+ if (flag & VERT_BIT_TEX(i)) {
+ COPY_4FV( ctx->Current.Attrib[VERT_ATTRIB_TEX0 + i],
+ IM->Attrib[VERT_ATTRIB_TEX0 + i][count]);
}
}
}
+
+ if (flag & VERT_BIT_MATERIAL) {
+ _mesa_update_material( ctx,
+ IM->Material[IM->LastMaterial],
+ IM->MaterialOrMask );
+
+ _mesa_validate_all_lighting_tables( ctx );
+ }
}
-void _tnl_compute_orflag( struct immediate *IM )
+void _tnl_compute_orflag( struct immediate *IM, GLuint start )
{
GLuint count = IM->Count;
GLuint orflag = 0;
/* Compute the flags for the whole buffer.
*/
- for (i = IM->CopyStart ; i < count ; i++) {
+ for (i = start ; i < count ; i++) {
andflag &= IM->Flag[i];
orflag |= IM->Flag[i];
}
/* It is possible there will be data in the buffer arising from
* calls like 'glNormal', 'glMaterial' that occur after the final
* glVertex, glEval, etc. Additionally, a buffer can consist of
- * only a single glMaterial call, in which case IM->Start ==
+ * eg. a single glMaterial call, in which case IM->Start ==
* IM->Count, but the buffer is definitely not empty.
*/
- if (IM->Flag[i] & VERT_DATA) {
+ if (IM->Flag[i] & VERT_BITS_DATA) {
IM->LastData++;
orflag |= IM->Flag[i];
}
- IM->Flag[IM->LastData+1] |= VERT_END_VB;
+ IM->Flag[IM->LastData+1] |= VERT_BIT_END_VB;
IM->CopyAndFlag = IM->AndFlag = andflag;
- IM->CopyOrFlag = IM->OrFlag = orflag;
+ IM->OrFlag = orflag;
+ IM->CopyOrFlag = orflag;
+ IM->Evaluated = 0;
}
-
-
-
-/* Note: The 'start' member of the GLvector structs is now redundant
+/**
+ * This is where the vertex data is transfered from the 'struct immediate
+ * into the 'struct vertex_buffer'.
+ *
+ * Note: The 'start' member of the GLvector structs is now redundant
* because we always re-transform copied vertices, and the vectors
* below are set up so that the first copied vertex (if any) appears
- * at position zero.
+ * at position zero.
*/
static void _tnl_vb_bind_immediate( GLcontext *ctx, struct immediate *IM )
{
struct vertex_buffer *VB = &tnl->vb;
struct vertex_arrays *tmp = &tnl->imm_inputs;
GLuint inputs = tnl->pipeline.inputs; /* for copy-to-current */
- GLuint start = IM->CopyStart;
- GLuint count = IM->Count - start;
-
+ const GLuint start = IM->CopyStart;
+ const GLuint count = IM->Count - start;
+
/* TODO: optimize the case where nothing has changed. (Just bind
* tmp to vb).
*/
*/
VB->Count = count;
VB->FirstClipped = IMM_MAXDATA - IM->CopyStart;
- VB->import_data = 0;
+ VB->import_data = NULL;
VB->importable_data = 0;
/* Need an IM->FirstPrimitive?
/* TexCoordPtr's are zeroed in loop below.
*/
- VB->NormalPtr = 0;
- VB->NormalLengthPtr = 0;
- VB->FogCoordPtr = 0;
- VB->EdgeFlag = 0;
- VB->IndexPtr[0] = 0;
- VB->IndexPtr[1] = 0;
- VB->ColorPtr[0] = 0;
- VB->ColorPtr[1] = 0;
- VB->SecondaryColorPtr[0] = 0;
- VB->SecondaryColorPtr[1] = 0;
- VB->Elts = 0;
- VB->MaterialMask = 0;
- VB->Material = 0;
+ VB->NormalPtr = NULL;
+ VB->NormalLengthPtr = NULL;
+ VB->EdgeFlag = NULL;
+ VB->IndexPtr[0] = NULL;
+ VB->IndexPtr[1] = NULL;
+ VB->ColorPtr[0] = NULL;
+ VB->ColorPtr[1] = NULL;
+ VB->SecondaryColorPtr[0] = NULL;
+ VB->SecondaryColorPtr[1] = NULL;
+ VB->Elts = NULL;
+ VB->MaterialMask = NULL;
+ VB->Material = NULL;
/* _tnl_print_vert_flags("copy-orflag", IM->CopyOrFlag); */
/* _tnl_print_vert_flags("orflag", IM->OrFlag); */
/* Setup the initial values of array pointers in the vb.
*/
- if (inputs & VERT_OBJ) {
- tmp->Obj.data = IM->Obj + start;
- tmp->Obj.start = (GLfloat *)(IM->Obj + start);
+ if (inputs & VERT_BIT_POS) {
+ tmp->Obj.data = IM->Attrib[VERT_ATTRIB_POS] + start;
+ tmp->Obj.start = (GLfloat *)(IM->Attrib[VERT_ATTRIB_POS] + start);
tmp->Obj.count = count;
- VB->ObjPtr = &tmp->Obj;
- if ((IM->CopyOrFlag & VERT_OBJ_234) == VERT_OBJ_234)
+ VB->ObjPtr = &tmp->Obj;
+ if ((IM->CopyOrFlag & VERT_BITS_OBJ_234) == VERT_BITS_OBJ_234)
tmp->Obj.size = 4;
- else if ((IM->CopyOrFlag & VERT_OBJ_234) == VERT_OBJ_23)
+ else if ((IM->CopyOrFlag & VERT_BITS_OBJ_234) == VERT_BITS_OBJ_23)
tmp->Obj.size = 3;
else
tmp->Obj.size = 2;
}
- if (inputs & VERT_NORM) {
- tmp->Normal.data = IM->Normal + start;
- tmp->Normal.start = (GLfloat *)(IM->Normal + start);
+ if (inputs & VERT_BIT_NORMAL) {
+ tmp->Normal.data = IM->Attrib[VERT_ATTRIB_NORMAL] + start;
+ tmp->Normal.start = (GLfloat *) (IM->Attrib[VERT_ATTRIB_NORMAL] + start);
tmp->Normal.count = count;
VB->NormalPtr = &tmp->Normal;
- if (IM->NormalLengths)
- VB->NormalLengthPtr = IM->NormalLengths + start;
+ if (IM->NormalLengthPtr)
+ VB->NormalLengthPtr = IM->NormalLengthPtr + start;
}
- if (inputs & VERT_INDEX) {
+ if (inputs & VERT_BIT_INDEX) {
tmp->Index.count = count;
tmp->Index.data = IM->Index + start;
tmp->Index.start = IM->Index + start;
VB->IndexPtr[0] = &tmp->Index;
}
- if (inputs & VERT_FOG_COORD) {
- tmp->FogCoord.data = IM->FogCoord + start;
- tmp->FogCoord.start = IM->FogCoord + start;
+ if (inputs & VERT_BIT_FOG) {
+ tmp->FogCoord.data = IM->Attrib[VERT_ATTRIB_FOG] + start;
+ tmp->FogCoord.start = (GLfloat *) (IM->Attrib[VERT_ATTRIB_FOG] + start);
tmp->FogCoord.count = count;
VB->FogCoordPtr = &tmp->FogCoord;
}
- if (inputs & VERT_SPEC_RGB) {
- tmp->SecondaryColor.data = IM->SecondaryColor + start;
- tmp->SecondaryColor.start = (GLubyte *)(IM->SecondaryColor + start);
- tmp->SecondaryColor.count = count;
+ if (inputs & VERT_BIT_COLOR1) {
+ tmp->SecondaryColor.Ptr = IM->Attrib[VERT_ATTRIB_COLOR1] + start;
VB->SecondaryColorPtr[0] = &tmp->SecondaryColor;
}
- if (inputs & VERT_EDGE) {
+ if (inputs & VERT_BIT_EDGEFLAG) {
VB->EdgeFlag = IM->EdgeFlag + start;
}
- if (inputs & VERT_RGBA) {
- tmp->Color.data = IM->Color + start;
- tmp->Color.start = (GLubyte *)(IM->Color + start);
- tmp->Color.count = count;
+ if (inputs & VERT_BIT_COLOR0) {
+ if (IM->CopyOrFlag & VERT_BIT_COLOR0) {
+ tmp->Color.Ptr = IM->Attrib[VERT_ATTRIB_COLOR0] + start;
+ tmp->Color.StrideB = 4 * sizeof(GLfloat);
+ tmp->Color.Flags = 0;
+ }
+ else {
+ tmp->Color.Ptr = ctx->Current.Attrib[VERT_ATTRIB_COLOR0];
+ tmp->Color.StrideB = 0;
+ tmp->Color.Flags = CA_CLIENT_DATA; /* hack */
+ VB->import_source = IM;
+ VB->importable_data |= VERT_BIT_COLOR0;
+ VB->import_data = _tnl_upgrade_current_data;
+ }
VB->ColorPtr[0] = &tmp->Color;
}
- if (inputs & VERT_TEX_ANY) {
+ if (inputs & VERT_BITS_TEX_ANY) {
GLuint i;
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) {
- VB->TexCoordPtr[i] = 0;
- if (inputs & VERT_TEX(i)) {
+ VB->TexCoordPtr[i] = NULL;
+ if (inputs & VERT_BIT_TEX(i)) {
tmp->TexCoord[i].count = count;
- tmp->TexCoord[i].data = IM->TexCoord[i] + start;
- tmp->TexCoord[i].start = (GLfloat *)(IM->TexCoord[i] + start);
+ tmp->TexCoord[i].data = IM->Attrib[VERT_ATTRIB_TEX0 + i] + start;
+ tmp->TexCoord[i].start = (GLfloat *)(IM->Attrib[VERT_ATTRIB_TEX0 + i] + start);
tmp->TexCoord[i].size = 2;
if (IM->TexSize & TEX_SIZE_3(i)) {
tmp->TexCoord[i].size = 3;
- if (IM->TexSize & TEX_SIZE_4(i))
+ if (IM->TexSize & TEX_SIZE_4(i))
tmp->TexCoord[i].size = 4;
}
VB->TexCoordPtr[i] = &tmp->TexCoord[i];
}
}
- if ((inputs & VERT_MATERIAL) && IM->Material) {
+ if ((inputs & VERT_BIT_MATERIAL) && IM->Material) {
VB->MaterialMask = IM->MaterialMask + start;
VB->Material = IM->Material + start;
- }
+ }
+
+ /* GL_NV_vertex_program */
+ if (ctx->VertexProgram.Enabled) {
+ GLuint attr;
+ for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
+ tmp->Attribs[attr].count = count;
+ tmp->Attribs[attr].data = IM->Attrib[attr] + start;
+ tmp->Attribs[attr].start = (GLfloat *) (IM->Attrib[attr] + start);
+ tmp->Attribs[attr].size = 4;
+ VB->AttribPtr[attr] = &(tmp->Attribs[attr]);
+ }
+ }
}
-/* Called by exec_cassette and execute_compiled_cassette.
+/**
+ * Called by exec_vert_cassette, execute_compiled_cassette, but not
+ * exec_elt_cassette.
*/
void _tnl_run_cassette( GLcontext *ctx, struct immediate *IM )
{
_tnl_vb_bind_immediate( ctx, IM );
- if (IM->CopyOrFlag & VERT_EVAL_ANY)
- _tnl_eval_vb( ctx,
- IM->Obj + IM->CopyStart,
- IM->CopyOrFlag,
- IM->CopyAndFlag );
+ if (IM->OrFlag & VERT_BITS_EVAL_ANY)
+ _tnl_eval_immediate( ctx, IM );
-
/* Invalidate all stored data before and after run:
*/
tnl->pipeline.run_input_changes |= tnl->pipeline.inputs;
- _tnl_run_pipeline( ctx );
+ tnl->Driver.RunPipeline( ctx );
tnl->pipeline.run_input_changes |= tnl->pipeline.inputs;
- copy_to_current( ctx, IM, IM->OrFlag );
+ _tnl_copy_to_current( ctx, IM, IM->OrFlag, IM->LastData );
}
+/**
+ * Called for regular vertex cassettes.
+ */
+static void exec_vert_cassette( GLcontext *ctx, struct immediate *IM )
+{
+/* fprintf(stderr, "%s\n", __FUNCTION__); */
+ if (IM->FlushElt) {
+ /* Orflag is computed twice, but only reach this code if app is
+ * using a mixture of glArrayElement() and glVertex() while
+ * arrays are locked (else would be in exec_elt_cassette now).
+ */
+ ASSERT(ctx->Array.LockCount);
+ ASSERT(IM->FlushElt == FLUSH_ELT_LAZY);
+ _tnl_translate_array_elts( ctx, IM, IM->CopyStart, IM->Count );
+ _tnl_compute_orflag( IM, IM->CopyStart );
+ }
-/* Called for pure, locked VERT_ELT cassettes instead of
- * _tnl_run_cassette.
+ _tnl_fixup_input( ctx, IM );
+/* _tnl_print_cassette( IM ); */
+ _tnl_run_cassette( ctx, IM );
+}
+
+
+/* Called for pure, locked VERT_BIT_ELT cassettes instead of
+ * _tnl_run_cassette.
*/
static void exec_elt_cassette( GLcontext *ctx, struct immediate *IM )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct vertex_buffer *VB = &tnl->vb;
+/* fprintf(stderr, "%s\n", __FUNCTION__); */
+
_tnl_vb_bind_arrays( ctx, ctx->Array.LockFirst, ctx->Array.LockCount );
+ /* Take only elements and primitive information from the immediate:
+ */
VB->Elts = IM->Elt + IM->CopyStart;
VB->Primitive = IM->Primitive + IM->CopyStart;
VB->PrimitiveLength = IM->PrimitiveLength + IM->CopyStart;
/* Run the pipeline. No input changes as a result of this action.
*/
- _tnl_run_pipeline( ctx );
+ tnl->Driver.RunPipeline( ctx );
- /* Still need to update current values: (TODO - copy from VB)
- * TODO: delay this until FlushVertices
+ /* Still need to update current values:
*/
if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) {
- _tnl_translate_array_elts( ctx, IM, IM->LastData, IM->LastData );
- copy_to_current( ctx, IM, ctx->Array._Enabled );
- }
-}
-
-/* Called for cassettes where CopyStart == Count -- no need to run the
- * pipeline.
- */
-void _tnl_run_empty_cassette( GLcontext *ctx, struct immediate *IM )
-{
- copy_to_current( ctx, IM, IM->OrFlag );
-
- if (IM->OrFlag & (VERT_RGBA|VERT_MATERIAL)) {
- GLuint start = IM->CopyStart;
-
- if (IM->OrFlag & VERT_MATERIAL)
- gl_update_material( ctx, IM->Material[start],
- IM->MaterialMask[start] );
-
- if (IM->OrFlag & VERT_RGBA)
- if (ctx->Light.ColorMaterialEnabled)
- gl_update_color_material( ctx, ctx->Current.Color );
-
- gl_validate_all_lighting_tables( ctx );
+ _tnl_translate_array_elts( ctx, IM, IM->LastData, IM->LastData );
+ _tnl_copy_to_current( ctx, IM, ctx->Array._Enabled, IM->LastData );
}
}
-/* Called for regular vertex cassettes.
- */
-static void exec_vert_cassette( GLcontext *ctx, struct immediate *IM )
+static void
+exec_empty_cassette( GLcontext *ctx, struct immediate *IM )
{
- if (IM->OrFlag & VERT_ELT) {
- GLuint andflag = ~0;
- GLuint i;
- GLuint start = IM->FlushElt ? IM->LastPrimitive : IM->CopyStart;
- _tnl_translate_array_elts( ctx, IM, start, IM->Count );
+ if (IM->FlushElt)
+ _tnl_translate_array_elts( ctx, IM, IM->CopyStart, IM->CopyStart );
- /* Need to recompute andflag.
- */
- if (IM->CopyAndFlag & VERT_ELT)
- IM->CopyAndFlag |= ctx->Array._Enabled;
- else {
- for (i = IM->CopyStart ; i < IM->Count ; i++)
- andflag &= IM->Flag[i];
- IM->CopyAndFlag = andflag;
- }
- }
-
- _tnl_fixup_input( ctx, IM );
-/* _tnl_print_cassette( IM ); */
- _tnl_run_cassette( ctx, IM );
+ _tnl_copy_to_current( ctx, IM, IM->OrFlag, IM->LastData );
}
-/* Called for all cassettes when not compiling or playing a display
+/**
+ * Called for all cassettes when not compiling or playing a display
* list.
*/
void _tnl_execute_cassette( GLcontext *ctx, struct immediate *IM )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
- ASSERT(tnl->ExecCopySource == IM);
-
- _tnl_compute_orflag( IM );
-
-/* _tnl_print_cassette( IM ); */
-
- /* Mark the last primitive:
- */
- IM->PrimitiveLength[IM->LastPrimitive] = IM->Count - IM->LastPrimitive;
- ASSERT(IM->Primitive[IM->LastPrimitive] & PRIM_LAST);
-
+ _tnl_compute_orflag( IM, IM->Start );
+ _tnl_copy_immediate_vertices( ctx, IM );
+ _tnl_get_exec_copy_verts( ctx, IM );
if (tnl->pipeline.build_state_changes)
_tnl_validate_pipeline( ctx );
- _tnl_get_exec_copy_verts( ctx, IM );
-
if (IM->CopyStart == IM->Count) {
- if (IM->OrFlag & VERT_ELT)
- _tnl_translate_array_elts( ctx, IM, IM->CopyStart, IM->CopyStart );
-
- _tnl_fixup_input( ctx, IM ); /* shouldn't be needed? (demos/fire) */
- _tnl_run_empty_cassette( ctx, IM );
+ exec_empty_cassette( ctx, IM );
}
- else if ((IM->OrFlag & VERT_DATA) == VERT_ELT &&
+ else if ((IM->CopyOrFlag & VERT_BITS_DATA) == VERT_BIT_ELT &&
ctx->Array.LockCount &&
ctx->Array.Vertex.Enabled) {
exec_elt_cassette( ctx, IM );
exec_vert_cassette( ctx, IM );
}
- _tnl_reset_input( ctx,
- IMM_MAX_COPIED_VERTS,
- IM->BeginState & (VERT_BEGIN_0|VERT_BEGIN_1),
- IM->SavedBeginState );
-
- /* Copy vertices and primitive information to immediate before it
- * can be overwritten.
+ /* Only reuse the immediate if there are no copied vertices living
+ * inside it:
*/
- _tnl_copy_immediate_vertices( ctx, IM );
+ {
+ GLuint begin_state = IM->BeginState & (VERT_BEGIN_0|VERT_BEGIN_1);
+ GLuint saved_begin_state = IM->SavedBeginState;
+
+ if (--IM->ref_count != 0) {
+ IM = _tnl_alloc_immediate( ctx );
+ SET_IMMEDIATE( ctx, IM );
+ }
+
+ IM->ref_count++;
+
+ _tnl_reset_exec_input( ctx, IMM_MAX_COPIED_VERTS,
+ begin_state, saved_begin_state );
+ }
if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1)
ctx->Driver.NeedFlush &= ~FLUSH_STORED_VERTICES;
-/* Setup vector pointers that will be used to bind immediates to VB's.
+/**
+ * Setup vector pointers that will be used to bind immediates to VB's.
*/
void _tnl_imm_init( GLcontext *ctx )
{
tnl->ExecCopyTexSize = 0;
tnl->ExecCopyCount = 0;
- tnl->ExecCopySource = TNL_CURRENT_IM(ctx);
- TNL_CURRENT_IM(ctx)->ref_count++;
+ tnl->ExecCopySource = 0;
TNL_CURRENT_IM(ctx)->CopyStart = IMM_MAX_COPIED_VERTS;
- gl_vector4f_init( &tmp->Obj, 0, 0 );
- gl_vector3f_init( &tmp->Normal, 0, 0 );
- gl_vector4ub_init( &tmp->Color, 0, 0 );
- gl_vector4ub_init( &tmp->SecondaryColor, 0, 0 );
- gl_vector1f_init( &tmp->FogCoord, 0, 0 );
- gl_vector1ui_init( &tmp->Index, 0, 0 );
- gl_vector1ub_init( &tmp->EdgeFlag, 0, 0 );
+ _mesa_vector4f_init( &tmp->Obj, 0, 0 );
+ _mesa_vector4f_init( &tmp->Normal, 0, 0 );
+
+ tmp->Color.Ptr = NULL;
+ tmp->Color.Type = GL_FLOAT;
+ tmp->Color.Size = 4;
+ tmp->Color.Stride = 0;
+ tmp->Color.StrideB = 4 * sizeof(GLfloat);
+ tmp->Color.Flags = 0;
+
+ tmp->SecondaryColor.Ptr = NULL;
+ tmp->SecondaryColor.Type = GL_FLOAT;
+ tmp->SecondaryColor.Size = 4;
+ tmp->SecondaryColor.Stride = 0;
+ tmp->SecondaryColor.StrideB = 4 * sizeof(GLfloat);
+ tmp->SecondaryColor.Flags = 0;
- for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
- gl_vector4f_init( &tmp->TexCoord[i], 0, 0);
+ _mesa_vector4f_init( &tmp->FogCoord, 0, 0 );
+ _mesa_vector1ui_init( &tmp->Index, 0, 0 );
+ _mesa_vector1ub_init( &tmp->EdgeFlag, 0, 0 );
+
+ for (i = 0; i < ctx->Const.MaxTextureUnits; i++)
+ _mesa_vector4f_init( &tmp->TexCoord[i], 0, 0);
/* Install the first immediate. Intially outside begin/end.
*/
- _tnl_reset_input( ctx, IMM_MAX_COPIED_VERTS, 0, 0 );
+ _tnl_reset_exec_input( ctx, IMM_MAX_COPIED_VERTS, 0, 0 );
tnl->ReplayHardBeginEnd = 0;
_tnl_imm_vtxfmt_init( ctx );
}
+/**
+ * Deallocate the immediate-mode buffer for the given context, if
+ * its reference count goes to zero.
+ */
void _tnl_imm_destroy( GLcontext *ctx )
{
- if (TNL_CURRENT_IM(ctx))
- _tnl_free_immediate( TNL_CURRENT_IM(ctx) );
-
+ if (TNL_CURRENT_IM(ctx)) {
+ TNL_CURRENT_IM(ctx)->ref_count--;
+ if (TNL_CURRENT_IM(ctx)->ref_count == 0)
+ _tnl_free_immediate( TNL_CURRENT_IM(ctx) );
+ /*
+ * Don't use SET_IMMEDIATE here, or else we'll whack the
+ * _tnl_CurrentInput pointer - not good when another
+ * context has already been made current.
+ * So we just set the context's own tnl immediate pointer
+ * to 0.
+ */
+ ctx->swtnl_im = NULL;
+ }
}