From ae0eaf93e092ac8e8b1c98f3e986de96940663fa Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Mon, 24 Nov 2003 15:23:18 +0000 Subject: Merge vtx-0-2-branch --- src/mesa/tnl/t_array_api.c | 130 ++-- src/mesa/tnl/t_array_import.c | 325 +++------ src/mesa/tnl/t_context.c | 63 +- src/mesa/tnl/t_context.h | 550 +++++++------- src/mesa/tnl/t_imm_alloc.c | 151 ---- src/mesa/tnl/t_imm_alloc.h | 39 - src/mesa/tnl/t_imm_debug.c | 182 ----- src/mesa/tnl/t_imm_debug.h | 38 - src/mesa/tnl/t_imm_dlist.c | 667 ----------------- src/mesa/tnl/t_imm_dlist.h | 44 -- src/mesa/tnl/t_imm_elt.h | 45 -- src/mesa/tnl/t_imm_eval.h | 38 - src/mesa/tnl/t_imm_exec.c | 586 --------------- src/mesa/tnl/t_imm_exec.h | 68 -- src/mesa/tnl/t_imm_fixup.c | 786 -------------------- src/mesa/tnl/t_imm_fixup.h | 56 -- src/mesa/tnl/t_pipeline.c | 18 +- src/mesa/tnl/t_pipeline.h | 22 +- src/mesa/tnl/t_save_api.c | 1580 ++++++++++++++++++++++++++++++++++++++++ src/mesa/tnl/t_save_api.h | 58 ++ src/mesa/tnl/t_save_loopback.c | 301 ++++++++ src/mesa/tnl/t_save_playback.c | 218 ++++++ src/mesa/tnl/t_vb_cliptmp.h | 10 +- src/mesa/tnl/t_vb_fog.c | 16 +- src/mesa/tnl/t_vb_light.c | 274 +++---- src/mesa/tnl/t_vb_lighttmp.h | 461 ++++-------- src/mesa/tnl/t_vb_normals.c | 16 +- src/mesa/tnl/t_vb_points.c | 14 +- src/mesa/tnl/t_vb_program.c | 109 +-- src/mesa/tnl/t_vb_render.c | 53 +- src/mesa/tnl/t_vb_rendertmp.h | 4 - src/mesa/tnl/t_vb_texgen.c | 32 +- src/mesa/tnl/t_vb_texmat.c | 14 +- src/mesa/tnl/t_vb_vertex.c | 56 +- src/mesa/tnl/t_vtx_api.c | 1319 ++++++++++++++++++++------------- src/mesa/tnl/t_vtx_api.h | 208 +----- src/mesa/tnl/t_vtx_eval.c | 253 +++++++ src/mesa/tnl/t_vtx_exec.c | 726 +++++------------- src/mesa/tnl/t_vtx_sse.c | 91 --- src/mesa/tnl/t_vtx_x86.c | 704 ------------------ 40 files changed, 4304 insertions(+), 6021 deletions(-) delete mode 100644 src/mesa/tnl/t_imm_alloc.c delete mode 100644 src/mesa/tnl/t_imm_alloc.h delete mode 100644 src/mesa/tnl/t_imm_debug.c delete mode 100644 src/mesa/tnl/t_imm_debug.h delete mode 100644 src/mesa/tnl/t_imm_dlist.c delete mode 100644 src/mesa/tnl/t_imm_dlist.h delete mode 100644 src/mesa/tnl/t_imm_elt.h delete mode 100644 src/mesa/tnl/t_imm_eval.h delete mode 100644 src/mesa/tnl/t_imm_exec.c delete mode 100644 src/mesa/tnl/t_imm_exec.h delete mode 100644 src/mesa/tnl/t_imm_fixup.c delete mode 100644 src/mesa/tnl/t_imm_fixup.h create mode 100644 src/mesa/tnl/t_save_api.c create mode 100644 src/mesa/tnl/t_save_api.h create mode 100644 src/mesa/tnl/t_save_loopback.c create mode 100644 src/mesa/tnl/t_save_playback.c create mode 100644 src/mesa/tnl/t_vtx_eval.c delete mode 100644 src/mesa/tnl/t_vtx_sse.c delete mode 100644 src/mesa/tnl/t_vtx_x86.c (limited to 'src/mesa/tnl') diff --git a/src/mesa/tnl/t_array_api.c b/src/mesa/tnl/t_array_api.c index b0228b74c7f..f9f5fe99511 100644 --- a/src/mesa/tnl/t_array_api.c +++ b/src/mesa/tnl/t_array_api.c @@ -40,38 +40,40 @@ #include "t_array_api.h" #include "t_array_import.h" -#include "t_imm_api.h" -#include "t_imm_exec.h" +#include "t_save_api.h" #include "t_context.h" #include "t_pipeline.h" static void fallback_drawarrays( GLcontext *ctx, GLenum mode, GLint start, GLsizei count ) { - if (_tnl_hard_begin( ctx, mode )) { - GLint i; - for (i = start; i < count; i++) - glArrayElement( i ); - glEnd(); - } + GLint i; + + assert(!ctx->CompileFlag); + assert(ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1); + + glBegin(mode); + for (i = start; i < count; i++) + glArrayElement( i ); + glEnd(); } static void fallback_drawelements( GLcontext *ctx, GLenum mode, GLsizei count, const GLuint *indices) { - if (_tnl_hard_begin(ctx, mode)) { - GLint i; - if (ctx->Array.ElementArrayBufferObj->Name) { - /* use indices in the buffer object */ - ASSERT(ctx->Array.ElementArrayBufferObj->Data); - indices = (const GLuint *) ctx->Array.ElementArrayBufferObj->Data; - } - for (i = 0 ; i < count ; i++) { - glArrayElement( indices[i] ); - } - glEnd(); + GLint i; + + assert(!ctx->CompileFlag); + assert(ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1); + + /* Here, indices will already reflect the buffer object if active */ + + glBegin(mode); + for (i = 0 ; i < count ; i++) { + glArrayElement( indices[i] ); } + glEnd(); } @@ -81,22 +83,26 @@ static void _tnl_draw_range_elements( GLcontext *ctx, GLenum mode, { TNLcontext *tnl = TNL_CONTEXT(ctx); + struct tnl_prim prim; int i; FLUSH_CURRENT( ctx, 0 ); - /* _mesa_debug(ctx, "%s\n", __FUNCTION__); */ if (tnl->pipeline.build_state_changes) _tnl_validate_pipeline( ctx ); _tnl_vb_bind_arrays( ctx, start, end ); - tnl->vb.FirstPrimitive = 0; - tnl->vb.Primitive[0] = mode | PRIM_BEGIN | PRIM_END | PRIM_LAST; - tnl->vb.PrimitiveLength[0] = count; + tnl->vb.Primitive = &prim; + tnl->vb.Primitive[0].mode = mode | PRIM_BEGIN | PRIM_END; + tnl->vb.Primitive[0].start = 0; + tnl->vb.Primitive[0].count = count; + tnl->vb.PrimitiveCount = 1; + tnl->vb.Elts = (GLuint *)indices; - for (i = 0 ; i < count ; i++) - indices[i] -= start; + if (start) + for (i = 0 ; i < count ; i++) + indices[i] -= start; if (ctx->Array.LockCount) tnl->Driver.RunPipeline( ctx ); @@ -108,8 +114,9 @@ static void _tnl_draw_range_elements( GLcontext *ctx, GLenum mode, tnl->pipeline.run_input_changes |= ctx->Array._Enabled; } - for (i = 0 ; i < count ; i++) - indices[i] += start; + if (start) + for (i = 0 ; i < count ; i++) + indices[i] += start; } @@ -122,7 +129,6 @@ _tnl_DrawArrays(GLenum mode, GLint start, GLsizei count) { GET_CURRENT_CONTEXT(ctx); TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; GLuint thresh = (ctx->Driver.NeedFlush & FLUSH_STORED_VERTICES) ? 30 : 10; if (MESA_VERBOSE & VERBOSE_API) @@ -136,10 +142,9 @@ _tnl_DrawArrays(GLenum mode, GLint start, GLsizei count) if (tnl->pipeline.build_state_changes) _tnl_validate_pipeline( ctx ); - if (ctx->CompileFlag) { - fallback_drawarrays( ctx, mode, start, start + count ); - } - else if (!ctx->Array.LockCount && (GLuint) count < thresh) { + assert(!ctx->CompileFlag); + + if (!ctx->Array.LockCount && (GLuint) count < thresh) { /* Small primitives: attempt to share a vb (at the expense of * using the immediate interface). */ @@ -148,6 +153,8 @@ _tnl_DrawArrays(GLenum mode, GLint start, GLsizei count) else if (ctx->Array.LockCount && count < (GLint) ctx->Const.MaxArrayLockSize) { + struct tnl_prim prim; + /* Locked primitives which can fit in a single vertex buffer: */ FLUSH_CURRENT( ctx, 0 ); @@ -160,9 +167,13 @@ _tnl_DrawArrays(GLenum mode, GLint start, GLsizei count) /* Locked drawarrays. Reuse any previously transformed data. */ _tnl_vb_bind_arrays( ctx, ctx->Array.LockFirst, ctx->Array.LockCount ); - VB->FirstPrimitive = start; - VB->Primitive[start] = mode | PRIM_BEGIN | PRIM_END | PRIM_LAST; - VB->PrimitiveLength[start] = count; + + tnl->vb.Primitive = &prim; + tnl->vb.Primitive[0].mode = mode | PRIM_BEGIN | PRIM_END; + tnl->vb.Primitive[0].start = start; + tnl->vb.Primitive[0].count = count; + tnl->vb.PrimitiveCount = 1; + tnl->Driver.RunPipeline( ctx ); } else { @@ -237,13 +248,25 @@ _tnl_DrawArrays(GLenum mode, GLint start, GLsizei count) for (j = start + minimum ; j < count ; j += nr + skip ) { + struct tnl_prim prim; + nr = MIN2( bufsz, count - j ); _tnl_vb_bind_arrays( ctx, j - minimum, j + nr ); - VB->FirstPrimitive = 0; - VB->Primitive[0] = mode | PRIM_BEGIN | PRIM_END | PRIM_LAST; - VB->PrimitiveLength[0] = nr + minimum; + tnl->vb.Primitive = &prim; + tnl->vb.Primitive[0].mode = mode; + + if (j == start + minimum) + tnl->vb.Primitive[0].mode |= PRIM_BEGIN; + + if (j + nr + skip >= count) + tnl->vb.Primitive[0].mode |= PRIM_END; + + tnl->vb.Primitive[0].start = 0; + tnl->vb.Primitive[0].count = nr + minimum; + tnl->vb.PrimitiveCount = 1; + tnl->pipeline.run_input_changes |= ctx->Array._Enabled; tnl->Driver.RunPipeline( ctx ); tnl->pipeline.run_input_changes |= ctx->Array._Enabled; @@ -286,12 +309,9 @@ _tnl_DrawRangeElements(GLenum mode, count, type, indices ); - if (ctx->CompileFlag) { - /* Can't do anything when compiling: - */ - fallback_drawelements( ctx, mode, count, ui_indices ); - } - else if (ctx->Array.LockCount) { + assert(!ctx->CompileFlag); + + if (ctx->Array.LockCount) { /* Are the arrays already locked? If so we currently have to look * at the whole locked range. */ @@ -360,12 +380,9 @@ _tnl_DrawElements(GLenum mode, GLsizei count, GLenum type, ui_indices = (GLuint *)_ac_import_elements( ctx, GL_UNSIGNED_INT, count, type, indices ); - if (ctx->CompileFlag) { - /* Can't do anything when compiling: - */ - fallback_drawelements( ctx, mode, count, ui_indices ); - } - else if (ctx->Array.LockCount) { + assert(!ctx->CompileFlag); + + if (ctx->Array.LockCount) { _tnl_draw_range_elements( ctx, mode, ctx->Array.LockFirst, ctx->Array.LockCount, @@ -397,8 +414,8 @@ _tnl_DrawElements(GLenum mode, GLsizei count, GLenum type, void _tnl_array_init( GLcontext *ctx ) { TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_arrays *tmp = &tnl->array_inputs; - GLvertexformat *vfmt = &(TNL_CONTEXT(ctx)->vtxfmt); + struct tnl_vertex_arrays *tmp = &tnl->array_inputs; + GLvertexformat *vfmt = &(TNL_CONTEXT(ctx)->exec_vtxfmt); GLuint i; vfmt->DrawArrays = _tnl_DrawArrays; @@ -410,14 +427,10 @@ void _tnl_array_init( GLcontext *ctx ) _mesa_vector4f_init( &tmp->Obj, 0, 0 ); _mesa_vector4f_init( &tmp->Normal, 0, 0 ); _mesa_vector4f_init( &tmp->FogCoord, 0, 0 ); - _mesa_vector1ui_init( &tmp->Index, 0, 0 ); - _mesa_vector1ub_init( &tmp->EdgeFlag, 0, 0 ); + _mesa_vector4f_init( &tmp->Index, 0, 0 ); for (i = 0; i < ctx->Const.MaxTextureUnits; i++) _mesa_vector4f_init( &tmp->TexCoord[i], 0, 0); - - tnl->tmp_primitive = (GLuint *)MALLOC(sizeof(GLuint)*tnl->vb.Size); - tnl->tmp_primitive_length = (GLuint *)MALLOC(sizeof(GLuint)*tnl->vb.Size); } @@ -427,7 +440,4 @@ void _tnl_array_init( GLcontext *ctx ) */ void _tnl_array_destroy( GLcontext *ctx ) { - TNLcontext *tnl = TNL_CONTEXT(ctx); - if (tnl->tmp_primitive_length) FREE(tnl->tmp_primitive_length); - if (tnl->tmp_primitive) FREE(tnl->tmp_primitive); } diff --git a/src/mesa/tnl/t_array_import.c b/src/mesa/tnl/t_array_import.c index a888894f747..16874dfb9a6 100644 --- a/src/mesa/tnl/t_array_import.c +++ b/src/mesa/tnl/t_array_import.c @@ -37,7 +37,6 @@ #include "t_array_import.h" #include "t_context.h" -#include "t_imm_debug.h" static void _tnl_import_vertex( GLcontext *ctx, @@ -46,7 +45,7 @@ static void _tnl_import_vertex( GLcontext *ctx, { struct gl_client_array *tmp; GLboolean is_writeable = 0; - struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; + struct tnl_vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; const GLubyte *data; tmp = _ac_import_vertex(ctx, @@ -56,21 +55,11 @@ static void _tnl_import_vertex( GLcontext *ctx, writeable, &is_writeable); -#if 0 - /* guess we really don't need to add pointers here - BP */ - data = ADD_POINTERS(tmp->Ptr, tmp->BufferObj->Data); -#else data = tmp->Ptr; -#endif inputs->Obj.data = (GLfloat (*)[4]) data; inputs->Obj.start = (GLfloat *) data; inputs->Obj.stride = tmp->StrideB; inputs->Obj.size = tmp->Size; - inputs->Obj.flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE); - if (inputs->Obj.stride != 4*sizeof(GLfloat)) - inputs->Obj.flags |= VEC_BAD_STRIDE; - if (!is_writeable) - inputs->Obj.flags |= VEC_NOT_WRITEABLE; } static void _tnl_import_normal( GLcontext *ctx, @@ -79,73 +68,72 @@ static void _tnl_import_normal( GLcontext *ctx, { struct gl_client_array *tmp; GLboolean is_writeable = 0; - struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; + struct tnl_vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; const GLubyte *data; tmp = _ac_import_normal(ctx, GL_FLOAT, stride ? 3*sizeof(GLfloat) : 0, writeable, &is_writeable); -#if 0 - data = ADD_POINTERS(tmp->Ptr, tmp->BufferObj->Data); -#else data = tmp->Ptr; -#endif inputs->Normal.data = (GLfloat (*)[4]) data; inputs->Normal.start = (GLfloat *) data; inputs->Normal.stride = tmp->StrideB; - inputs->Normal.flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE); - if (inputs->Normal.stride != 3*sizeof(GLfloat)) - inputs->Normal.flags |= VEC_BAD_STRIDE; - if (!is_writeable) - inputs->Normal.flags |= VEC_NOT_WRITEABLE; } static void _tnl_import_color( GLcontext *ctx, - GLenum type, GLboolean writeable, GLboolean stride ) { struct gl_client_array *tmp; GLboolean is_writeable = 0; - struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; + struct tnl_vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; + GLubyte *data; tmp = _ac_import_color(ctx, - type, + GL_FLOAT, stride ? 4*sizeof(GLfloat) : 0, 4, writeable, &is_writeable); - inputs->Color = *tmp; + data = tmp->Ptr; + inputs->Color.data = (GLfloat (*)[4]) data; + inputs->Color.start = (GLfloat *) data; + inputs->Color.stride = tmp->StrideB; + inputs->Color.size = tmp->Size; } static void _tnl_import_secondarycolor( GLcontext *ctx, - GLenum type, GLboolean writeable, GLboolean stride ) { struct gl_client_array *tmp; GLboolean is_writeable = 0; - struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; + struct tnl_vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; + GLubyte *data; tmp = _ac_import_secondarycolor(ctx, - type, + GL_FLOAT, stride ? 4*sizeof(GLfloat) : 0, 4, writeable, &is_writeable); - inputs->SecondaryColor = *tmp; + data = tmp->Ptr; + inputs->SecondaryColor.data = (GLfloat (*)[4]) data; + inputs->SecondaryColor.start = (GLfloat *) data; + inputs->SecondaryColor.stride = tmp->StrideB; + inputs->SecondaryColor.size = tmp->Size; } static void _tnl_import_fogcoord( GLcontext *ctx, GLboolean writeable, GLboolean stride ) { - struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; + struct tnl_vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; struct gl_client_array *tmp; GLboolean is_writeable = 0; const GLubyte *data; @@ -154,47 +142,29 @@ static void _tnl_import_fogcoord( GLcontext *ctx, stride ? sizeof(GLfloat) : 0, writeable, &is_writeable); -#if 0 - data = ADD_POINTERS(tmp->Ptr, tmp->BufferObj->Data); -#else data = tmp->Ptr; -#endif inputs->FogCoord.data = (GLfloat (*)[4]) data; inputs->FogCoord.start = (GLfloat *) data; inputs->FogCoord.stride = tmp->StrideB; - inputs->FogCoord.flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE); - if (inputs->FogCoord.stride != sizeof(GLfloat)) - inputs->FogCoord.flags |= VEC_BAD_STRIDE; - if (!is_writeable) - inputs->FogCoord.flags |= VEC_NOT_WRITEABLE; } static void _tnl_import_index( GLcontext *ctx, GLboolean writeable, GLboolean stride ) { - struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; + struct tnl_vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; struct gl_client_array *tmp; GLboolean is_writeable = 0; const GLubyte *data; - tmp = _ac_import_index(ctx, GL_UNSIGNED_INT, - stride ? sizeof(GLuint) : 0, writeable, + tmp = _ac_import_index(ctx, GL_FLOAT, + stride ? sizeof(GLfloat) : 0, writeable, &is_writeable); -#if 0 - data = ADD_POINTERS(tmp->Ptr, tmp->BufferObj->Data); -#else data = tmp->Ptr; -#endif - inputs->Index.data = (GLuint *) data; - inputs->Index.start = (GLuint *) data; + inputs->Index.data = (GLfloat (*)[4]) data; + inputs->Index.start = (GLfloat *) data; inputs->Index.stride = tmp->StrideB; - inputs->Index.flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE); - if (inputs->Index.stride != sizeof(GLuint)) - inputs->Index.flags |= VEC_BAD_STRIDE; - if (!is_writeable) - inputs->Index.flags |= VEC_NOT_WRITEABLE; } @@ -203,7 +173,7 @@ static void _tnl_import_texcoord( GLcontext *ctx, GLboolean writeable, GLboolean stride ) { - struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; + struct tnl_vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; struct gl_client_array *tmp; GLboolean is_writeable = 0; const GLubyte *data; @@ -214,20 +184,11 @@ static void _tnl_import_texcoord( GLcontext *ctx, writeable, &is_writeable); -#if 0 - data = ADD_POINTERS(tmp->Ptr, tmp->BufferObj->Data); -#else data = tmp->Ptr; -#endif inputs->TexCoord[unit].data = (GLfloat (*)[4]) data; inputs->TexCoord[unit].start = (GLfloat *) data; inputs->TexCoord[unit].stride = tmp->StrideB; inputs->TexCoord[unit].size = tmp->Size; - inputs->TexCoord[unit].flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE); - if (inputs->TexCoord[unit].stride != 4*sizeof(GLfloat)) - inputs->TexCoord[unit].flags |= VEC_BAD_STRIDE; - if (!is_writeable) - inputs->TexCoord[unit].flags |= VEC_NOT_WRITEABLE; } @@ -235,29 +196,18 @@ static void _tnl_import_edgeflag( GLcontext *ctx, GLboolean writeable, GLboolean stride ) { - struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; + struct tnl_vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; struct gl_client_array *tmp; GLboolean is_writeable = 0; const GLubyte *data; tmp = _ac_import_edgeflag(ctx, GL_UNSIGNED_BYTE, - stride ? sizeof(GLubyte) : 0, + sizeof(GLubyte), 0, &is_writeable); -#if 0 - data = ADD_POINTERS(tmp->Ptr, tmp->BufferObj->Data); -#else data = tmp->Ptr; -#endif - inputs->EdgeFlag.data = (GLubyte *) data; - inputs->EdgeFlag.start = (GLubyte *) data; - inputs->EdgeFlag.stride = tmp->StrideB; - inputs->EdgeFlag.flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE); - if (inputs->EdgeFlag.stride != sizeof(GLubyte)) - inputs->EdgeFlag.flags |= VEC_BAD_STRIDE; - if (!is_writeable) - inputs->EdgeFlag.flags |= VEC_NOT_WRITEABLE; + inputs->EdgeFlag = (GLubyte *) data; } @@ -267,7 +217,7 @@ static void _tnl_import_attrib( GLcontext *ctx, GLboolean writeable, GLboolean stride ) { - struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; + struct tnl_vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; struct gl_client_array *tmp; GLboolean is_writeable = 0; const GLubyte *data; @@ -278,98 +228,15 @@ static void _tnl_import_attrib( GLcontext *ctx, writeable, &is_writeable); -#if 0 - data = ADD_POINTERS(tmp->Ptr, tmp->BufferObj->Data); -#else data = tmp->Ptr; -#endif inputs->Attribs[index].data = (GLfloat (*)[4]) data; inputs->Attribs[index].start = (GLfloat *) data; inputs->Attribs[index].stride = tmp->StrideB; inputs->Attribs[index].size = tmp->Size; - inputs->Attribs[index].flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE); - if (inputs->Attribs[index].stride != 4 * sizeof(GLfloat)) - inputs->Attribs[index].flags |= VEC_BAD_STRIDE; - if (!is_writeable) - inputs->Attribs[index].flags |= VEC_NOT_WRITEABLE; } -/** - * Callback for VB stages that need to improve the quality of arrays - * bound to the VB. This is only necessary for client arrays which - * have not been transformed at any point in the pipeline. - * \param required - bitmask of VERT_*_BIT flags - * \param flags - bitmask of VEC_* flags (ex: VEC_NOT_WRITABLE) - */ -static void _tnl_upgrade_client_data( GLcontext *ctx, - GLuint required, - GLuint flags ) -{ - GLuint i; - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; - GLboolean writeable = (flags & VEC_NOT_WRITEABLE) != 0; - GLboolean stride = (flags & VEC_BAD_STRIDE) != 0; - struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; - GLuint ca_flags = 0; - (void) inputs; - - if (writeable || stride) ca_flags |= CA_CLIENT_DATA; - - if ((required & VERT_BIT_CLIP) && VB->ClipPtr == VB->ObjPtr) - required |= VERT_BIT_POS; - -/* _tnl_print_vert_flags("_tnl_upgrade_client_data", required); */ - - if ((required & VERT_BIT_POS) && (VB->ObjPtr->flags & flags)) { - ASSERT(VB->ObjPtr == &inputs->Obj); - _tnl_import_vertex( ctx, writeable, stride ); - VB->importable_data &= ~(VERT_BIT_POS|VERT_BIT_CLIP); - } - - if ((required & VERT_BIT_NORMAL) && (VB->NormalPtr->flags & flags)) { - ASSERT(VB->NormalPtr == &inputs->Normal); - _tnl_import_normal( ctx, writeable, stride ); - VB->importable_data &= ~VERT_BIT_NORMAL; - } - - if ((required & VERT_BIT_COLOR0) && (VB->ColorPtr[0]->Flags & ca_flags)) { - ASSERT(VB->ColorPtr[0] == &inputs->Color); - _tnl_import_color( ctx, GL_FLOAT, writeable, stride ); - VB->importable_data &= ~VERT_BIT_COLOR0; - } - - if ((required & VERT_BIT_COLOR1) && - (VB->SecondaryColorPtr[0]->Flags & ca_flags)) { - ASSERT(VB->SecondaryColorPtr[0] == &inputs->SecondaryColor); - _tnl_import_secondarycolor( ctx, GL_FLOAT, writeable, stride ); - VB->importable_data &= ~VERT_BIT_COLOR1; - } - - if ((required & VERT_BIT_FOG) - && (VB->FogCoordPtr->flags & flags)) { - ASSERT(VB->FogCoordPtr == &inputs->FogCoord); - _tnl_import_fogcoord( ctx, writeable, stride ); - VB->importable_data &= ~VERT_BIT_FOG; - } - - if ((required & VERT_BIT_INDEX) && (VB->IndexPtr[0]->flags & flags)) { - ASSERT(VB->IndexPtr[0] == &inputs->Index); - _tnl_import_index( ctx, writeable, stride ); - VB->importable_data &= ~VERT_BIT_INDEX; - } - - if (required & VERT_BITS_TEX_ANY) - for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) - if ((required & VERT_BIT_TEX(i)) && (VB->TexCoordPtr[i]->flags & flags)) { - ASSERT(VB->TexCoordPtr[i] == &inputs->TexCoord[i]); - _tnl_import_texcoord( ctx, i, writeable, stride ); - VB->importable_data &= ~VERT_BIT_TEX(i); - } - - /* XXX not sure what to do here for vertex program arrays */ -} @@ -378,28 +245,15 @@ void _tnl_vb_bind_arrays( GLcontext *ctx, GLint start, GLsizei count ) TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; GLuint inputs = tnl->pipeline.inputs; - struct vertex_arrays *tmp = &tnl->array_inputs; - -/* _mesa_debug(ctx, "%s %d..%d // %d..%d\n", __FUNCTION__, */ -/* start, count, ctx->Array.LockFirst, ctx->Array.LockCount); */ -/* _tnl_print_vert_flags(" inputs", inputs); */ -/* _tnl_print_vert_flags(" _Enabled", ctx->Array._Enabled); */ -/* _tnl_print_vert_flags(" importable", inputs & VERT_BITS_FIXUP); */ + struct tnl_vertex_arrays *tmp = &tnl->array_inputs; + GLuint i; VB->Count = count - start; - VB->FirstClipped = VB->Count; VB->Elts = NULL; - VB->MaterialMask = NULL; - VB->Material = NULL; - VB->Flag = NULL; - VB->Primitive = tnl->tmp_primitive; - VB->PrimitiveLength = tnl->tmp_primitive_length; - VB->import_data = _tnl_upgrade_client_data; - VB->importable_data = inputs & VERT_BITS_FIXUP; if (ctx->Array.LockCount) { - ASSERT(start == (GLint) ctx->Array.LockFirst); - ASSERT(count == (GLint) ctx->Array.LockCount); + assert(start == (GLint) ctx->Array.LockFirst); + assert(count == (GLint) ctx->Array.LockCount); } _ac_import_range( ctx, start, count ); @@ -416,63 +270,92 @@ void _tnl_vb_bind_arrays( GLcontext *ctx, GLint start, GLsizei count ) VB->AttribPtr[index] = &tmp->Attribs[index]; } } + else { + + /* + * Conventional attributes + */ + if (inputs & _TNL_BIT_POS) { + _tnl_import_vertex( ctx, 0, 0 ); + tmp->Obj.count = VB->Count; + VB->AttribPtr[_TNL_ATTRIB_POS] = &tmp->Obj; + } - /* - * Conventional attributes - */ - if (inputs & VERT_BIT_POS) { - _tnl_import_vertex( ctx, 0, 0 ); - tmp->Obj.count = VB->Count; - VB->ObjPtr = &tmp->Obj; - } - - if (inputs & VERT_BIT_NORMAL) { - _tnl_import_normal( ctx, 0, 0 ); - tmp->Normal.count = VB->Count; - VB->NormalPtr = &tmp->Normal; - } - - if (inputs & VERT_BIT_COLOR0) { - _tnl_import_color( ctx, 0, 0, 0 ); - VB->ColorPtr[0] = &tmp->Color; - VB->ColorPtr[1] = 0; - } + if (inputs & _TNL_BIT_NORMAL) { + _tnl_import_normal( ctx, 0, 0 ); + tmp->Normal.count = VB->Count; + VB->AttribPtr[_TNL_ATTRIB_NORMAL] = &tmp->Normal; + } - if (inputs & VERT_BITS_TEX_ANY) { - GLuint unit; - for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { - if (inputs & VERT_BIT_TEX(unit)) { - _tnl_import_texcoord( ctx, unit, GL_FALSE, GL_FALSE ); - tmp->TexCoord[unit].count = VB->Count; - VB->TexCoordPtr[unit] = &tmp->TexCoord[unit]; - } + if (inputs & _TNL_BIT_COLOR0) { + _tnl_import_color( ctx, 0, 0 ); + tmp->Color.count = VB->Count; + VB->AttribPtr[_TNL_ATTRIB_COLOR0] = &tmp->Color; } - } - if (inputs & (VERT_BIT_INDEX | VERT_BIT_FOG | - VERT_BIT_EDGEFLAG | VERT_BIT_COLOR1)) { - if (inputs & VERT_BIT_INDEX) { + if (inputs & _TNL_BIT_INDEX) { _tnl_import_index( ctx, 0, 0 ); tmp->Index.count = VB->Count; - VB->IndexPtr[0] = &tmp->Index; - VB->IndexPtr[1] = 0; + VB->AttribPtr[_TNL_ATTRIB_INDEX] = &tmp->Index; } - if (inputs & VERT_BIT_FOG) { + if (inputs & _TNL_BIT_FOG) { _tnl_import_fogcoord( ctx, 0, 0 ); tmp->FogCoord.count = VB->Count; - VB->FogCoordPtr = &tmp->FogCoord; + VB->AttribPtr[_TNL_ATTRIB_FOG] = &tmp->FogCoord; } - if (inputs & VERT_BIT_EDGEFLAG) { + if (inputs & _TNL_BIT_EDGEFLAG) { _tnl_import_edgeflag( ctx, GL_TRUE, sizeof(GLboolean) ); - VB->EdgeFlag = (GLboolean *) tmp->EdgeFlag.data; + VB->EdgeFlag = (GLboolean *) tmp->EdgeFlag; + } + + if (inputs & _TNL_BIT_COLOR1) { + _tnl_import_secondarycolor( ctx, 0, 0 ); + tmp->SecondaryColor.count = VB->Count; + VB->AttribPtr[_TNL_ATTRIB_COLOR1] = &tmp->SecondaryColor; } - if (inputs & VERT_BIT_COLOR1) { - _tnl_import_secondarycolor( ctx, 0, 0, 0 ); - VB->SecondaryColorPtr[0] = &tmp->SecondaryColor; - VB->SecondaryColorPtr[1] = 0; + + if (inputs & _TNL_BITS_TEX_ANY) { + for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { + if (inputs & _TNL_BIT_TEX(i)) { + _tnl_import_texcoord( ctx, i, GL_FALSE, GL_FALSE ); + tmp->TexCoord[i].count = VB->Count; + VB->AttribPtr[_TNL_ATTRIB_TEX0 + i] = &tmp->TexCoord[i]; + } + } } } + + + /* These are constant & can be precalculated: + */ + if (inputs & _TNL_BITS_MAT_ANY) { + for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT; i < _TNL_ATTRIB_INDEX; i++) { + tmp->Attribs[i].count = count; + tmp->Attribs[i].data = (GLfloat (*)[4]) tnl->vtx.current[i]; + tmp->Attribs[i].start = tnl->vtx.current[i]; + tmp->Attribs[i].size = 4; + tmp->Attribs[i].stride = 0; + VB->AttribPtr[i] = &tmp->Attribs[i]; + } + } + + + /* Legacy pointers -- remove one day. + */ + VB->ObjPtr = VB->AttribPtr[_TNL_ATTRIB_POS]; + VB->NormalPtr = VB->AttribPtr[_TNL_ATTRIB_NORMAL]; + VB->ColorPtr[0] = VB->AttribPtr[_TNL_ATTRIB_COLOR0]; + VB->ColorPtr[1] = 0; + VB->IndexPtr[0] = VB->AttribPtr[_TNL_ATTRIB_INDEX]; + VB->IndexPtr[1] = 0; + VB->SecondaryColorPtr[0] = VB->AttribPtr[_TNL_ATTRIB_COLOR1]; + VB->SecondaryColorPtr[1] = 0; + + for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { + VB->TexCoordPtr[i] = VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]; + } + } diff --git a/src/mesa/tnl/t_context.c b/src/mesa/tnl/t_context.c index 67558733f06..383e50601e2 100644 --- a/src/mesa/tnl/t_context.c +++ b/src/mesa/tnl/t_context.c @@ -27,6 +27,7 @@ */ +#include "api_arrayelt.h" #include "glheader.h" #include "imports.h" #include "macros.h" @@ -37,17 +38,11 @@ #include "t_context.h" #include "t_array_api.h" -#include "t_eval_api.h" -#include "t_imm_alloc.h" -#include "t_imm_api.h" -#include "t_imm_exec.h" -#include "t_imm_dlist.h" +#include "t_vtx_api.h" +#include "t_save_api.h" #include "t_pipeline.h" #include "tnl.h" -#ifndef THREADS -struct immediate *_tnl_CurrentInput = NULL; -#endif void @@ -55,9 +50,6 @@ _tnl_MakeCurrent( GLcontext *ctx, GLframebuffer *drawBuffer, GLframebuffer *readBuffer ) { -#ifndef THREADS - SET_IMMEDIATE( ctx, TNL_CURRENT_IM(ctx) ); -#endif } @@ -66,7 +58,8 @@ install_driver_callbacks( GLcontext *ctx ) { ctx->Driver.NewList = _tnl_NewList; ctx->Driver.EndList = _tnl_EndList; - ctx->Driver.FlushVertices = _tnl_flush_vertices; + ctx->Driver.FlushVertices = _tnl_FlushVertices; + ctx->Driver.SaveFlushVertices = _tnl_SaveFlushVertices; ctx->Driver.MakeCurrent = _tnl_MakeCurrent; ctx->Driver.BeginCallList = _tnl_BeginCallList; ctx->Driver.EndCallList = _tnl_EndCallList; @@ -89,18 +82,21 @@ _tnl_CreateContext( GLcontext *ctx ) /* Initialize the VB. */ - tnl->vb.Size = MAX2( IMM_SIZE, - ctx->Const.MaxArrayLockSize + MAX_CLIPPED_VERTICES); + tnl->vb.Size = ctx->Const.MaxArrayLockSize + MAX_CLIPPED_VERTICES; /* Initialize tnl state and tnl->vtxfmt. */ - _tnl_dlist_init( ctx ); + _tnl_save_init( ctx ); _tnl_array_init( ctx ); - _tnl_imm_init( ctx ); - _tnl_eval_init( ctx ); + _tnl_vtx_init( ctx ); _tnl_install_pipeline( ctx, _tnl_default_pipeline ); + /* Initialize the arrayelt helper + */ + if (!_ae_create_context( ctx )) + return GL_FALSE; + tnl->NeedNdcCoords = GL_TRUE; tnl->LoopbackDListCassettes = GL_FALSE; @@ -108,29 +104,19 @@ _tnl_CreateContext( GLcontext *ctx ) /* Hook our functions into exec and compile dispatch tables. */ - _mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt ); - - tnl->save_vtxfmt = tnl->vtxfmt; - tnl->save_vtxfmt.CallList = _mesa_save_CallList; - tnl->save_vtxfmt.EvalMesh1 = _mesa_save_EvalMesh1; - tnl->save_vtxfmt.EvalMesh2 = _mesa_save_EvalMesh2; - tnl->save_vtxfmt.Begin = _tnl_save_Begin; - - _mesa_install_save_vtxfmt( ctx, &tnl->save_vtxfmt ); + _mesa_install_exec_vtxfmt( ctx, &tnl->exec_vtxfmt ); /* Set a few default values in the driver struct. */ install_driver_callbacks(ctx); - ctx->Driver.NeedFlush = FLUSH_UPDATE_CURRENT; + ctx->Driver.NeedFlush = 0; ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN; tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts; tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts; tnl->Driver.NotifyMaterialChange = _mesa_validate_all_lighting_tables; - - return GL_TRUE; } @@ -142,9 +128,9 @@ _tnl_DestroyContext( GLcontext *ctx ) TNLcontext *tnl = TNL_CONTEXT(ctx); _tnl_array_destroy( ctx ); - _tnl_imm_destroy( ctx ); + _tnl_vtx_destroy( ctx ); + _tnl_save_destroy( ctx ); _tnl_destroy_pipeline( ctx ); - _tnl_free_immediate( ctx, tnl->freed_immediate ); FREE(tnl); ctx->swtnl_context = 0; @@ -157,13 +143,6 @@ _tnl_InvalidateState( GLcontext *ctx, GLuint new_state ) TNLcontext *tnl = TNL_CONTEXT(ctx); if (new_state & _NEW_ARRAY) { - struct immediate *IM = TNL_CURRENT_IM(ctx); - IM->ArrayEltFlags = ~ctx->Array._Enabled; - IM->ArrayEltFlush = (ctx->Array.LockCount - ? FLUSH_ELT_LAZY : FLUSH_ELT_EAGER); - IM->ArrayEltIncr = (ctx->Array.Vertex.Enabled || - (ctx->VertexProgram.Enabled && - ctx->Array.VertexAttrib[0].Enabled)) ? 1 : 0; tnl->pipeline.run_input_changes |= ctx->Array.NewState; /* overkill */ } @@ -171,7 +150,7 @@ _tnl_InvalidateState( GLcontext *ctx, GLuint new_state ) tnl->pipeline.build_state_changes |= (new_state & tnl->pipeline.build_state_trigger); - tnl->eval.EvalNewState |= new_state; + tnl->vtx.eval.new_state |= new_state; } @@ -185,7 +164,7 @@ _tnl_wakeup_exec( GLcontext *ctx ) /* Hook our functions into exec and compile dispatch tables. */ - _mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt ); + _mesa_install_exec_vtxfmt( ctx, &tnl->exec_vtxfmt ); /* Call all appropriate driver callbacks to revive state. */ @@ -197,9 +176,9 @@ _tnl_wakeup_exec( GLcontext *ctx ) tnl->pipeline.run_input_changes = ~0; if (ctx->Light.ColorMaterialEnabled) { - _mesa_update_color_material( ctx, ctx->Current.Attrib[VERT_ATTRIB_COLOR0] ); + _mesa_update_color_material( ctx, + ctx->Current.Attrib[VERT_ATTRIB_COLOR0] ); } - } diff --git a/src/mesa/tnl/t_context.h b/src/mesa/tnl/t_context.h index c375a5670bc..9d806da81fc 100644 --- a/src/mesa/tnl/t_context.h +++ b/src/mesa/tnl/t_context.h @@ -1,5 +1,5 @@ /* - * Mesa 3-D graphics library + * mesa 3-D graphics library * Version: 5.1 * * Copyright (C) 1999-2003 Brian Paul All Rights Reserved. @@ -37,9 +37,9 @@ * necessary transformations (rotations, clipping, vertex shader etc.) * and passes then the output to the rasterizer. * - * The gl_pipeline contains the array of all stages, which should be + * The tnl_pipeline contains the array of all stages, which should be * applied. Each stage is a black-box, which is described by an - * gl_pipeline_stage. The function ::_tnl_run_pipeline applies all the + * tnl_pipeline_stage. The function ::_tnl_run_pipeline applies all the * stages to the vertex_buffer TNLcontext::vb, where the vertex data * is stored. The last stage in the pipeline is the rasterizer. * @@ -68,7 +68,6 @@ * into TNLcontext::vb, so that the pipeline can be started. */ -/* What is ELT? */ #ifndef _T_CONTEXT_H #define _T_CONTEXT_H @@ -84,256 +83,346 @@ #define MAX_PIPELINE_STAGES 30 -/* Numbers for sizing immediate structs. +enum { + _TNL_ATTRIB_POS = 0, + _TNL_ATTRIB_WEIGHT = 1, + _TNL_ATTRIB_NORMAL = 2, + _TNL_ATTRIB_COLOR0 = 3, + _TNL_ATTRIB_COLOR1 = 4, + _TNL_ATTRIB_FOG = 5, + _TNL_ATTRIB_SIX = 6, + _TNL_ATTRIB_SEVEN = 7, + _TNL_ATTRIB_TEX0 = 8, + _TNL_ATTRIB_TEX1 = 9, + _TNL_ATTRIB_TEX2 = 10, + _TNL_ATTRIB_TEX3 = 11, + _TNL_ATTRIB_TEX4 = 12, + _TNL_ATTRIB_TEX5 = 13, + _TNL_ATTRIB_TEX6 = 14, + _TNL_ATTRIB_TEX7 = 15, + _TNL_ATTRIB_MAT_FRONT_AMBIENT = 16, + _TNL_ATTRIB_MAT_BACK_AMBIENT = 17, + _TNL_ATTRIB_MAT_FRONT_DIFFUSE = 18, + _TNL_ATTRIB_MAT_BACK_DIFFUSE = 19, + _TNL_ATTRIB_MAT_FRONT_SPECULAR = 20, + _TNL_ATTRIB_MAT_BACK_SPECULAR = 21, + _TNL_ATTRIB_MAT_FRONT_EMISSION = 22, + _TNL_ATTRIB_MAT_BACK_EMISSION = 23, + _TNL_ATTRIB_MAT_FRONT_SHININESS = 24, + _TNL_ATTRIB_MAT_BACK_SHININESS = 25, + _TNL_ATTRIB_MAT_FRONT_INDEXES = 26, + _TNL_ATTRIB_MAT_BACK_INDEXES = 27, + _TNL_ATTRIB_INDEX = 28, + _TNL_ATTRIB_EDGEFLAG = 29, + _TNL_ATTRIB_MAX = 30 +} ; + +/* Will probably have to revise this scheme fairly shortly, eg. by + * compacting all the MAT flags down to one bit, or by using two + * dwords to store the flags. */ -#define IMM_MAX_COPIED_VERTS 3 -#define IMM_MAXDATA (216 + IMM_MAX_COPIED_VERTS) -#define IMM_SIZE (IMM_MAXDATA + MAX_CLIPPED_VERTICES) +#define _TNL_BIT_POS (1<<0) +#define _TNL_BIT_WEIGHT (1<<1) +#define _TNL_BIT_NORMAL (1<<2) +#define _TNL_BIT_COLOR0 (1<<3) +#define _TNL_BIT_COLOR1 (1<<4) +#define _TNL_BIT_FOG (1<<5) +#define _TNL_BIT_SIX (1<<6) +#define _TNL_BIT_SEVEN (1<<7) +#define _TNL_BIT_TEX0 (1<<8) +#define _TNL_BIT_TEX1 (1<<9) +#define _TNL_BIT_TEX2 (1<<10) +#define _TNL_BIT_TEX3 (1<<11) +#define _TNL_BIT_TEX4 (1<<12) +#define _TNL_BIT_TEX5 (1<<13) +#define _TNL_BIT_TEX6 (1<<14) +#define _TNL_BIT_TEX7 (1<<15) +#define _TNL_BIT_MAT_FRONT_AMBIENT (1<<16) +#define _TNL_BIT_MAT_BACK_AMBIENT (1<<17) +#define _TNL_BIT_MAT_FRONT_DIFFUSE (1<<18) +#define _TNL_BIT_MAT_BACK_DIFFUSE (1<<19) +#define _TNL_BIT_MAT_FRONT_SPECULAR (1<<20) +#define _TNL_BIT_MAT_BACK_SPECULAR (1<<21) +#define _TNL_BIT_MAT_FRONT_EMISSION (1<<22) +#define _TNL_BIT_MAT_BACK_EMISSION (1<<23) +#define _TNL_BIT_MAT_FRONT_SHININESS (1<<24) +#define _TNL_BIT_MAT_BACK_SHININESS (1<<25) +#define _TNL_BIT_MAT_FRONT_INDEXES (1<<26) +#define _TNL_BIT_MAT_BACK_INDEXES (1<<27) +#define _TNL_BIT_INDEX (1<<28) +#define _TNL_BIT_EDGEFLAG (1<<29) + +#define _TNL_BIT_TEX(u) (1 << (_TNL_ATTRIB_TEX0 + (u))) + + +#define _TNL_BITS_MAT_ANY (_TNL_BIT_MAT_FRONT_AMBIENT | \ + _TNL_BIT_MAT_BACK_AMBIENT | \ + _TNL_BIT_MAT_FRONT_DIFFUSE | \ + _TNL_BIT_MAT_BACK_DIFFUSE | \ + _TNL_BIT_MAT_FRONT_SPECULAR | \ + _TNL_BIT_MAT_BACK_SPECULAR | \ + _TNL_BIT_MAT_FRONT_EMISSION | \ + _TNL_BIT_MAT_BACK_EMISSION | \ + _TNL_BIT_MAT_FRONT_SHININESS | \ + _TNL_BIT_MAT_BACK_SHININESS | \ + _TNL_BIT_MAT_FRONT_INDEXES | \ + _TNL_BIT_MAT_BACK_INDEXES) + + +#define _TNL_BITS_TEX_ANY (_TNL_BIT_TEX0 | \ + _TNL_BIT_TEX1 | \ + _TNL_BIT_TEX2 | \ + _TNL_BIT_TEX3 | \ + _TNL_BIT_TEX4 | \ + _TNL_BIT_TEX5 | \ + _TNL_BIT_TEX6 | \ + _TNL_BIT_TEX7) + + +#define _TNL_BITS_PROG_ANY (_TNL_BIT_POS | \ + _TNL_BIT_WEIGHT | \ + _TNL_BIT_NORMAL | \ + _TNL_BIT_COLOR0 | \ + _TNL_BIT_COLOR1 | \ + _TNL_BIT_FOG | \ + _TNL_BIT_SIX | \ + _TNL_BIT_SEVEN | \ + _TNL_BITS_TEX_ANY) + + + +#define PRIM_BEGIN 0x10 +#define PRIM_END 0x20 +#define PRIM_WEAK 0x40 +#define PRIM_MODE_MASK 0x0f + +/* + */ +struct tnl_prim { + GLuint mode; + GLuint start; + GLuint count; +}; -/* Values for IM->BeginState - */ -#define VERT_BEGIN_0 0x1 /* glBegin (if initially inside beg/end) */ -#define VERT_BEGIN_1 0x2 /* glBegin (if initially outside beg/end) */ -#define VERT_ERROR_0 0x4 /* invalid_operation in initial state 0 */ -#define VERT_ERROR_1 0x8 /* invalid_operation in initial state 1 */ +struct tnl_eval1_map { + struct gl_1d_map *map; + GLuint sz; +}; -/* Flags to be added to the primitive enum in VB->Primitive. - */ -#define PRIM_MODE_MASK 0xff /* Extract the actual primitive */ -#define PRIM_BEGIN 0x100 /* The prim starts here (not wrapped) */ -#define PRIM_END 0x200 /* The prim ends in this VB (does not wrap) */ -#define PRIM_PARITY 0x400 /* The prim wrapped on an odd number of verts */ -#define PRIM_LAST 0x800 /* No more prims in the VB */ +struct tnl_eval2_map { + struct gl_2d_map *map; + GLuint sz; +}; + +struct tnl_eval { + GLuint new_state; + struct tnl_eval1_map map1[_TNL_ATTRIB_INDEX + 1]; + struct tnl_eval2_map map2[_TNL_ATTRIB_INDEX + 1]; +}; -/** - * Flags that describe the inputs and outputs of pipeline stages, and - * the contents of a vertex-cassette. We reuse the VERT_BIT_* flags - * defined in mtypes.h and add a bunch of new ones. - */ -/* bits 0..5 defined in mtypes.h */ -#define VERT_BIT_INDEX VERT_BIT_SIX /* a free vertex attrib bit */ -#define VERT_BIT_EDGEFLAG VERT_BIT_SEVEN /* a free vertex attrib bit */ -/* bits 8..15 defined in mtypes.h */ -#define VERT_BIT_EVAL_C1 (1 << 16) /* imm only */ -#define VERT_BIT_EVAL_C2 (1 << 17) /* imm only */ -#define VERT_BIT_EVAL_P1 (1 << 18) /* imm only */ -#define VERT_BIT_EVAL_P2 (1 << 19) /* imm only */ -#define VERT_BIT_OBJ_3 (1 << 20) /* imm only */ -#define VERT_BIT_OBJ_4 (1 << 21) /* imm only */ -#define VERT_BIT_MATERIAL (1 << 22) /* imm only, but tested in vb code */ -#define VERT_BIT_ELT (1 << 23) /* imm only */ -#define VERT_BIT_BEGIN (1 << 24) /* imm only, but tested in vb code */ -#define VERT_BIT_END (1 << 25) /* imm only, but tested in vb code */ -#define VERT_BIT_END_VB (1 << 26) /* imm only, but tested in vb code */ -#define VERT_BIT_POINT_SIZE (1 << 27) /* vb only, could reuse a bit */ -#define VERT_BIT_EYE VERT_BIT_BEGIN /* vb only, reuse imm bit */ -#define VERT_BIT_CLIP VERT_BIT_END /* vb only, reuse imm bit*/ - - -/* Flags for IM->TexCoordSize. Enough flags for 16 units. +#define TNL_MAX_PRIM 16 +#define TNL_MAX_COPIED_VERTS 3 + +struct tnl_copied_vtx { + GLfloat buffer[_TNL_ATTRIB_MAX * 4 * TNL_MAX_COPIED_VERTS]; + GLuint nr; +}; + +#define VERT_BUFFER_SIZE 2048 /* 8kbytes */ + +typedef void (*attrfv_func)( const GLfloat * ); + +/* The assembly of vertices in immediate mode is separated from + * display list compilation. This allows a simpler immediate mode + * treatment and a display list compiler better suited to + * hardware-acceleration. */ -#define TEX_0_SIZE_3 (unsigned)0x1 -#define TEX_0_SIZE_4 (unsigned)0x10001 -#define TEX_SIZE_3(unit) (TEX_0_SIZE_3 << (unit)) -#define TEX_SIZE_4(unit) (TEX_0_SIZE_4 << (unit)) +struct tnl_vtx { + GLfloat buffer[VERT_BUFFER_SIZE]; + GLubyte attrsz[_TNL_ATTRIB_MAX]; + GLuint vertex_size; + struct tnl_prim prim[TNL_MAX_PRIM]; + GLuint prim_count; + GLfloat *vbptr; /* cursor, points into buffer */ + GLfloat vertex[_TNL_ATTRIB_MAX*4]; /* current vertex */ + GLfloat *attrptr[_TNL_ATTRIB_MAX]; /* points into vertex */ + GLfloat *current[_TNL_ATTRIB_MAX]; /* points into ctx->Current, etc */ + GLuint counter, initial_counter; + struct tnl_copied_vtx copied; + attrfv_func tabfv[_TNL_ATTRIB_MAX][4]; + struct tnl_eval eval; + GLboolean *edgeflag_tmp; +}; + + -/* Shorthands. +/* For display lists, this structure holds a run of vertices of the + * same format, and a strictly well-formed set of begin/end pairs, + * starting on the first vertex and ending at the last. Vertex + * copying on buffer breaks is precomputed according to these + * primitives, though there are situations where the copying will need + * correction at execute-time, perhaps by replaying the list as + * immediate mode commands. + * + * On executing this list, the 'current' values may be updated with + * the values of the final vertex, and often no fixup of the start of + * the vertex list is required. + * + * Eval and other commands that don't fit into these vertex lists are + * compiled using the fallback opcode mechanism provided by dlist.c. */ -#define VERT_BITS_OBJ_23 (VERT_BIT_POS | VERT_BIT_OBJ_3) -#define VERT_BITS_OBJ_234 (VERT_BIT_POS | VERT_BIT_OBJ_3 | VERT_BIT_OBJ_4) - -#define VERT_BITS_TEX_ANY (VERT_BIT_TEX0 | \ - VERT_BIT_TEX1 | \ - VERT_BIT_TEX2 | \ - VERT_BIT_TEX3 | \ - VERT_BIT_TEX4 | \ - VERT_BIT_TEX5 | \ - VERT_BIT_TEX6 | \ - VERT_BIT_TEX7) - -#define VERT_BITS_EVAL_ANY (VERT_BIT_EVAL_C1 | VERT_BIT_EVAL_P1 | \ - VERT_BIT_EVAL_C2 | VERT_BIT_EVAL_P2) - -#define VERT_BITS_FIXUP (VERT_BITS_TEX_ANY | \ - VERT_BIT_COLOR0 | \ - VERT_BIT_COLOR1 | \ - VERT_BIT_FOG | \ - VERT_BIT_INDEX | \ - VERT_BIT_EDGEFLAG | \ - VERT_BIT_NORMAL) - -#define VERT_BITS_CURRENT_DATA (VERT_BITS_FIXUP | \ - VERT_BIT_MATERIAL) - -#define VERT_BITS_DATA (VERT_BITS_TEX_ANY | \ - VERT_BIT_COLOR0 | \ - VERT_BIT_COLOR1 | \ - VERT_BIT_FOG | \ - VERT_BIT_INDEX | \ - VERT_BIT_EDGEFLAG | \ - VERT_BIT_NORMAL | \ - VERT_BIT_POS | \ - VERT_BIT_MATERIAL | \ - VERT_BIT_ELT | \ - VERT_BITS_EVAL_ANY) +struct tnl_vertex_list { + GLubyte attrsz[_TNL_ATTRIB_MAX]; + GLuint vertex_size; + + GLfloat *buffer; + GLuint count; + GLuint wrap_count; /* number of copied vertices at start */ + GLuint dangling_attr_ref; /* current attr implicitly referenced + outside the list */ + + GLfloat *normal_lengths; + struct tnl_prim *prim; + GLuint prim_count; + + struct tnl_vertex_store *vertex_store; + struct tnl_primitive_store *prim_store; +}; +/* These buffers should be a reasonable size to support upload to + * hardware? Maybe drivers should stitch them back together, or + * specify a desired size? + */ +#define SAVE_BUFFER_SIZE (16*1024) +#define SAVE_PRIM_SIZE 128 -/** - * \struct immediate - * Stores everything that can take place between a glBegin and glEnd. - * Adjacent glBegin/glEnd pairs are stored back-to-back when there's no - * state changes between them. - * Used for immediate mode rendering and display lists. +/* Storage to be shared among several vertex_lists. */ -struct immediate -{ - GLuint id, ref_count; +struct tnl_vertex_store { + GLfloat buffer[SAVE_BUFFER_SIZE]; + GLuint used; + GLuint refcount; +}; - /* This must be saved when immediates are shared in display lists. - */ - GLuint CopyStart, Start, Count; - GLuint LastData; /* count or count+1 */ - GLuint AndFlag, OrFlag; - GLuint TexSize; /* keep track of texcoord sizes */ - GLuint BeginState, SavedBeginState; - GLuint LastPrimitive; +struct tnl_primitive_store { + struct tnl_prim buffer[SAVE_PRIM_SIZE]; + GLuint used; + GLuint refcount; +}; - GLuint ArrayEltFlags; /* precalc'ed for glArrayElt */ - GLuint ArrayEltIncr; - GLuint ArrayEltFlush; -#define FLUSH_ELT_EAGER 0x1 -#define FLUSH_ELT_LAZY 0x2 - GLuint FlushElt; +struct tnl_save { + GLubyte attrsz[_TNL_ATTRIB_MAX]; + GLuint vertex_size; - GLuint MaxTextureUnits; /* precalc'ed for glMultiTexCoordARB */ + GLfloat *buffer; + GLuint count; + GLuint wrap_count; - /* Temporary values created when vertices are copied into the - * first 3 slots of the struct: - */ - GLuint CopyOrFlag; - GLuint CopyAndFlag; - GLuint CopyTexSize; - GLuint Evaluated; + struct tnl_prim *prim; + GLuint prim_count, prim_max; + struct tnl_vertex_store *vertex_store; + struct tnl_primitive_store *prim_store; - /* allocate storage for these on demand: - */ - struct gl_material *Material; - GLuint *MaterialMask; - GLuint LastMaterial; - GLuint MaterialOrMask; - GLuint MaterialAndMask; - - GLuint Primitive[IMM_SIZE]; /* BEGIN/END */ - GLuint PrimitiveLength[IMM_SIZE]; /* BEGIN/END */ - GLuint Flag[IMM_SIZE]; /* VERT_BIT_* flags */ - - /* Attrib is an array [MAX_VERT_ATTRIBS] of pointer to array [][4] - * of GLfloat. - * We only pre-allocate the vertex position array. The other vertex - * attribute arrays are only allocated when needed to save memory. - */ - GLfloat (*Attrib[VERT_ATTRIB_MAX])[4]; + GLfloat *vbptr; /* cursor, points into buffer */ + GLfloat vertex[_TNL_ATTRIB_MAX*4]; /* current values */ + GLfloat *attrptr[_TNL_ATTRIB_MAX]; + GLuint counter, initial_counter; + GLuint dangling_attr_ref; + + GLuint opcode_vertex_list; + + struct tnl_copied_vtx copied; - GLfloat *NormalLengthPtr; /* length of normal vectors (display list only) */ + GLfloat *current[_TNL_ATTRIB_MAX]; /* points into ctx->ListState */ + GLubyte *currentsz[_TNL_ATTRIB_MAX]; - GLuint Elt[IMM_SIZE]; - GLubyte EdgeFlag[IMM_SIZE]; - GLuint Index[IMM_SIZE]; + void (*tabfv[_TNL_ATTRIB_MAX][4])( const GLfloat * ); }; -struct vertex_arrays + + + + + +struct tnl_vertex_arrays { /* Conventional vertex attribute arrays */ GLvector4f Obj; GLvector4f Normal; - struct gl_client_array Color; - struct gl_client_array SecondaryColor; + GLvector4f Color; + GLvector4f SecondaryColor; GLvector4f FogCoord; GLvector4f TexCoord[MAX_TEXTURE_COORD_UNITS]; - GLvector1ub EdgeFlag; - GLvector1ui Index; - GLvector1ui Elt; + GLvector4f Index; + + GLubyte *EdgeFlag; + GLuint *Elt; /* These attributes don't alias with the conventional attributes. * The GL_NV_vertex_program extension defines 16 extra sets of vertex * arrays which have precedent over the conventional arrays when enabled. */ - GLvector4f Attribs[VERT_ATTRIB_MAX]; + GLvector4f Attribs[_TNL_ATTRIB_MAX]; }; /** * Contains the current state of a running pipeline. */ -typedef struct vertex_buffer +struct vertex_buffer { /* Constant over life of the vertex_buffer. */ - GLuint Size; + GLuint Size; /* Constant over the pipeline. */ - GLuint Count; /* for everything except Elts */ - GLuint FirstClipped; /* temp verts for clipping */ - GLuint FirstPrimitive; /* usually zero */ + GLuint Count; /* for everything except Elts */ /* Pointers to current data. */ - GLuint *Elts; /* VERT_BIT_ELT */ - GLvector4f *ObjPtr; /* VERT_BIT_POS */ - GLvector4f *EyePtr; /* VERT_BIT_EYE */ - GLvector4f *ClipPtr; /* VERT_BIT_CLIP */ - GLvector4f *NdcPtr; /* VERT_BIT_CLIP (2) */ - GLubyte ClipOrMask; /* VERT_BIT_CLIP (3) */ - GLubyte *ClipMask; /* VERT_BIT_CLIP (4) */ - GLvector4f *NormalPtr; /* VERT_BIT_NORMAL */ - GLfloat *NormalLengthPtr; /* VERT_BIT_NORMAL */ - GLboolean *EdgeFlag; /* VERT_BIT_EDGEFLAG */ + GLuint *Elts; + GLvector4f *ObjPtr; /* _TNL_BIT_POS */ + GLvector4f *EyePtr; /* _TNL_BIT_POS */ + GLvector4f *ClipPtr; /* _TNL_BIT_POS */ + GLvector4f *NdcPtr; /* _TNL_BIT_POS */ + GLubyte ClipOrMask; /* _TNL_BIT_POS */ + GLubyte *ClipMask; /* _TNL_BIT_POS */ + GLvector4f *NormalPtr; /* _TNL_BIT_NORMAL */ + GLfloat *NormalLengthPtr; /* _TNL_BIT_NORMAL */ + GLboolean *EdgeFlag; /* _TNL_BIT_EDGEFLAG */ GLvector4f *TexCoordPtr[MAX_TEXTURE_COORD_UNITS]; /* VERT_TEX_0..n */ - GLvector1ui *IndexPtr[2]; /* VERT_BIT_INDEX */ - struct gl_client_array *ColorPtr[2]; /* VERT_BIT_COLOR0 */ - struct gl_client_array *SecondaryColorPtr[2];/* VERT_BIT_COLOR1 */ - GLvector4f *PointSizePtr; /* VERT_BIT_POINT_SIZE */ - GLvector4f *FogCoordPtr; /* VERT_BIT_FOG */ - struct gl_material *Material; /* VERT_BIT_MATERIAL, optional */ - GLuint *MaterialMask; /* VERT_BIT_MATERIAL, optional */ - GLuint *Flag; /* VERT_BIT_* flags, optional */ - GLuint *Primitive; /* GL_(mode)|PRIM_* flags */ - GLuint *PrimitiveLength; /* integers */ + GLvector4f *IndexPtr[2]; /* _TNL_BIT_INDEX */ + GLvector4f *ColorPtr[2]; /* _TNL_BIT_COLOR0 */ + GLvector4f *SecondaryColorPtr[2]; /* _TNL_BIT_COLOR1 */ + GLvector4f *PointSizePtr; /* _TNL_BIT_POS */ + GLvector4f *FogCoordPtr; /* _TNL_BIT_FOG */ + + struct tnl_prim *Primitive; + GLuint PrimitiveCount; /* Inputs to the vertex program stage */ - GLvector4f *AttribPtr[VERT_ATTRIB_MAX]; /* GL_NV_vertex_program */ - - GLuint importable_data; - void *import_source; - void (*import_data)( GLcontext *ctx, GLuint flags, GLuint vecflags ); - /* Callback to the provider of the untransformed input for the - * render stage (or other stages) to call if they need to write into - * write-protected arrays, or fixup the stride on input arrays. - * - * This is currently only necessary for client arrays that make it - * as far down the pipeline as the render stage. - */ + GLvector4f *AttribPtr[_TNL_ATTRIB_MAX]; /* GL_NV_vertex_program */ GLuint LastClipped; /* Private data from _tnl_render_stage that has no business being * in this struct. */ -} TNLvertexbuffer; +}; /** Describes an individual operation on the pipeline. */ -struct gl_pipeline_stage { +struct tnl_pipeline_stage { const char *name; GLuint check_state; /* All state referenced in check() -- * When is the pipeline_stage struct @@ -365,12 +454,12 @@ struct gl_pipeline_stage { /* Free private data. May not be null. */ - void (*destroy)( struct gl_pipeline_stage * ); + void (*destroy)( struct tnl_pipeline_stage * ); /* Called from _tnl_validate_pipeline(). Must update all fields in * the pipeline_stage struct for the current state. */ - void (*check)( GLcontext *ctx, struct gl_pipeline_stage * ); + void (*check)( GLcontext *ctx, struct tnl_pipeline_stage * ); /* Called from _tnl_run_pipeline(). The stage.changed_inputs value * encodes all inputs to thee struct which have changed. If @@ -380,31 +469,23 @@ struct gl_pipeline_stage { * Return value: GL_TRUE - keep going * GL_FALSE - finished pipeline */ - GLboolean (*run)( GLcontext *ctx, struct gl_pipeline_stage * ); + GLboolean (*run)( GLcontext *ctx, struct tnl_pipeline_stage * ); }; /** Contains the array of all pipeline stages. * The default values are defined at the end of t_pipeline.c */ -struct gl_pipeline { +struct tnl_pipeline { GLuint build_state_trigger; /**< state changes which require build */ GLuint build_state_changes; /**< state changes since last build */ GLuint run_state_changes; /**< state changes since last run */ GLuint run_input_changes; /**< VERT_* changes since last run */ GLuint inputs; /**< VERT_* inputs to pipeline */ /** This array has to end with a NULL-pointer. */ - struct gl_pipeline_stage stages[MAX_PIPELINE_STAGES+1]; + struct tnl_pipeline_stage stages[MAX_PIPELINE_STAGES+1]; GLuint nr_stages; }; -struct tnl_eval_store { - GLuint EvalMap1Flags; - GLuint EvalMap2Flags; - GLuint EvalMap1AttribFlags; /* GL_NV_vertex_program */ - GLuint EvalMap2AttribFlags; /* GL_NV_vertex_program */ - GLuint EvalNewState; - struct immediate *im; /* used for temporary data */ -}; typedef void (*points_func)( GLcontext *ctx, GLuint first, GLuint last ); @@ -533,50 +614,26 @@ typedef struct { */ struct tnl_device_driver Driver; - /* Track whether the module is active. + /* Execute: */ - GLboolean bound_exec; - - /* Display list extensions + struct tnl_vtx vtx; + + /* Compile: */ - GLuint opcode_vertex_cassette; + struct tnl_save save; /* Pipeline */ - struct gl_pipeline pipeline; + struct tnl_pipeline pipeline; struct vertex_buffer vb; /* GLvectors for binding to vb: */ - struct vertex_arrays imm_inputs; - struct vertex_arrays array_inputs; - GLuint *tmp_primitive; - GLuint *tmp_primitive_length; - - /* Set when executing an internally generated begin/end object. If - * such an object is encountered in a display list, it will be - * replayed only if the list is outside any existing begin/end - * objects. - */ - GLboolean ReplayHardBeginEnd; + struct tnl_vertex_arrays vtx_inputs; + struct tnl_vertex_arrays save_inputs; + struct tnl_vertex_arrays current; + struct tnl_vertex_arrays array_inputs; - /* Note which vertices need copying over succesive immediates. - * Will add save versions to precompute vertex copying where - * possible. - */ - struct immediate *ExecCopySource; - GLuint ExecCopyCount; - GLuint ExecCopyElts[IMM_MAX_COPIED_VERTS]; - GLuint ExecCopyTexSize; - GLuint ExecParity; - - GLuint DlistPrimitive; - GLuint DlistPrimitiveLength; - GLuint DlistLastPrimitive; - - /* Cache a single free immediate (refcount == 0) - */ - struct immediate *freed_immediate; /* Probably need a better configuration mechanism: */ @@ -585,13 +642,8 @@ typedef struct { GLboolean CalcDListNormalLengths; GLboolean IsolateMaterials; - /* Derived state and storage for _tnl_eval_vb: - */ - struct tnl_eval_store eval; - /* Functions to be plugged into dispatch when tnl is active. - */ - GLvertexformat vtxfmt; + GLvertexformat exec_vtxfmt; GLvertexformat save_vtxfmt; } TNLcontext; @@ -599,7 +651,6 @@ typedef struct { #define TNL_CONTEXT(ctx) ((TNLcontext *)(ctx->swtnl_context)) -#define TNL_CURRENT_IM(ctx) ((struct immediate *)(ctx->swtnl_im)) #define TYPE_IDX(t) ((t) & 0xf) @@ -610,21 +661,6 @@ extern void _tnl_MakeCurrent( GLcontext *ctx, GLframebuffer *readBuffer ); -/* - * Macros for fetching current input buffer. - */ -#ifdef THREADS -#define GET_IMMEDIATE struct immediate *IM = TNL_CURRENT_IM(((GLcontext *) (_glapi_Context ? _glapi_Context : _glapi_get_context()))) -#define SET_IMMEDIATE(ctx, im) ctx->swtnl_im = (void *)im -#else -extern struct immediate *_tnl_CurrentInput; -#define GET_IMMEDIATE struct immediate *IM = _tnl_CurrentInput -#define SET_IMMEDIATE(ctx, im) \ -do { \ - ctx->swtnl_im = (void *)im; \ - _tnl_CurrentInput = im; \ -} while (0) -#endif #endif diff --git a/src/mesa/tnl/t_imm_alloc.c b/src/mesa/tnl/t_imm_alloc.c deleted file mode 100644 index a8b3d729141..00000000000 --- a/src/mesa/tnl/t_imm_alloc.c +++ /dev/null @@ -1,151 +0,0 @@ - -/* - * Mesa 3-D graphics library - * Version: 5.1 - * - * Copyright (C) 1999-2003 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 - */ - -#include "glheader.h" -#include "imports.h" -#include "mtypes.h" - -#include "t_imm_alloc.h" - - -static int id = 0; /* give each struct immediate a unique ID number */ - - -static struct immediate * -real_alloc_immediate( GLcontext *ctx ) -{ - struct immediate *immed = ALIGN_CALLOC_STRUCT( immediate, 32 ); - - if (!immed) - return NULL; - - immed->id = id++; - immed->ref_count = 0; - immed->FlushElt = 0; - immed->LastPrimitive = IMM_MAX_COPIED_VERTS; - immed->Count = IMM_MAX_COPIED_VERTS; - immed->Start = IMM_MAX_COPIED_VERTS; - immed->Material = 0; - immed->MaterialMask = 0; - immed->MaxTextureUnits = ctx->Const.MaxTextureCoordUnits; - immed->TexSize = 0; - immed->NormalLengthPtr = 0; - - /* Only allocate space for vertex positions right now. Color, texcoord, - * etc storage will be allocated as needed. - */ - immed->Attrib[VERT_ATTRIB_POS] = (GLfloat (*)[4]) _mesa_malloc(IMM_SIZE * 4 * sizeof(GLfloat)); - - /* Enable this to allocate all attribute arrays up front */ - if (0) - { - int i; - for (i = 1; i < VERT_ATTRIB_MAX; i++) { - immed->Attrib[i] = (GLfloat (*)[4]) _mesa_malloc(IMM_SIZE * 4 * sizeof(GLfloat)); - } - } - - immed->CopyTexSize = 0; - immed->CopyStart = immed->Start; - - return immed; -} - - -static void -real_free_immediate( struct immediate *immed ) -{ - static int freed = 0; - GLuint i; - - for (i =0; i < VERT_ATTRIB_MAX; i++) { - if (immed->Attrib[i]) - _mesa_free(immed->Attrib[i]); - immed->Attrib[i] = NULL; - } - - if (immed->Material) { - FREE( immed->Material ); - FREE( immed->MaterialMask ); - immed->Material = 0; - immed->MaterialMask = 0; - } - - if (immed->NormalLengthPtr) - ALIGN_FREE( immed->NormalLengthPtr ); - - ALIGN_FREE( immed ); - freed++; -/* printf("outstanding %d\n", id - freed); */ -} - - -/** - * Return a pointer to a new 'struct immediate' object. - * We actually keep a spare/cached one to reduce malloc calls. - */ -struct immediate * -_tnl_alloc_immediate( GLcontext *ctx ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct immediate *tmp = tnl->freed_immediate; - - if (tmp) { - tnl->freed_immediate = 0; - return tmp; - } - else - return real_alloc_immediate( ctx ); -} - -/** - * Free a 'struct immediate' object. - * May be called after tnl is destroyed. - */ -void -_tnl_free_immediate( GLcontext *ctx, struct immediate *immed ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - - ASSERT(immed->ref_count == 0); - - if (immed->NormalLengthPtr) { - ALIGN_FREE(immed->NormalLengthPtr); - immed->NormalLengthPtr = NULL; - } - - if (!tnl) { - real_free_immediate( immed ); - } - else { - if (tnl->freed_immediate) - real_free_immediate( tnl->freed_immediate ); - - tnl->freed_immediate = immed; - } -} diff --git a/src/mesa/tnl/t_imm_alloc.h b/src/mesa/tnl/t_imm_alloc.h deleted file mode 100644 index 502be3fe9b1..00000000000 --- a/src/mesa/tnl/t_imm_alloc.h +++ /dev/null @@ -1,39 +0,0 @@ - -/* - * Mesa 3-D graphics library - * Version: 3.5 - * - * 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"), - * 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. - */ - - -#ifndef _T_IMM_ALLOC_H -#define _T_IMM_ALLOC_H - -#include "mtypes.h" -#include "t_context.h" - - -extern struct immediate *_tnl_alloc_immediate( GLcontext *ctx ); - -extern void _tnl_free_immediate( GLcontext *ctx, struct immediate *im ); - - -#endif diff --git a/src/mesa/tnl/t_imm_debug.c b/src/mesa/tnl/t_imm_debug.c deleted file mode 100644 index 856eaa75f7a..00000000000 --- a/src/mesa/tnl/t_imm_debug.c +++ /dev/null @@ -1,182 +0,0 @@ - -/* - * Mesa 3-D graphics library - * Version: 5.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. - */ - -#include "mtypes.h" -#include "context.h" -#include "imports.h" -#include "t_context.h" -#include "t_imm_debug.h" - - -void _tnl_print_vert_flags( const char *name, GLuint flags ) -{ - _mesa_debug(NULL, - "%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", - name, - flags, - (flags & VERT_BIT_CLIP) ? "clip/proj-clip/glend, " : "", - (flags & VERT_BIT_EDGEFLAG) ? "edgeflag, " : "", - (flags & VERT_BIT_ELT) ? "array-elt, " : "", - (flags & VERT_BIT_END_VB) ? "end-vb, " : "", - (flags & VERT_BITS_EVAL_ANY) ? "eval-coord, " : "", - (flags & VERT_BIT_EYE) ? "eye/glbegin, " : "", - (flags & VERT_BIT_FOG) ? "fog-coord, " : "", - (flags & VERT_BIT_INDEX) ? "index, " : "", - (flags & VERT_BIT_MATERIAL) ? "material, " : "", - (flags & VERT_BIT_NORMAL) ? "normals, " : "", - (flags & VERT_BIT_POS) ? "obj, " : "", - (flags & VERT_BIT_OBJ_3) ? "obj-3, " : "", - (flags & VERT_BIT_OBJ_4) ? "obj-4, " : "", - (flags & VERT_BIT_POINT_SIZE) ? "point-size, " : "", - (flags & VERT_BIT_COLOR0) ? "colors, " : "", - (flags & VERT_BIT_COLOR1) ? "specular, " : "", - (flags & VERT_BIT_TEX0) ? "texcoord0, " : "", - (flags & VERT_BIT_TEX1) ? "texcoord1, " : "", - (flags & VERT_BIT_TEX2) ? "texcoord2, " : "", - (flags & VERT_BIT_TEX3) ? "texcoord3, " : "", - (flags & VERT_BIT_TEX4) ? "texcoord4, " : "", - (flags & VERT_BIT_TEX5) ? "texcoord5, " : "", - (flags & VERT_BIT_TEX6) ? "texcoord6, " : "", - (flags & VERT_BIT_TEX7) ? "texcoord7, " : "" - ); -} - -void _tnl_print_cassette( struct immediate *IM ) -{ - GLuint i; - GLuint *flags = IM->Flag; - GLuint andflag = IM->CopyAndFlag; - GLuint orflag = (IM->CopyOrFlag|IM->Evaluated); - GLuint state = IM->BeginState; - GLuint req = ~0; - - _mesa_debug(NULL, "Cassette id %d, %u rows.\n", IM->id, - IM->Count - IM->CopyStart); - - _tnl_print_vert_flags("Contains at least one", orflag); - - if (IM->Count != IM->CopyStart) - { - _tnl_print_vert_flags("Contains a full complement of", andflag); - - _mesa_debug(NULL, "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"); - - } - - for (i = IM->CopyStart ; i <= IM->Count ; i++) { - _mesa_debug(NULL, "%u: ", i); - if (req & VERT_BITS_OBJ_234) { - if (flags[i] & VERT_BIT_EVAL_C1) - _mesa_debug(NULL, "EvalCoord %f ", - IM->Attrib[VERT_ATTRIB_POS][i][0]); - else if (flags[i] & VERT_BIT_EVAL_P1) - _mesa_debug(NULL, "EvalPoint %.0f ", - IM->Attrib[VERT_ATTRIB_POS][i][0]); - else if (flags[i] & VERT_BIT_EVAL_C2) - _mesa_debug(NULL, "EvalCoord %f %f ", - IM->Attrib[VERT_ATTRIB_POS][i][0], - IM->Attrib[VERT_ATTRIB_POS][i][1]); - else if (flags[i] & VERT_BIT_EVAL_P2) - _mesa_debug(NULL, "EvalPoint %.0f %.0f ", - IM->Attrib[VERT_ATTRIB_POS][i][0], - IM->Attrib[VERT_ATTRIB_POS][i][1]); - else if (i < IM->Count && (flags[i] & VERT_BITS_OBJ_234)) { - _mesa_debug(NULL, "Obj %f %f %f %f", - IM->Attrib[VERT_ATTRIB_POS][i][0], - IM->Attrib[VERT_ATTRIB_POS][i][1], - IM->Attrib[VERT_ATTRIB_POS][i][2], - IM->Attrib[VERT_ATTRIB_POS][i][3]); - } - } - - if (req & flags[i] & VERT_BIT_ELT) - _mesa_debug(NULL, " Elt %u\t", IM->Elt[i]); - - if (req & flags[i] & VERT_BIT_NORMAL) - _mesa_debug(NULL, " Norm %f %f %f ", - IM->Attrib[VERT_ATTRIB_NORMAL][i][0], - IM->Attrib[VERT_ATTRIB_NORMAL][i][1], - IM->Attrib[VERT_ATTRIB_NORMAL][i][2]); - - if (req & flags[i] & VERT_BITS_TEX_ANY) { - GLuint j; - for (j = 0 ; j < MAX_TEXTURE_COORD_UNITS ; j++) { - if (req & flags[i] & VERT_BIT_TEX(j)) { - _mesa_debug(NULL, "TC%d %f %f %f %f", j, - IM->Attrib[VERT_ATTRIB_TEX0 + j][i][0], - IM->Attrib[VERT_ATTRIB_TEX0 + j][i][1], - IM->Attrib[VERT_ATTRIB_TEX0 + j][i][2], - IM->Attrib[VERT_ATTRIB_TEX0 + j][i][3]); - } - } - } - - if (req & flags[i] & VERT_BIT_COLOR0) - _mesa_debug(NULL, " Rgba %f %f %f %f ", - IM->Attrib[VERT_ATTRIB_COLOR0][i][0], - IM->Attrib[VERT_ATTRIB_COLOR0][i][1], - IM->Attrib[VERT_ATTRIB_COLOR0][i][2], - IM->Attrib[VERT_ATTRIB_COLOR0][i][3]); - - if (req & flags[i] & VERT_BIT_COLOR1) - _mesa_debug(NULL, " Spec %f %f %f ", - IM->Attrib[VERT_ATTRIB_COLOR1][i][0], - IM->Attrib[VERT_ATTRIB_COLOR1][i][1], - IM->Attrib[VERT_ATTRIB_COLOR1][i][2]); - - if (req & flags[i] & VERT_BIT_FOG) - _mesa_debug(NULL, " Fog %f ", IM->Attrib[VERT_ATTRIB_FOG][i][0]); - - if (req & flags[i] & VERT_BIT_INDEX) - _mesa_debug(NULL, " Index %u ", IM->Index[i]); - - if (req & flags[i] & VERT_BIT_EDGEFLAG) - _mesa_debug(NULL, " Edgeflag %d ", IM->EdgeFlag[i]); - - if (req & flags[i] & VERT_BIT_MATERIAL) - _mesa_debug(NULL, " 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_BIT_END) - _mesa_debug(NULL, " END "); - - if (req & flags[i] & VERT_BIT_BEGIN) - _mesa_debug(NULL, " BEGIN(%s) (%s%s%s%s)", - _mesa_prim_name[IM->Primitive[i] & PRIM_MODE_MASK], - (IM->Primitive[i] & PRIM_LAST) ? "LAST," : "", - (IM->Primitive[i] & PRIM_BEGIN) ? "BEGIN," : "", - (IM->Primitive[i] & PRIM_END) ? "END," : "", - (IM->Primitive[i] & PRIM_PARITY) ? "PARITY," : ""); - - _mesa_debug(NULL, "\n"); - } -} diff --git a/src/mesa/tnl/t_imm_debug.h b/src/mesa/tnl/t_imm_debug.h deleted file mode 100644 index 91eea934798..00000000000 --- a/src/mesa/tnl/t_imm_debug.h +++ /dev/null @@ -1,38 +0,0 @@ - -/* - * Mesa 3-D graphics library - * Version: 3.5 - * - * 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"), - * 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 - */ - -#ifndef _T_DEBUG_H -#define _T_DEBUG_H - -#include "mtypes.h" -#include "t_context.h" - -void _tnl_print_cassette( struct immediate *IM ); -void _tnl_print_vert_flags( const char *name, GLuint flags ); - -#endif diff --git a/src/mesa/tnl/t_imm_dlist.c b/src/mesa/tnl/t_imm_dlist.c deleted file mode 100644 index 8fcc9b25f05..00000000000 --- a/src/mesa/tnl/t_imm_dlist.c +++ /dev/null @@ -1,667 +0,0 @@ -/* - * Mesa 3-D graphics library - * Version: 5.1 - * - * Copyright (C) 1999-2003 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 - */ - - -#include "glheader.h" -#include "context.h" -#include "dlist.h" -#include "debug.h" -#include "macros.h" -#include "imports.h" -#include "state.h" - -#include "t_context.h" -#include "t_imm_api.h" -#include "t_imm_elt.h" -#include "t_imm_alloc.h" -#include "t_imm_dlist.h" -#include "t_imm_debug.h" -#include "t_imm_exec.h" -#include "t_imm_fixup.h" -#include "t_pipeline.h" - -typedef struct { - struct immediate *IM; - GLuint Start; - GLuint Count; - GLuint BeginState; - GLuint SavedBeginState; - GLuint OrFlag; - GLuint AndFlag; - GLuint TexSize; - GLuint LastData; - GLuint LastPrimitive; - GLuint LastMaterial; - GLuint MaterialOrMask; - GLuint MaterialAndMask; -} TNLvertexcassette; - -static void execute_compiled_cassette( GLcontext *ctx, void *data ); -static void loopback_compiled_cassette( GLcontext *ctx, struct immediate *IM ); - - -static void -build_normal_lengths( struct immediate *IM ) -{ - GLuint i; - GLfloat len; - GLfloat (*data)[4] = IM->Attrib[VERT_ATTRIB_NORMAL] + IM->Start; - GLfloat *dest = IM->NormalLengthPtr; - const GLuint *flags = IM->Flag + IM->Start; - const GLuint count = IM->Count - IM->Start; - - if (!dest) { - dest = IM->NormalLengthPtr = (GLfloat *) ALIGN_MALLOC( IMM_SIZE*sizeof(GLfloat), 32 ); - if (!dest) return; - } - dest += IM->Start; - - len = (GLfloat) LEN_3FV( data[0] ); - if (len > 0.0F) len = 1.0F / len; - - for (i = 0 ; i < count ; ) { - dest[i] = len; - if (flags[++i] & VERT_BIT_NORMAL) { - len = (GLfloat) LEN_3FV( data[i] ); - if (len > 0.0F) len = 1.0F / len; - } - } -} - - -static void -fixup_normal_lengths( struct immediate *IM ) -{ - GLuint i; - GLfloat len = 1.0F; /* just to silence warnings */ - GLfloat (*data)[4] = IM->Attrib[VERT_ATTRIB_NORMAL]; - GLfloat *dest = IM->NormalLengthPtr; - const GLuint *flags = IM->Flag; - - for (i = IM->CopyStart ; i <= IM->Start ; i++) { - len = (GLfloat) LEN_3FV( data[i] ); - if (len > 0.0F) - len = 1.0F / len; - dest[i] = len; - } - - if (i < IM->Count) { - while (!(flags[i] & (VERT_BIT_NORMAL|VERT_BIT_END_VB))) { - dest[i] = len; - i++; - } - } -} - - - -/* Insert the active immediate struct onto the display list currently - * being built. - */ -void -_tnl_compile_cassette( GLcontext *ctx, struct immediate *IM ) -{ - struct immediate *im = TNL_CURRENT_IM(ctx); - TNLcontext *tnl = TNL_CONTEXT(ctx); - TNLvertexcassette *node; - GLuint new_beginstate; - - if (MESA_VERBOSE & VERBOSE_DISPLAY_LIST) - _mesa_debug(ctx, "_tnl_compiled_cassette IM: %d\n", IM->id); - - if (IM->FlushElt) { - ASSERT (IM->FlushElt == FLUSH_ELT_LAZY); - _tnl_translate_array_elts( ctx, IM, IM->Start, IM->Count ); - } - - _tnl_compute_orflag( IM, IM->Start ); - - /* Need to clear this flag, or fixup gets confused. (The - * array-elements have been translated away by now, so it's ok to - * remove it.) - */ - IM->OrFlag &= ~VERT_BIT_ELT; - IM->AndFlag &= ~VERT_BIT_ELT; - - _tnl_fixup_input( ctx, IM ); - - /* Allocate space for this structure in the display list currently - * being compiled. - */ - node = (TNLvertexcassette *) - _mesa_alloc_instruction(ctx, - tnl->opcode_vertex_cassette, - sizeof(TNLvertexcassette)); - if (!node) - return; - - node->IM = im; im->ref_count++; - node->Start = im->Start; - node->Count = im->Count; - node->BeginState = im->BeginState; - node->SavedBeginState = im->SavedBeginState; - node->OrFlag = im->OrFlag; - node->TexSize = im->TexSize; - node->AndFlag = im->AndFlag; - node->LastData = im->LastData; - node->LastPrimitive = im->LastPrimitive; - node->LastMaterial = im->LastMaterial; - node->MaterialOrMask = im->MaterialOrMask; - node->MaterialAndMask = im->MaterialAndMask; - - /* - * XXX always allocate VERT_ATTRIB_NORMAL array now??? - */ - if (tnl->CalcDListNormalLengths && IM->Attrib[VERT_ATTRIB_NORMAL]) { - build_normal_lengths( im ); - } - - if (ctx->ExecuteFlag) { - execute_compiled_cassette( ctx, (void *)node ); - } - - /* Discard any errors raised in the last cassette. - */ - new_beginstate = node->BeginState & (VERT_BEGIN_0|VERT_BEGIN_1); - - /* Decide whether this immediate struct is full, or can be used for - * the next batch of vertices as well. - */ - if (im->Count > IMM_MAXDATA - 16) { - /* Call it full... - */ - struct immediate *new_im = _tnl_alloc_immediate(ctx); - new_im->ref_count++; - im->ref_count--; /* remove CURRENT_IM reference */ - ASSERT(im->ref_count > 0); /* it is compiled into a display list */ - SET_IMMEDIATE( ctx, new_im ); - _tnl_reset_compile_input( ctx, IMM_MAX_COPIED_VERTS, - new_beginstate, node->SavedBeginState ); - } else { - /* Still some room in the current immediate. - */ - _tnl_reset_compile_input( ctx, im->Count+1+IMM_MAX_COPIED_VERTS, - new_beginstate, node->SavedBeginState); - } -} - - -static void -fixup_compiled_primitives( GLcontext *ctx, struct immediate *IM ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - - /* Can potentially overwrite primitive details - need to save the - * first slot: - */ - 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->BeginState & VERT_ERROR_1) - _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin/glEnd"); - - for (i = IM->Start ; i <= IM->Count ; i += IM->PrimitiveLength[i]) - if (IM->Flag[i] & (VERT_BIT_BEGIN|VERT_BIT_END_VB)) - break; - - /* 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->Flag[IM->Start] & VERT_BIT_BEGIN)) { - IM->Primitive[IM->CopyStart] = GL_POLYGON+1; - IM->PrimitiveLength[IM->CopyStart] = i - IM->CopyStart; - if (IM->Flag[i] & VERT_BIT_END_VB) { - IM->Primitive[IM->CopyStart] |= PRIM_LAST; - IM->LastPrimitive = IM->CopyStart; - } - } - } - else { - GLuint i; - - if (IM->BeginState & VERT_ERROR_0) - _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin/glEnd"); - - if (IM->CopyStart == IM->Start && - IM->Flag[IM->Start] & (VERT_BIT_END | VERT_BIT_END_VB)) - { - /* nothing */ - } - else - { - IM->Primitive[IM->CopyStart] = ctx->Driver.CurrentExecPrimitive; - if (tnl->ExecParity) - IM->Primitive[IM->CopyStart] |= PRIM_PARITY; - - /* one of these should be true, else we'll be in an infinite loop - */ - ASSERT(IM->PrimitiveLength[IM->Start] > 0 || - IM->Flag[IM->Start] & (VERT_BIT_END | VERT_BIT_END_VB)); - - for (i = IM->Start ; i <= IM->Count ; i += IM->PrimitiveLength[i]) { - if (IM->Flag[i] & (VERT_BIT_END | VERT_BIT_END_VB)) { - IM->PrimitiveLength[IM->CopyStart] = i - IM->CopyStart; - if (IM->Flag[i] & VERT_BIT_END_VB) { - IM->Primitive[IM->CopyStart] |= PRIM_LAST; - IM->LastPrimitive = IM->CopyStart; - } - if (IM->Flag[i] & VERT_BIT_END) { - IM->Primitive[IM->CopyStart] |= PRIM_END; - } - break; - } - } - } - } -} - - -/* Undo any changes potentially made to the immediate in the range - * IM->Start..IM->Count above. - */ -static void -restore_compiled_primitives( GLcontext *ctx, struct immediate *IM ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - IM->Primitive[IM->Start] = tnl->DlistPrimitive; - IM->PrimitiveLength[IM->Start] = tnl->DlistPrimitiveLength; -} - - -static void -execute_compiled_cassette( GLcontext *ctx, void *data ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - TNLvertexcassette *node = (TNLvertexcassette *)data; - struct immediate *IM = node->IM; - -/* _mesa_debug("%s\n", __FUNCTION__); */ - - IM->Start = node->Start; - IM->CopyStart = node->Start; - IM->Count = node->Count; - IM->BeginState = node->BeginState; - IM->SavedBeginState = node->SavedBeginState; - IM->OrFlag = node->OrFlag; - IM->TexSize = node->TexSize; - IM->AndFlag = node->AndFlag; - IM->LastData = node->LastData; - IM->LastPrimitive = node->LastPrimitive; - IM->LastMaterial = node->LastMaterial; - IM->MaterialOrMask = node->MaterialOrMask; - IM->MaterialAndMask = node->MaterialAndMask; - - if ((MESA_VERBOSE & VERBOSE_DISPLAY_LIST) && - (MESA_VERBOSE & VERBOSE_IMMEDIATE)) - _tnl_print_cassette( IM ); - - if (MESA_VERBOSE & VERBOSE_DISPLAY_LIST) { - _mesa_debug(ctx, "Run cassette %d, rows %d..%d, beginstate %x ", - IM->id, IM->Start, IM->Count, IM->BeginState); - _tnl_print_vert_flags("orflag", IM->OrFlag); - } - - - /* Need to respect 'HardBeginEnd' even if the commands are looped - * back to a driver tnl module. - */ - if (IM->SavedBeginState) { - if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) - tnl->ReplayHardBeginEnd = 1; - if (!tnl->ReplayHardBeginEnd) { - /* This is a user error. Whatever operation (like glRectf) - * decomposed to this hard begin/end pair is now being run - * inside a begin/end object -- illegally. Reject it and - * raise an error. - */ - _mesa_error(ctx, GL_INVALID_OPERATION, "hard replay"); - return; - } - } - - if (tnl->LoopbackDListCassettes) { -/* (tnl->IsolateMaterials && (IM->OrFlag & VERT_MATERIAL)) ) { */ - fixup_compiled_primitives( ctx, IM ); - loopback_compiled_cassette( ctx, IM ); - restore_compiled_primitives( ctx, IM ); - } - else { - if (ctx->NewState) - _mesa_update_state(ctx); - - if (tnl->pipeline.build_state_changes) - _tnl_validate_pipeline( ctx ); - - _tnl_fixup_compiled_cassette( ctx, IM ); - fixup_compiled_primitives( ctx, IM ); - - if (IM->Primitive[IM->LastPrimitive] & PRIM_END) - ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1; - else if ((IM->Primitive[IM->LastPrimitive] & PRIM_BEGIN) || - (IM->Primitive[IM->LastPrimitive] & PRIM_MODE_MASK) == - PRIM_OUTSIDE_BEGIN_END) { - ctx->Driver.CurrentExecPrimitive = - IM->Primitive[IM->LastPrimitive] & PRIM_MODE_MASK; - } - - _tnl_get_exec_copy_verts( ctx, IM ); - - if (IM->NormalLengthPtr) - fixup_normal_lengths( IM ); - - if (IM->Count == IM->Start) - _tnl_copy_to_current( ctx, IM, IM->OrFlag, IM->LastData ); - else { -/* _tnl_print_cassette( IM ); */ - _tnl_run_cassette( ctx, IM ); - } - - restore_compiled_primitives( ctx, IM ); - } - - if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) - tnl->ReplayHardBeginEnd = 0; -} - - -static void -destroy_compiled_cassette( GLcontext *ctx, void *data ) -{ - TNLvertexcassette *node = (TNLvertexcassette *)data; - - if ( --node->IM->ref_count == 0 ) - _tnl_free_immediate( ctx, node->IM ); -} - - -static void -print_compiled_cassette( GLcontext *ctx, void *data ) -{ - TNLvertexcassette *node = (TNLvertexcassette *)data; - struct immediate *IM = node->IM; - - _mesa_debug(ctx, "TNL-VERTEX-CASSETTE, id %u, rows %u..%u\n", - node->IM->id, node->Start, node->Count); - - IM->Start = node->Start; - IM->CopyStart = node->Start; - IM->Count = node->Count; - IM->BeginState = node->BeginState; - IM->OrFlag = node->OrFlag; - IM->TexSize = node->TexSize; - IM->AndFlag = node->AndFlag; - IM->LastData = node->LastData; - IM->LastPrimitive = node->LastPrimitive; - IM->LastMaterial = node->LastMaterial; - IM->MaterialOrMask = node->MaterialOrMask; - IM->MaterialAndMask = node->MaterialAndMask; - - _tnl_print_cassette( node->IM ); -} - - -void -_tnl_BeginCallList( GLcontext *ctx, GLuint list ) -{ - (void) ctx; - (void) list; - FLUSH_CURRENT(ctx, 0); -} - - -/* Called at the tail of a CallList. Make current immediate aware of - * any new to-be-copied vertices. - */ -void -_tnl_EndCallList( GLcontext *ctx ) -{ - GLuint beginstate = 0; - - if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) - beginstate = VERT_BEGIN_0|VERT_BEGIN_1; - - _tnl_reset_exec_input( ctx, TNL_CURRENT_IM(ctx)->Start, beginstate, 0 ); -} - - -void -_tnl_EndList( GLcontext *ctx ) -{ - struct immediate *IM = TNL_CURRENT_IM(ctx); - - ctx->swtnl_im = 0; - IM->ref_count--; - - /* outside begin/end, even in COMPILE_AND_EXEC, - * so no vertices to copy, right? - */ - ASSERT(TNL_CONTEXT(ctx)->ExecCopyCount == 0); - - /* If this one isn't free, get a clean one. (Otherwise we'll be - * using one that's already half full). - */ - if (IM->ref_count != 0) - IM = _tnl_alloc_immediate( ctx ); - - ASSERT(IM->ref_count == 0); - - SET_IMMEDIATE( ctx, IM ); - IM->ref_count++; - - _tnl_reset_exec_input( ctx, IMM_MAX_COPIED_VERTS, 0, 0 ); -} - - -void -_tnl_NewList( GLcontext *ctx, GLuint list, GLenum mode ) -{ - struct immediate *IM = TNL_CURRENT_IM(ctx); - - /* Use the installed immediate struct. No vertices in the current - * immediate, no copied vertices in the system. - */ - ASSERT(TNL_CURRENT_IM(ctx)); - ASSERT(TNL_CURRENT_IM(ctx)->Start == IMM_MAX_COPIED_VERTS); - ASSERT(TNL_CURRENT_IM(ctx)->Start == TNL_CURRENT_IM(ctx)->Count); - ASSERT(TNL_CONTEXT(ctx)->ExecCopyCount == 0); - - /* Set current Begin/End state to unknown: - */ - IM->BeginState = VERT_BEGIN_0; - ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN; -} - - -void -_tnl_dlist_init( GLcontext *ctx ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - - tnl->opcode_vertex_cassette = - _mesa_alloc_opcode( ctx, - sizeof(TNLvertexcassette), - execute_compiled_cassette, - destroy_compiled_cassette, - print_compiled_cassette ); -} - - -/** - * Call glMaterialfv for the attributes specified by bitmask, using the - * material colors in src. - */ -static void -emit_material( const struct gl_material *src, GLuint bitmask ) -{ - const GLfloat (*attr)[4] = src->Attrib; - - if (bitmask & MAT_BIT_FRONT_EMISSION) - glMaterialfv( GL_FRONT, GL_EMISSION, attr[MAT_ATTRIB_FRONT_EMISSION] ); - - if (bitmask & MAT_BIT_BACK_EMISSION) - glMaterialfv( GL_BACK, GL_EMISSION, attr[MAT_ATTRIB_BACK_EMISSION] ); - - if (bitmask & MAT_BIT_FRONT_AMBIENT) - glMaterialfv( GL_FRONT, GL_AMBIENT, attr[MAT_ATTRIB_FRONT_AMBIENT] ); - - if (bitmask & MAT_BIT_BACK_AMBIENT) - glMaterialfv( GL_BACK, GL_AMBIENT, attr[MAT_ATTRIB_BACK_AMBIENT] ); - - if (bitmask & MAT_BIT_FRONT_DIFFUSE) - glMaterialfv( GL_FRONT, GL_DIFFUSE, attr[MAT_ATTRIB_FRONT_DIFFUSE] ); - - if (bitmask & MAT_BIT_BACK_DIFFUSE) - glMaterialfv( GL_BACK, GL_DIFFUSE, attr[MAT_ATTRIB_BACK_DIFFUSE] ); - - if (bitmask & MAT_BIT_FRONT_SPECULAR) - glMaterialfv( GL_FRONT, GL_SPECULAR, attr[MAT_ATTRIB_FRONT_SPECULAR] ); - - if (bitmask & MAT_BIT_BACK_SPECULAR) - glMaterialfv( GL_BACK, GL_SPECULAR, attr[MAT_ATTRIB_BACK_SPECULAR] ); - - if (bitmask & MAT_BIT_FRONT_SHININESS) - glMaterialfv( GL_FRONT, GL_SHININESS, attr[MAT_ATTRIB_FRONT_SHININESS] ); - - if (bitmask & MAT_BIT_BACK_SHININESS) - glMaterialfv( GL_BACK, GL_SHININESS, attr[MAT_ATTRIB_BACK_SHININESS] ); - - if (bitmask & MAT_BIT_FRONT_INDEXES) - glMaterialfv( GL_FRONT, GL_COLOR_INDEXES, attr[MAT_ATTRIB_FRONT_INDEXES]); - - if (bitmask & MAT_BIT_BACK_INDEXES) - glMaterialfv( GL_BACK, GL_COLOR_INDEXES, attr[MAT_ATTRIB_BACK_INDEXES] ); -} - - -/* Low-performance helper function to allow driver-supplied tnl - * modules to process tnl display lists. This is primarily supplied - * to avoid fallbacks if CallList is invoked inside a Begin/End pair. - * For higher performance, drivers should fallback to tnl (if outside - * begin/end), or (for tnl hardware) implement their own display list - * mechanism. - */ -static void -loopback_compiled_cassette( GLcontext *ctx, struct immediate *IM ) -{ - const GLuint *flags = IM->Flag; - const GLuint orflag = IM->OrFlag; - void (GLAPIENTRY *vertex)( const GLfloat * ); - void (GLAPIENTRY *texcoordfv[MAX_TEXTURE_COORD_UNITS])( GLenum, const GLfloat * ); - GLuint i, j, p, length, prim = 0, maxtex = 0; - - if (orflag & VERT_BITS_OBJ_234) - vertex = (void (GLAPIENTRY *)(const GLfloat *)) glVertex4fv; - else - vertex = (void (GLAPIENTRY *)(const GLfloat *)) glVertex3fv; - - if (orflag & VERT_BITS_TEX_ANY) { - for (j = 0 ; j < ctx->Const.MaxTextureCoordUnits ; j++) { - if (orflag & VERT_BIT_TEX(j)) { - maxtex = j+1; - if ((IM->TexSize & TEX_SIZE_4(j)) == TEX_SIZE_4(j)) - texcoordfv[j] = glMultiTexCoord4fvARB; - else if (IM->TexSize & TEX_SIZE_3(j)) - texcoordfv[j] = glMultiTexCoord3fvARB; - else - texcoordfv[j] = glMultiTexCoord2fvARB; - } - } - } - - for (p = IM->Start ; !(prim & PRIM_LAST) ; p += length) - { - prim = IM->Primitive[p]; - length= IM->PrimitiveLength[p]; - ASSERT(length || (prim & PRIM_LAST)); - ASSERT((prim & PRIM_MODE_MASK) <= GL_POLYGON+1); - - if (prim & PRIM_BEGIN) { - glBegin(prim & PRIM_MODE_MASK); - } - - for ( i = p ; i <= p+length ; i++) { - if (flags[i] & VERT_BITS_TEX_ANY) { - GLuint k; - for (k = 0 ; k < maxtex ; k++) { - if (flags[i] & VERT_BIT_TEX(k)) { - texcoordfv[k]( GL_TEXTURE0_ARB + k, - IM->Attrib[VERT_ATTRIB_TEX0 + k][i] ); - } - } - } - - /* XXX Maybe we should jump through _glapi->Dispatch all the time?? */ - if (flags[i] & VERT_BIT_NORMAL) - glNormal3fv(IM->Attrib[VERT_ATTRIB_NORMAL][i]); - - if (flags[i] & VERT_BIT_COLOR0) - glColor4fv( IM->Attrib[VERT_ATTRIB_COLOR0][i] ); - - if (flags[i] & VERT_BIT_COLOR1) - _glapi_Dispatch->SecondaryColor3fvEXT( IM->Attrib[VERT_ATTRIB_COLOR1][i] ); - - if (flags[i] & VERT_BIT_FOG) - _glapi_Dispatch->FogCoordfEXT( IM->Attrib[VERT_ATTRIB_FOG][i][0] ); - - if (flags[i] & VERT_BIT_INDEX) - glIndexi( IM->Index[i] ); - - if (flags[i] & VERT_BIT_EDGEFLAG) - glEdgeFlag( IM->EdgeFlag[i] ); - - if (flags[i] & VERT_BIT_MATERIAL) - emit_material( &IM->Material[i], IM->MaterialMask[i] ); - - if (flags[i]&VERT_BITS_OBJ_234) - vertex( IM->Attrib[VERT_ATTRIB_POS][i] ); - else if (flags[i] & VERT_BIT_EVAL_C1) - glEvalCoord1f( IM->Attrib[VERT_ATTRIB_POS][i][0] ); - else if (flags[i] & VERT_BIT_EVAL_P1) - glEvalPoint1( (GLint) IM->Attrib[VERT_ATTRIB_POS][i][0] ); - else if (flags[i] & VERT_BIT_EVAL_C2) - glEvalCoord2f( IM->Attrib[VERT_ATTRIB_POS][i][0], - IM->Attrib[VERT_ATTRIB_POS][i][1] ); - else if (flags[i] & VERT_BIT_EVAL_P2) - glEvalPoint2( (GLint) IM->Attrib[VERT_ATTRIB_POS][i][0], - (GLint) IM->Attrib[VERT_ATTRIB_POS][i][1] ); - } - - if (prim & PRIM_END) { - glEnd(); - } - } -} diff --git a/src/mesa/tnl/t_imm_dlist.h b/src/mesa/tnl/t_imm_dlist.h deleted file mode 100644 index e12d4c05326..00000000000 --- a/src/mesa/tnl/t_imm_dlist.h +++ /dev/null @@ -1,44 +0,0 @@ - -/* - * Mesa 3-D graphics library - * Version: 3.5 - * - * 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"), - * 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 - */ - -#ifndef _T_DLIST_H -#define _T_DLIST_H - -#include "mtypes.h" -#include "t_context.h" - -extern void _tnl_dlist_init( GLcontext *ctx ); - -extern void _tnl_compile_cassette( GLcontext *ctx, struct immediate *IM ); -extern void _tnl_EndList( GLcontext *ctx ); -extern void _tnl_NewList( GLcontext *ctx, GLuint list, GLenum mode ); - -extern void _tnl_EndCallList( GLcontext *ctx ); -extern void _tnl_BeginCallList( GLcontext *ctx, GLuint list ); - -#endif diff --git a/src/mesa/tnl/t_imm_elt.h b/src/mesa/tnl/t_imm_elt.h deleted file mode 100644 index 811cb17c35c..00000000000 --- a/src/mesa/tnl/t_imm_elt.h +++ /dev/null @@ -1,45 +0,0 @@ - -/* - * Mesa 3-D graphics library - * Version: 3.5 - * - * 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"), - * 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 - */ - - -#ifndef _T_IMM_ELT_H_ -#define _T_IMM_ELT_H_ - -#include "mtypes.h" -#include "t_context.h" - - -extern void _tnl_imm_elt_init( void ); - -extern void _tnl_translate_array_elts( GLcontext *ctx, - struct immediate *IM, - GLuint start, - GLuint end ); - - -#endif diff --git a/src/mesa/tnl/t_imm_eval.h b/src/mesa/tnl/t_imm_eval.h deleted file mode 100644 index 58e8a38af50..00000000000 --- a/src/mesa/tnl/t_imm_eval.h +++ /dev/null @@ -1,38 +0,0 @@ - -/* - * Mesa 3-D graphics library - * Version: 3.5 - * - * 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"), - * 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. - */ - - -#ifndef _T_IMM_EVAL_H -#define _T_IMM_EVAL_H - - -#include "mtypes.h" -#include "t_context.h" - -extern void _tnl_eval_init( void ); - -extern void _tnl_eval_immediate( GLcontext *ctx, struct immediate *IM ); - -#endif diff --git a/src/mesa/tnl/t_imm_exec.c b/src/mesa/tnl/t_imm_exec.c deleted file mode 100644 index 14d214e8438..00000000000 --- a/src/mesa/tnl/t_imm_exec.c +++ /dev/null @@ -1,586 +0,0 @@ -/* - * Mesa 3-D graphics library - * Version: 5.1 - * - * Copyright (C) 1999-2003 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. - */ - -/** - * \file tnl/t_imm_exec.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 "macros.h" -#include "imports.h" -#include "light.h" -#include "state.h" -#include "mtypes.h" - -#include "math/m_matrix.h" -#include "math/m_xform.h" - -#include "t_context.h" -#include "t_array_import.h" -#include "t_imm_alloc.h" -#include "t_imm_api.h" -#include "t_imm_debug.h" -#include "t_imm_dlist.h" -#include "t_imm_eval.h" -#include "t_imm_elt.h" -#include "t_imm_exec.h" -#include "t_imm_fixup.h" -#include "t_pipeline.h" - - - -static void reset_input( GLcontext *ctx, - GLuint start, - GLuint beginstate, - GLuint savedbeginstate ) -{ - struct immediate *IM = TNL_CURRENT_IM(ctx); - - /* Clear the dirty part of the flag array. - */ - if (start < IM->Count+2) - MEMSET(IM->Flag + start, 0, sizeof(GLuint) * (IM->Count+2-start)); - - if (MESA_VERBOSE & VERBOSE_IMMEDIATE) - _mesa_debug(ctx, "reset_input: IM(%d) new %x\n", IM->id, 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 || - (ctx->VertexProgram.Enabled && - ctx->Array.VertexAttrib[0].Enabled)) ? 1 : 0; - 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; -} - - -void _tnl_reset_compile_input( GLcontext *ctx, - GLuint start, - GLuint beginstate, - GLuint savedbeginstate ) -{ - 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 ) -{ - GLuint attr; - - if (MESA_VERBOSE&VERBOSE_IMMEDIATE) - _tnl_print_vert_flags("copy to current", flag); - - for (attr = 1; attr < VERT_ATTRIB_MAX; attr++) { - if ((flag & (1 << attr)) && IM->Attrib[attr]) { - COPY_4FV(ctx->Current.Attrib[attr], IM->Attrib[attr][count]); - } - } - - /* special cases */ - if (flag & VERT_BIT_INDEX) - ctx->Current.Index = IM->Index[count]; - - if (flag & VERT_BIT_EDGEFLAG) - ctx->Current.EdgeFlag = IM->EdgeFlag[count]; - - if ((flag & VERT_BIT_COLOR0) && ctx->Light.ColorMaterialEnabled) { - _mesa_update_color_material(ctx, - ctx->Current.Attrib[VERT_ATTRIB_COLOR0]); - TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx ); - } - - if (flag & VERT_BIT_MATERIAL) { - _mesa_copy_materials( &ctx->Light.Material, - &IM->Material[IM->LastMaterial], - IM->MaterialOrMask ); - - _mesa_update_material( ctx, IM->MaterialOrMask ); - - TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx ); - } -} - - - -void _tnl_compute_orflag( struct immediate *IM, GLuint start ) -{ - GLuint count = IM->Count; - GLuint orflag = 0; - GLuint andflag = ~0U; - GLuint i; - - IM->LastData = count-1; - - - /* Compute the flags for the whole buffer. - */ - 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 - * eg. a single glMaterial call, in which case IM->Start == - * IM->Count, but the buffer is definitely not empty. - */ - if (IM->Flag[i] & VERT_BITS_DATA) { - IM->LastData++; - orflag |= IM->Flag[i]; - } - - IM->Flag[IM->LastData+1] |= VERT_BIT_END_VB; - IM->CopyAndFlag = IM->AndFlag = andflag; - IM->OrFlag = orflag; - IM->CopyOrFlag = orflag; - IM->Evaluated = 0; -} - - -/** - * 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. - */ -static void _tnl_vb_bind_immediate( GLcontext *ctx, struct immediate *IM ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - struct vertex_arrays *tmp = &tnl->imm_inputs; - GLuint inputs = tnl->pipeline.inputs; /* for copy-to-current */ - const GLuint start = IM->CopyStart; - const GLuint count = IM->Count - start; - - /* TODO: optimize the case where nothing has changed. (Just bind - * tmp to vb). - */ - - /* Setup constant data in the VB. - */ - VB->Count = count; - VB->FirstClipped = IMM_MAXDATA - IM->CopyStart; - VB->import_data = NULL; - VB->importable_data = 0; - - /* Need an IM->FirstPrimitive? - */ - VB->Primitive = IM->Primitive + IM->CopyStart; - VB->PrimitiveLength = IM->PrimitiveLength + IM->CopyStart; - VB->FirstPrimitive = 0; - - VB->Flag = IM->Flag + start; - - /* TexCoordPtr's are zeroed in loop below. - */ - 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); */ -/* _tnl_print_vert_flags("inputs", inputs); */ - - /* Setup the initial values of array pointers in the vb. - */ - 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_BITS_OBJ_234) == VERT_BITS_OBJ_234) - tmp->Obj.size = 4; - else if ((IM->CopyOrFlag & VERT_BITS_OBJ_234) == VERT_BITS_OBJ_23) - tmp->Obj.size = 3; - else - tmp->Obj.size = 2; - } - - 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; - tmp->Normal.size = 3; /* just to be safe */ - VB->NormalPtr = &tmp->Normal; - if (IM->NormalLengthPtr) - VB->NormalLengthPtr = IM->NormalLengthPtr + start; - } - - 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_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_BIT_COLOR1) { - tmp->SecondaryColor.Ptr = (GLubyte *) (IM->Attrib[VERT_ATTRIB_COLOR1] + start); - VB->SecondaryColorPtr[0] = &tmp->SecondaryColor; - } - - if (inputs & VERT_BIT_EDGEFLAG) { - VB->EdgeFlag = IM->EdgeFlag + start; - } - - if (inputs & VERT_BIT_COLOR0) { - if (IM->CopyOrFlag & VERT_BIT_COLOR0) { - tmp->Color.Ptr = (GLubyte *) (IM->Attrib[VERT_ATTRIB_COLOR0] + start); - tmp->Color.StrideB = 4 * sizeof(GLfloat); - tmp->Color.Flags = 0; - } - else { - tmp->Color.Ptr = (GLubyte *) 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_BITS_TEX_ANY) { - GLuint i; - for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { - VB->TexCoordPtr[i] = NULL; - if (inputs & VERT_BIT_TEX(i)) { - tmp->TexCoord[i].count = count; - 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)) - tmp->TexCoord[i].size = 4; - } - VB->TexCoordPtr[i] = &tmp->TexCoord[i]; - } - } - } - - if ((inputs & IM->OrFlag & 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_vert_cassette, execute_compiled_cassette, but not - * exec_elt_cassette. - */ -void _tnl_run_cassette( GLcontext *ctx, struct immediate *IM ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - - _tnl_vb_bind_immediate( ctx, IM ); - - 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->Driver.RunPipeline( ctx ); - tnl->pipeline.run_input_changes |= tnl->pipeline.inputs; - - _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 ) -{ - 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 ); - } - - _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; - - _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; - VB->FirstPrimitive = 0; - - /* Run the pipeline. No input changes as a result of this action. - */ - tnl->Driver.RunPipeline( ctx ); - - /* Still need to update current values: - */ - if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) { - _tnl_translate_array_elts( ctx, IM, IM->LastData, IM->LastData ); - _tnl_copy_to_current( ctx, IM, ctx->Array._Enabled, IM->LastData ); - } -} - - -static void -exec_empty_cassette( GLcontext *ctx, struct immediate *IM ) -{ - if (IM->FlushElt) - _tnl_translate_array_elts( ctx, IM, IM->CopyStart, IM->CopyStart ); - - _tnl_copy_to_current( ctx, IM, IM->OrFlag, IM->LastData ); -} - - - -/** - * 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); - - _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 ); - - if (IM->CopyStart == IM->Count) { - exec_empty_cassette( ctx, IM ); - } - else if ((IM->CopyOrFlag & VERT_BITS_DATA) == VERT_BIT_ELT && - ctx->Array.LockCount && - (ctx->Array.Vertex.Enabled || - (ctx->VertexProgram.Enabled && - ctx->Array.VertexAttrib[0].Enabled))) { - exec_elt_cassette( ctx, IM ); - } - else { - exec_vert_cassette( ctx, IM ); - } - - /* Only reuse the immediate if there are no copied vertices living - * inside it: - */ - { - 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 ); - } - - /* Don't unset FLUSH_STORED_VERTICES flag here as the driver might - * have other stored data of its own & be relying on the - * FlushVertices notification to clear it. - */ -} - - - - -/** - * Setup vector pointers that will be used to bind immediates to VB's. - */ -void _tnl_imm_init( GLcontext *ctx ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_arrays *tmp = &tnl->imm_inputs; - GLuint i; - static int firsttime = 1; - - if (firsttime) { - firsttime = 0; - _tnl_imm_elt_init(); - } - - ctx->swtnl_im = _tnl_alloc_immediate( ctx ); - TNL_CURRENT_IM(ctx)->ref_count++; - - tnl->ExecCopyTexSize = 0; - tnl->ExecCopyCount = 0; - tnl->ExecCopySource = 0; - - TNL_CURRENT_IM(ctx)->CopyStart = IMM_MAX_COPIED_VERTS; - - _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->Color.BufferObj = ctx->Array.NullBufferObj; - - 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; - tmp->SecondaryColor.BufferObj = ctx->Array.NullBufferObj; - - _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.MaxTextureCoordUnits; i++) - _mesa_vector4f_init( &tmp->TexCoord[i], 0, 0); - - /* Install the first immediate. Intially outside begin/end. - */ - _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_CURRENT_IM(ctx)->ref_count--; - if (TNL_CURRENT_IM(ctx)->ref_count == 0) - _tnl_free_immediate( ctx, 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; - } -} diff --git a/src/mesa/tnl/t_imm_exec.h b/src/mesa/tnl/t_imm_exec.h deleted file mode 100644 index 1cadf29c057..00000000000 --- a/src/mesa/tnl/t_imm_exec.h +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Mesa 3-D graphics library - * Version: 5.1 - * - * Copyright (C) 1999-2003 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. - */ - - -#ifndef _T_IMM_EXEC_H -#define _T_IMM_EXEC_H - -#include "mtypes.h" -#include "t_context.h" - - -/* Hook for ctx->Driver.FlushVertices: - */ -extern void _tnl_flush_vertices( GLcontext *ctx, GLuint flush_flags ); - -/* Called from imm_api.c and _tnl_flush_vertices: - */ -extern void _tnl_flush_immediate( GLcontext *ctx, struct immediate *IM ); - -/* Called from imm_dlist.c and _tnl_flush_immediate: - */ -extern void _tnl_run_cassette( GLcontext *ctx, struct immediate *IM ); -extern void _tnl_copy_to_current( GLcontext *ctx, struct immediate *IM, - GLuint flag, GLuint row ); - -/* Initialize some stuff: - */ -extern void _tnl_imm_init( GLcontext *ctx ); - -extern void _tnl_imm_destroy( GLcontext *ctx ); - -extern void _tnl_reset_exec_input( GLcontext *ctx, - GLuint start, - GLuint beginstate, - GLuint savedbeginstate ); - -extern void _tnl_reset_compile_input( GLcontext *ctx, - GLuint start, - GLuint beginstate, - GLuint savedbeginstate ); - -extern void _tnl_compute_orflag( struct immediate *IM, GLuint start ); -extern void _tnl_execute_cassette( GLcontext *ctx, struct immediate *IM ); - - - -#endif diff --git a/src/mesa/tnl/t_imm_fixup.c b/src/mesa/tnl/t_imm_fixup.c deleted file mode 100644 index 7cfacd4c0dc..00000000000 --- a/src/mesa/tnl/t_imm_fixup.c +++ /dev/null @@ -1,786 +0,0 @@ -/* - * Mesa 3-D graphics library - * Version: 5.1 - * - * Copyright (C) 1999-2003 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 - */ - - -#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 "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" - - -/* - * Indexed by primitive type (GL_POINTS=0, GL_LINES=1, GL_LINE_LOOP=2, etc) - */ -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], const 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_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_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], const GLuint flag[], GLuint match, - GLuint start, const GLfloat *dflt ) -{ - GLuint i = start-1; - match |= VERT_BIT_END_VB; - - while ((flag[++i]&match) == 0) - COPY_4FV(data[i], dflt); -} - - -static void -fixup_first_1ui( GLuint data[], const GLuint flag[], GLuint match, - GLuint start, const GLuint dflt ) -{ - GLuint i = start-1; - match |= VERT_BIT_END_VB; - - while ((flag[++i]&match) == 0) - data[i] = dflt; -} - - -static void -fixup_first_1ub( GLubyte data[], const 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); - - for (attrib = 0, attribBit = 1; attrib < 16; attrib++, attribBit <<= 1) { - if (copyMask & attribBit) { - if (!IM->Attrib[attrib]) { - IM->Attrib[attrib] = (GLfloat (*)[4]) _mesa_malloc(IMM_SIZE * 4 * sizeof(GLfloat)); - if (!IM->Attrib[attrib]) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "vertex processing3"); - return; - } - } - COPY_4FV( IM->Attrib[attrib][pos], ctx->Current.Attrib[attrib]); - } - } - - if (copyMask & VERT_BIT_INDEX) - IM->Index[pos] = ctx->Current.Index; - - if (copyMask & VERT_BIT_EDGEFLAG) - IM->EdgeFlag[pos] = ctx->Current.EdgeFlag; -} - - -/** - * Fill in missing vertex attributes in the incoming immediate structure. - * For example, suppose the following calls are made: - * glBegin() - * glColor(c1) - * glVertex(v1) - * glVertex(v2) - * glEnd() - * The v2 vertex should get color c1 since glColor wasn't called for v2. - * This function will make c2 be c1. Same story for all vertex attribs. - */ -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) { - const GLuint copy = fixup & ~IM->Flag[start]; - GLuint attr; - - /* 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); - - for (attr = 1; attr < VERT_ATTRIB_MAX; attr++) { /* skip 0 (POS) */ - const GLuint attrBit = 1 << attr; - if (fixup & attrBit) { - if (!IM->Attrib[attr]) { - IM->Attrib[attr] = (GLfloat (*)[4]) _mesa_malloc(IMM_SIZE * 4 * sizeof(GLfloat)); - if (!IM->Attrib[attr]) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "vertex processing"); - return; - } - } - - if (attr == VERT_BIT_COLOR0) { - /* special case, darn - try to remove someday */ - 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) - */ - } - else { - /* general case */ - if (orflag & attrBit) - _tnl_fixup_4f( IM->Attrib[attr], IM->Flag, start, attrBit ); - else - fixup_first_4f( IM->Attrib[attr], IM->Flag, VERT_BIT_END_VB, - start, IM->Attrib[attr][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] ); - } - - } - - /* 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_materials( &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 *) - MALLOC( sizeof(struct gl_material) * IMM_SIZE ); - next->MaterialMask = (GLuint *) MALLOC( sizeof(GLuint) * IMM_SIZE ); - } - - next->MaterialMask[dst] = prev->MaterialOrMask; - MEMCPY(&next->Material[dst], &prev->Material[src], - 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 || - (ctx->VertexProgram.Enabled && ctx->Array.VertexAttrib[0].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, attr; - - 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); */ - - /* Allocate attribute arrays in the destination immediate struct */ - for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { - if ((copy & (1 << attr)) && !next->Attrib[attr]) { - next->Attrib[attr] = (GLfloat (*)[4]) _mesa_malloc(IMM_SIZE * 4 * sizeof(GLfloat)); - if (!next->Attrib[attr]) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "vertex processing"); - return; - } - } - } - - /* 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. - * - * XXX try to use a loop over vertex attribs here. - */ - COPY_4FV( next->Attrib[VERT_ATTRIB_POS][dst], - inputs->Obj.data[isrc] ); - - if (copy & VERT_BIT_NORMAL) { - 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_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] ); - } - } - - /* the rest aren't used for evaluators */ - if (copy & VERT_BIT_COLOR1) - COPY_4FV( next->Attrib[VERT_ATTRIB_COLOR1][dst], - prev->Attrib[VERT_ATTRIB_COLOR1][src] ); - - if (copy & VERT_BIT_FOG) - COPY_4FV( next->Attrib[VERT_ATTRIB_FOG][dst], - prev->Attrib[VERT_ATTRIB_FOG][src] ); - - - if (copy & VERT_BIT_INDEX) - next->Index[dst] = inputs->Index.data[isrc]; - - if (copy & VERT_BIT_EDGEFLAG) - next->EdgeFlag[dst] = prev->EdgeFlag[src]; - - if (copy & VERT_BIT_ELT) - next->Elt[dst] = prev->Elt[src]; - - if (copy & VERT_BIT_MATERIAL) - if (prev->Flag[src] & VERT_BIT_MATERIAL) - copy_material(next, prev, dst, 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) { - GLuint attr; - - for (attr = 1; attr < VERT_ATTRIB_MAX; attr++) { /* skip 0 (POS) */ - const GLuint attrBit = 1 << attr; - if (fixup & attrBit) { - if (!IM->Attrib[attr]) { - IM->Attrib[attr] = (GLfloat (*)[4]) _mesa_malloc(IMM_SIZE * 4 * sizeof(GLfloat)); - if (!IM->Attrib[attr]) { - _mesa_error(ctx, GL_OUT_OF_MEMORY, "vertex processing"); - } - } - if (attr == VERT_ATTRIB_COLOR0) { - /* special case, darn */ - 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; - } - else { - fixup_first_4f(IM->Attrib[attr], IM->Flag, - attrBit, start, ctx->Current.Attrib[attr] ); - } - } - } - - 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_materials( &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_three( 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, /* GL_POINTS */ - copy_overflow, /* GL_LINES */ - copy_first_and_last, /* GL_LINE_LOOP */ - copy_last, /* GL_LINE_STRIP */ - copy_overflow, /* GL_TRIANGLES */ - copy_last_three, /* GL_TRIANGLE_STRIP */ - copy_first_and_last, /* GL_TRIANGLE_FAN */ - copy_overflow, /* GL_QUADS */ - copy_last_three, /* GL_QUAD_STRIP */ - copy_first_and_last, /* GL_POLYGON */ - 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]]; - } -} - - -/** - * Called via the VB->import_data function pointer. - */ -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 = (GLubyte *) (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; - } -} diff --git a/src/mesa/tnl/t_imm_fixup.h b/src/mesa/tnl/t_imm_fixup.h deleted file mode 100644 index a2121bb8c92..00000000000 --- a/src/mesa/tnl/t_imm_fixup.h +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Mesa 3-D graphics library - * Version: 5.1 - * - * Copyright (C) 1999-2003 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. - */ - - -#ifndef _T_IMM_FIXUP_H -#define _T_IMM_FIXUP_H - -#include "mtypes.h" -#include "t_context.h" - -extern void _tnl_fixup_1ub( GLubyte *data, GLuint flag[], - GLuint start, GLuint match ); - -extern void _tnl_fixup_1ui( GLuint *data, GLuint flag[], - GLuint start, GLuint match ); - -extern void _tnl_fixup_4f( GLfloat data[][4], const GLuint flag[], - GLuint start, GLuint match ); - -extern void _tnl_fixup_input( GLcontext *ctx, struct immediate *IM ); - -extern void _tnl_fixup_compiled_cassette( GLcontext *ctx, - struct immediate *IM ); - -extern void _tnl_copy_immediate_vertices( GLcontext *ctx, - struct immediate *IM ); - -extern void _tnl_get_purged_copy_verts( GLcontext *ctx, struct immediate *IM ); - -extern void _tnl_get_exec_copy_verts( GLcontext *ctx, struct immediate *IM ); - -extern void _tnl_upgrade_current_data( GLcontext *ctx, GLuint required, - GLuint flags ); - -#endif diff --git a/src/mesa/tnl/t_pipeline.c b/src/mesa/tnl/t_pipeline.c index c187cf56a10..5e40309cd0d 100644 --- a/src/mesa/tnl/t_pipeline.c +++ b/src/mesa/tnl/t_pipeline.c @@ -40,10 +40,10 @@ void _tnl_install_pipeline( GLcontext *ctx, - const struct gl_pipeline_stage **stages ) + const struct tnl_pipeline_stage **stages ) { TNLcontext *tnl = TNL_CONTEXT(ctx); - struct gl_pipeline *pipe = &tnl->pipeline; + struct tnl_pipeline *pipe = &tnl->pipeline; GLuint i; ASSERT(pipe->nr_stages == 0); @@ -82,8 +82,8 @@ void _tnl_destroy_pipeline( GLcontext *ctx ) void _tnl_validate_pipeline( GLcontext *ctx ) { TNLcontext *tnl = TNL_CONTEXT(ctx); - struct gl_pipeline *pipe = &tnl->pipeline; - struct gl_pipeline_stage *s = pipe->stages; + struct tnl_pipeline *pipe = &tnl->pipeline; + struct tnl_pipeline_stage *s = pipe->stages; GLuint newstate = pipe->build_state_changes; GLuint generated = 0; GLuint changed_inputs = 0; @@ -118,9 +118,8 @@ void _tnl_validate_pipeline( GLcontext *ctx ) void _tnl_run_pipeline( GLcontext *ctx ) { TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - struct gl_pipeline *pipe = &tnl->pipeline; - struct gl_pipeline_stage *s = pipe->stages; + struct tnl_pipeline *pipe = &tnl->pipeline; + struct tnl_pipeline_stage *s = pipe->stages; GLuint changed_state = pipe->run_state_changes; GLuint changed_inputs = pipe->run_input_changes; GLboolean running = GL_TRUE; @@ -153,7 +152,6 @@ void _tnl_run_pipeline( GLcontext *ctx ) running = s->run( ctx, s ); s->changed_inputs = 0; - VB->importable_data &= ~s->outputs; } } @@ -184,7 +182,7 @@ void _tnl_run_pipeline( GLcontext *ctx ) * * - inserting optimized (but specialized) stages ahead of the * general-purpose fallback implementation. For example, the old - * fastpath mechanism, which only works when the VERT_BIT_ELT input is + * fastpath mechanism, which only works when the VB->Elts input is * available, can be duplicated by placing the fastpath stage at the * head of this pipeline. Such specialized stages are currently * constrained to have no outputs (ie. they must either finish the * @@ -193,7 +191,7 @@ void _tnl_run_pipeline( GLcontext *ctx ) * Some work can be done to lift some of the restrictions in the final * case, if it becomes necessary to do so. */ -const struct gl_pipeline_stage *_tnl_default_pipeline[] = { +const struct tnl_pipeline_stage *_tnl_default_pipeline[] = { &_tnl_vertex_transform_stage, &_tnl_normal_transform_stage, &_tnl_lighting_stage, diff --git a/src/mesa/tnl/t_pipeline.h b/src/mesa/tnl/t_pipeline.h index 9ccdb799890..02128ea8fd3 100644 --- a/src/mesa/tnl/t_pipeline.h +++ b/src/mesa/tnl/t_pipeline.h @@ -41,24 +41,24 @@ extern void _tnl_validate_pipeline( GLcontext *ctx ); extern void _tnl_destroy_pipeline( GLcontext *ctx ); extern void _tnl_install_pipeline( GLcontext *ctx, - const struct gl_pipeline_stage **stages ); + const struct tnl_pipeline_stage **stages ); /* These are implemented in the t_vb_*.c files: */ -extern const struct gl_pipeline_stage _tnl_vertex_transform_stage; -extern const struct gl_pipeline_stage _tnl_normal_transform_stage; -extern const struct gl_pipeline_stage _tnl_lighting_stage; -extern const struct gl_pipeline_stage _tnl_fog_coordinate_stage; -extern const struct gl_pipeline_stage _tnl_texgen_stage; -extern const struct gl_pipeline_stage _tnl_texture_transform_stage; -extern const struct gl_pipeline_stage _tnl_point_attenuation_stage; -extern const struct gl_pipeline_stage _tnl_vertex_program_stage; -extern const struct gl_pipeline_stage _tnl_render_stage; +extern const struct tnl_pipeline_stage _tnl_vertex_transform_stage; +extern const struct tnl_pipeline_stage _tnl_normal_transform_stage; +extern const struct tnl_pipeline_stage _tnl_lighting_stage; +extern const struct tnl_pipeline_stage _tnl_fog_coordinate_stage; +extern const struct tnl_pipeline_stage _tnl_texgen_stage; +extern const struct tnl_pipeline_stage _tnl_texture_transform_stage; +extern const struct tnl_pipeline_stage _tnl_point_attenuation_stage; +extern const struct tnl_pipeline_stage _tnl_vertex_program_stage; +extern const struct tnl_pipeline_stage _tnl_render_stage; /* Shorthand to plug in the default pipeline: */ -extern const struct gl_pipeline_stage *_tnl_default_pipeline[]; +extern const struct tnl_pipeline_stage *_tnl_default_pipeline[]; /* Convenience routines provided by t_vb_render.c: diff --git a/src/mesa/tnl/t_save_api.c b/src/mesa/tnl/t_save_api.c new file mode 100644 index 00000000000..63a59e77d1b --- /dev/null +++ b/src/mesa/tnl/t_save_api.c @@ -0,0 +1,1580 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas. + +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 +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS 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 + */ + + + +/* Display list compiler attempts to store lists of vertices with the + * same vertex layout. Additionally it attempts to minimize the need + * for execute-time fixup of these vertex lists, allowing them to be + * cached on hardware. + * + * There are still some circumstances where this can be thwarted, for + * example by building a list that consists of one very long primitive + * (eg Begin(Triangles), 1000 vertices, End), and calling that list + * from inside a different begin/end object (Begin(Lines), CallList, + * End). + * + * In that case the code will have to replay the list as individual + * commands through the Exec dispatch table, or fix up the copied + * vertices at execute-time. + * + * The other case where fixup is required is when a vertex attribute + * is introduced in the middle of a primitive. Eg: + * Begin(Lines) + * TexCoord1f() Vertex2f() + * TexCoord1f() Color3f() Vertex2f() + * End() + * + * If the current value of Color isn't known at compile-time, this + * primitive will require fixup. + * + * + * The list compiler currently doesn't attempt to compile lists + * containing EvalCoord or EvalPoint commands. On encountering one of + * these, compilation falls back to opcodes. + * + * This could be improved to fallback only when a mix of EvalCoord and + * Vertex commands are issued within a single primitive. + */ + + +#include "context.h" +#include "dlist.h" +#include "enums.h" +#include "macros.h" +#include "api_validate.h" +#include "api_arrayelt.h" +#include "vtxfmt.h" +#include "t_save_api.h" + +/* + * NOTE: Old 'parity' issue is gone, but copying can still be + * wrong-footed on replay. + */ +static GLuint _save_copy_vertices( GLcontext *ctx, + struct tnl_vertex_list *node ) +{ + TNLcontext *tnl = TNL_CONTEXT( ctx ); + struct tnl_prim *prim = &node->prim[node->prim_count-1]; + GLuint nr = prim->count; + GLuint sz = tnl->save.vertex_size; + GLfloat *src = node->buffer + prim->start * sz; + GLfloat *dst = tnl->save.copied.buffer; + GLuint ovf, i; + + if (prim->mode & PRIM_END) + return 0; + + switch( prim->mode & PRIM_MODE_MASK ) + { + case GL_POINTS: + return 0; + case GL_LINES: + ovf = nr&1; + for (i = 0 ; i < ovf ; i++) + memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) ); + return i; + case GL_TRIANGLES: + ovf = nr%3; + for (i = 0 ; i < ovf ; i++) + memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) ); + return i; + case GL_QUADS: + ovf = nr&3; + for (i = 0 ; i < ovf ; i++) + memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) ); + return i; + case GL_LINE_STRIP: + if (nr == 0) + return 0; + else { + memcpy( dst, src+(nr-1)*sz, sz*sizeof(GLfloat) ); + return 1; + } + case GL_LINE_LOOP: + case GL_TRIANGLE_FAN: + case GL_POLYGON: + if (nr == 0) + return 0; + else if (nr == 1) { + memcpy( dst, src+0, sz*sizeof(GLfloat) ); + return 1; + } else { + memcpy( dst, src+0, sz*sizeof(GLfloat) ); + memcpy( dst+sz, src+(nr-1)*sz, sz*sizeof(GLfloat) ); + return 2; + } + case GL_TRIANGLE_STRIP: + case GL_QUAD_STRIP: + switch (nr) { + case 0: ovf = 0; break; + case 1: ovf = 1; break; + default: ovf = 2 + (nr&1); break; + } + for (i = 0 ; i < ovf ; i++) + memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz*sizeof(GLfloat) ); + return i; + default: + assert(0); + return 0; + } +} + + +static void +build_normal_lengths( struct tnl_vertex_list *node ) +{ + GLuint i; + GLfloat *len; + GLfloat *n = node->buffer; + GLuint stride = node->vertex_size; + GLuint count = node->count; + + len = node->normal_lengths = MALLOC( count * sizeof(GLfloat) ); + if (!len) + return; + + /* Find the normal of the first vertex: + */ + for (i = 0 ; i < _TNL_ATTRIB_NORMAL ; i++) + n += node->attrsz[i]; + + for (i = 0 ; i < count ; i++, n += stride) { + len[i] = LEN_3FV( n ); + if (len[i] > 0.0F) len[i] = 1.0F / len[i]; + } +} + +static struct tnl_vertex_store *alloc_vertex_store( GLcontext *ctx ) +{ + struct tnl_vertex_store *store = MALLOC( sizeof(*store) ); + store->used = 0; + store->refcount = 1; + return store; +} + +static struct tnl_primitive_store *alloc_prim_store( GLcontext *ctx ) +{ + struct tnl_primitive_store *store = MALLOC( sizeof(*store) ); + store->used = 0; + store->refcount = 1; + return store; +} + +static void _save_reset_counters( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + + tnl->save.prim = tnl->save.prim_store->buffer + tnl->save.prim_store->used; + tnl->save.buffer = (tnl->save.vertex_store->buffer + + tnl->save.vertex_store->used); + + if (tnl->save.vertex_size) + tnl->save.initial_counter = ((SAVE_BUFFER_SIZE - + tnl->save.vertex_store->used) / + tnl->save.vertex_size); + else + tnl->save.initial_counter = 0; + + if (tnl->save.initial_counter > ctx->Const.MaxArrayLockSize ) + tnl->save.initial_counter = ctx->Const.MaxArrayLockSize; + + tnl->save.counter = tnl->save.initial_counter; + tnl->save.prim_count = 0; + tnl->save.prim_max = SAVE_PRIM_SIZE - tnl->save.prim_store->used; + tnl->save.copied.nr = 0; + tnl->save.dangling_attr_ref = 0; +} + + +/* Insert the active immediate struct onto the display list currently + * being built. + */ +static void _save_compile_vertex_list( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct tnl_vertex_list *node; + + /* Allocate space for this structure in the display list currently + * being compiled. + */ + node = (struct tnl_vertex_list *) + _mesa_alloc_instruction(ctx, tnl->save.opcode_vertex_list, sizeof(*node)); + + if (!node) + return; + + /* Duplicate our template, increment refcounts to the storage structs: + */ + memcpy(node->attrsz, tnl->save.attrsz, sizeof(node->attrsz)); + node->vertex_size = tnl->save.vertex_size; + node->buffer = tnl->save.buffer; + node->wrap_count = tnl->save.copied.nr; + node->count = tnl->save.initial_counter - tnl->save.counter; + node->prim = tnl->save.prim; + node->prim_count = tnl->save.prim_count; + node->vertex_store = tnl->save.vertex_store; + node->prim_store = tnl->save.prim_store; + node->dangling_attr_ref = tnl->save.dangling_attr_ref; + node->normal_lengths = 0; + + node->vertex_store->refcount++; + node->prim_store->refcount++; + + assert(node->attrsz[_TNL_ATTRIB_POS] != 0); + + /* Maybe calculate normal lengths: + */ + if (tnl->CalcDListNormalLengths && + node->attrsz[_TNL_ATTRIB_NORMAL] == 3 && + !node->dangling_attr_ref) + build_normal_lengths( node ); + + tnl->save.vertex_store->used += tnl->save.vertex_size * node->count; + tnl->save.prim_store->used += node->prim_count; + + /* Decide whether the storage structs are full, or can be used for + * the next vertex lists as well. + */ + if (tnl->save.vertex_store->used > + SAVE_BUFFER_SIZE - 16 * (tnl->save.vertex_size + 4)) { + + tnl->save.vertex_store->refcount--; + assert(tnl->save.vertex_store->refcount != 0); + tnl->save.vertex_store = alloc_vertex_store( ctx ); + tnl->save.vbptr = tnl->save.vertex_store->buffer; + } + + if (tnl->save.prim_store->used > SAVE_PRIM_SIZE - 6) { + tnl->save.prim_store->refcount--; + assert(tnl->save.prim_store->refcount != 0); + tnl->save.prim_store = alloc_prim_store( ctx ); + } + + /* Reset our structures for the next run of vertices: + */ + _save_reset_counters( ctx ); + + /* Copy duplicated vertices + */ + tnl->save.copied.nr = _save_copy_vertices( ctx, node ); + + + /* Deal with GL_COMPILE_AND_EXECUTE: + */ + if (ctx->ExecuteFlag) { + _tnl_playback_vertex_list( ctx, (void *)node ); + } +} + + +/* TODO -- If no new vertices have been stored, don't bother saving + * it. + */ +static void _save_wrap_buffers( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLint i = tnl->save.prim_count - 1; + GLenum mode; + + assert(i < tnl->save.prim_max); + assert(i >= 0); + + /* Close off in-progress primitive. + */ + tnl->save.prim[i].count = ((tnl->save.initial_counter - tnl->save.counter) - + tnl->save.prim[i].start); + mode = tnl->save.prim[i].mode & ~(PRIM_BEGIN|PRIM_END); + + /* store the copied vertices, and allocate a new list. + */ + _save_compile_vertex_list( ctx ); + + /* Restart interrupted primitive + */ + tnl->save.prim[0].mode = mode; + tnl->save.prim[0].start = 0; + tnl->save.prim[0].count = 0; + tnl->save.prim_count = 1; +} + + + +/* Called only when buffers are wrapped as the result of filling the + * vertex_store struct. + */ +static void _save_wrap_filled_vertex( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLfloat *data = tnl->save.copied.buffer; + int i; + + /* Emit a glEnd to close off the last vertex list. + */ + _save_wrap_buffers( ctx ); + + /* Copy stored stored vertices to start of new list. + */ + assert(tnl->save.counter > tnl->save.copied.nr); + + for (i = 0 ; i < tnl->save.copied.nr ; i++) { + memcpy( tnl->save.vbptr, data, tnl->save.vertex_size * sizeof(GLfloat)); + data += tnl->save.vertex_size; + tnl->save.vbptr += tnl->save.vertex_size; + tnl->save.counter--; + } +} + + +static void _save_copy_to_current( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint i; + + for (i = _TNL_ATTRIB_POS+1 ; i <= _TNL_ATTRIB_INDEX ; i++) { + if (tnl->save.attrsz[i]) { + tnl->save.currentsz[i][0] = tnl->save.attrsz[i]; + ASSIGN_4V(tnl->save.current[i], 0, 0, 0, 1); + COPY_SZ_4V(tnl->save.current[i], + tnl->save.attrsz[i], + tnl->save.attrptr[i]); + } + } + + /* Edgeflag requires special treatment: + */ + if (tnl->save.attrsz[_TNL_ATTRIB_EDGEFLAG]) { + ctx->ListState.ActiveEdgeFlag = 1; + ctx->ListState.CurrentEdgeFlag = + (tnl->save.attrptr[_TNL_ATTRIB_EDGEFLAG][0] == 1.0); + } +} + + +static void _save_copy_from_current( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLint i; + + for (i = _TNL_ATTRIB_POS+1 ; i <= _TNL_ATTRIB_INDEX ; i++) + switch (tnl->save.attrsz[i]) { + case 4: tnl->save.attrptr[i][3] = tnl->save.current[i][3]; + case 3: tnl->save.attrptr[i][2] = tnl->save.current[i][2]; + case 2: tnl->save.attrptr[i][1] = tnl->save.current[i][1]; + case 1: tnl->save.attrptr[i][0] = tnl->save.current[i][0]; + case 0: break; + } + + /* Edgeflag requires special treatment: + */ + if (tnl->save.attrsz[_TNL_ATTRIB_EDGEFLAG]) + tnl->save.attrptr[_TNL_ATTRIB_EDGEFLAG][0] = + (GLfloat)ctx->ListState.CurrentEdgeFlag; +} + + + + +/* Flush existing data, set new attrib size, replay copied vertices. + */ +static void _save_upgrade_vertex( GLcontext *ctx, + GLuint attr, + GLuint newsz ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint oldsz; + GLuint i; + GLfloat *tmp; + + /* Store the current run of vertices, and emit a GL_END. Emit a + * BEGIN in the new buffer. + */ + if (tnl->save.initial_counter != tnl->save.counter) + _save_wrap_buffers( ctx ); + else + assert( tnl->save.copied.nr == 0 ); + + /* Do a COPY_TO_CURRENT to ensure back-copying works for the case + * when the attribute already exists in the vertex and is having + * its size increased. + */ + _save_copy_to_current( ctx ); + + /* Fix up sizes: + */ + oldsz = tnl->save.attrsz[attr]; + tnl->save.attrsz[attr] = newsz; + + tnl->save.vertex_size += newsz - oldsz; + tnl->save.counter = ((SAVE_BUFFER_SIZE - tnl->save.vertex_store->used) / + tnl->save.vertex_size); + tnl->save.initial_counter = tnl->save.counter; + + + /* Recalculate all the attrptr[] values: + */ + for (i = 0, tmp = tnl->save.vertex ; i < _TNL_ATTRIB_MAX ; i++) { + if (tnl->save.attrsz[i]) { + tnl->save.attrptr[i] = tmp; + tmp += tnl->save.attrsz[i]; + } + else + tnl->save.attrptr[i] = 0; /* will not be dereferenced. */ + } + + /* Copy from current to repopulate the vertex with correct values. + */ + _save_copy_from_current( ctx ); + + + /* Replay stored vertices to translate them to new format here. + * + * If there are copied vertices and the new (upgraded) attribute + * has not been defined before, this list is somewhat degenerate, + * and will need fixup at runtime. + */ + if (tnl->save.copied.nr) + { + GLfloat *data = tnl->save.copied.buffer; + GLfloat *dest = tnl->save.buffer; + GLint j; + + /* Need to note this and fix up at runtime (or loopback): + */ + if (tnl->save.currentsz[attr] == 0) { + assert(oldsz == 0); + tnl->save.dangling_attr_ref = attr; + _mesa_debug(0, "%s: dangling reference attr %d\n", + __FUNCTION__, attr); + +#if 0 + /* The current strategy is to punt these degenerate cases + * through _tnl_loopback_vertex_list(), a lower-performance + * option. To minimize the impact of this, artificially + * reduce the size of this vertex_list. + */ + if (t->save.counter > 10) { + t->save.initial_counter = 10; + t->save.counter = 10; + } +#endif + } + + for (i = 0 ; i < tnl->save.copied.nr ; i++) { + for (j = 0 ; j < _TNL_ATTRIB_MAX ; j++) { + if (tnl->save.attrsz[j]) { + if (j == attr) { + ASSIGN_4V( dest, 0, 0, 0, 1 ); + COPY_SZ_4V( dest, oldsz, data ); + data += oldsz; + dest += newsz; + } + else { + GLint sz = tnl->save.attrsz[j]; + COPY_SZ_4V( dest, sz, data ); + data += sz; + dest += sz; + } + } + } + } + + tnl->save.vbptr = dest; + tnl->save.counter -= tnl->save.copied.nr; + } +} + + + + +/* Helper function for 'CHOOSE' macro. Do what's necessary when an + * entrypoint is called for the first time. + */ +static void do_choose( GLuint attr, GLuint sz, + void (*attr_func)( const GLfloat *), + void (*choose1)( const GLfloat *), + void (*choose2)( const GLfloat *), + void (*choose3)( const GLfloat *), + void (*choose4)( const GLfloat *), + const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + TNLcontext *tnl = TNL_CONTEXT(ctx); + static GLfloat id[4] = { 0, 0, 0, 1 }; + int i; + + if (tnl->save.attrsz[attr] < sz) { + /* New size is larger. Need to flush existing vertices and get + * an enlarged vertex format. + */ + _save_upgrade_vertex( ctx, attr, sz ); + } + else { + /* New size is equal or smaller - just need to fill in some + * zeros. + */ + for (i = sz ; i <= tnl->save.attrsz[attr] ; i++) + tnl->save.attrptr[attr][i-1] = id[i-1]; + } + + /* Reset any active pointers for this attribute + */ + tnl->save.tabfv[attr][0] = choose1; + tnl->save.tabfv[attr][1] = choose2; + tnl->save.tabfv[attr][2] = choose3; + tnl->save.tabfv[attr][3] = choose4; + + /* Update the secondary dispatch table with the new function + */ + tnl->save.tabfv[attr][sz-1] = attr_func; + + (*attr_func)(v); +} + + + +/* Only one size for each attribute may be active at once. Eg. if + * Color3f is installed/active, then Color4f may not be, even if the + * vertex actually contains 4 color coordinates. This is because the + * 3f version won't otherwise set color[3] to 1.0 -- this is the job + * of the chooser function when switching between Color4f and Color3f. + */ +#define ATTRFV( ATTR, N ) \ +static void save_choose_##ATTR##_##N( const GLfloat *v ); \ + \ +static void save_attrib_##ATTR##_##N( const GLfloat *v ) \ +{ \ + GET_CURRENT_CONTEXT( ctx ); \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + \ + if ((ATTR) == 0) { \ + int i; \ + \ + if (N>0) tnl->save.vbptr[0] = v[0]; \ + if (N>1) tnl->save.vbptr[1] = v[1]; \ + if (N>2) tnl->save.vbptr[2] = v[2]; \ + if (N>3) tnl->save.vbptr[3] = v[3]; \ + \ + for (i = N; i < tnl->save.vertex_size; i++) \ + tnl->save.vbptr[i] = tnl->save.vertex[i]; \ + \ + tnl->save.vbptr += tnl->save.vertex_size; \ + \ + if (--tnl->save.counter == 0) \ + _save_wrap_filled_vertex( ctx ); \ + } \ + else { \ + GLfloat *dest = tnl->save.attrptr[ATTR]; \ + if (N>0) dest[0] = v[0]; \ + if (N>1) dest[1] = v[1]; \ + if (N>2) dest[2] = v[2]; \ + if (N>3) dest[3] = v[3]; \ + } \ +} + +#define CHOOSE( ATTR, N ) \ +static void save_choose_##ATTR##_##N( const GLfloat *v ) \ +{ \ + do_choose(ATTR, N, \ + save_attrib_##ATTR##_##N, \ + save_choose_##ATTR##_1, \ + save_choose_##ATTR##_2, \ + save_choose_##ATTR##_3, \ + save_choose_##ATTR##_4, \ + v ); \ +} + +#define INIT(ATTR) \ +static void save_init_##ATTR( TNLcontext *tnl ) \ +{ \ + tnl->save.tabfv[ATTR][0] = save_choose_##ATTR##_1; \ + tnl->save.tabfv[ATTR][1] = save_choose_##ATTR##_2; \ + tnl->save.tabfv[ATTR][2] = save_choose_##ATTR##_3; \ + tnl->save.tabfv[ATTR][3] = save_choose_##ATTR##_4; \ +} + +#define ATTRS( ATTRIB ) \ + ATTRFV( ATTRIB, 1 ) \ + ATTRFV( ATTRIB, 2 ) \ + ATTRFV( ATTRIB, 3 ) \ + ATTRFV( ATTRIB, 4 ) \ + CHOOSE( ATTRIB, 1 ) \ + CHOOSE( ATTRIB, 2 ) \ + CHOOSE( ATTRIB, 3 ) \ + CHOOSE( ATTRIB, 4 ) \ + INIT( ATTRIB ) \ + + +/* Generate a lot of functions. These are the actual worker + * functions, which are equivalent to those generated via codegen + * elsewhere. + */ +ATTRS( 0 ) +ATTRS( 1 ) +ATTRS( 2 ) +ATTRS( 3 ) +ATTRS( 4 ) +ATTRS( 5 ) +ATTRS( 6 ) +ATTRS( 7 ) +ATTRS( 8 ) +ATTRS( 9 ) +ATTRS( 10 ) +ATTRS( 11 ) +ATTRS( 12 ) +ATTRS( 13 ) +ATTRS( 14 ) +ATTRS( 15 ) + + +static void _save_reset_vertex( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint i; + + save_init_0( tnl ); + save_init_1( tnl ); + save_init_2( tnl ); + save_init_3( tnl ); + save_init_4( tnl ); + save_init_5( tnl ); + save_init_6( tnl ); + save_init_7( tnl ); + save_init_8( tnl ); + save_init_9( tnl ); + save_init_10( tnl ); + save_init_11( tnl ); + save_init_12( tnl ); + save_init_13( tnl ); + save_init_14( tnl ); + save_init_15( tnl ); + + for (i = 0 ; i < _TNL_ATTRIB_MAX ; i++) + tnl->save.attrsz[i] = 0; + + tnl->save.vertex_size = 0; + + _save_reset_counters( ctx ); +} + + + +/* Cope with aliasing of classic Vertex, Normal, etc. and the fan-out + * of glMultTexCoord and glProgramParamterNV by routing all these + * through a second level dispatch table. + */ +#define DISPATCH_ATTRFV( ATTR, COUNT, P ) \ +do { \ + GET_CURRENT_CONTEXT( ctx ); \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + tnl->save.tabfv[ATTR][COUNT-1]( P ); \ +} while (0) + +#define DISPATCH_ATTR1FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 1, V ) +#define DISPATCH_ATTR2FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 2, V ) +#define DISPATCH_ATTR3FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 3, V ) +#define DISPATCH_ATTR4FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 4, V ) + +#define DISPATCH_ATTR1F( ATTR, S ) DISPATCH_ATTRFV( ATTR, 1, &(S) ) + +#define DISPATCH_ATTR2F( ATTR, S,T ) \ +do { \ + GLfloat v[2]; \ + v[0] = S; v[1] = T; \ + DISPATCH_ATTR2FV( ATTR, v ); \ +} while (0) +#define DISPATCH_ATTR3F( ATTR, S,T,R ) \ +do { \ + GLfloat v[3]; \ + v[0] = S; v[1] = T; v[2] = R; \ + DISPATCH_ATTR3FV( ATTR, v ); \ +} while (0) +#define DISPATCH_ATTR4F( ATTR, S,T,R,Q ) \ +do { \ + GLfloat v[4]; \ + v[0] = S; v[1] = T; v[2] = R; v[3] = Q; \ + DISPATCH_ATTR4FV( ATTR, v ); \ +} while (0) + + +static void enum_error( void ) +{ + GET_CURRENT_CONTEXT( ctx ); + _mesa_compile_error( ctx, GL_INVALID_ENUM, __FUNCTION__ ); +} + +static void _save_Vertex2f( GLfloat x, GLfloat y ) +{ + DISPATCH_ATTR2F( _TNL_ATTRIB_POS, x, y ); +} + +static void _save_Vertex2fv( const GLfloat *v ) +{ + DISPATCH_ATTR2FV( _TNL_ATTRIB_POS, v ); +} + +static void _save_Vertex3f( GLfloat x, GLfloat y, GLfloat z ) +{ + DISPATCH_ATTR3F( _TNL_ATTRIB_POS, x, y, z ); +} + +static void _save_Vertex3fv( const GLfloat *v ) +{ + DISPATCH_ATTR3FV( _TNL_ATTRIB_POS, v ); +} + +static void _save_Vertex4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + DISPATCH_ATTR4F( _TNL_ATTRIB_POS, x, y, z, w ); +} + +static void _save_Vertex4fv( const GLfloat *v ) +{ + DISPATCH_ATTR4FV( _TNL_ATTRIB_POS, v ); +} + +static void _save_TexCoord1f( GLfloat x ) +{ + DISPATCH_ATTR1F( _TNL_ATTRIB_TEX0, x ); +} + +static void _save_TexCoord1fv( const GLfloat *v ) +{ + DISPATCH_ATTR1FV( _TNL_ATTRIB_TEX0, v ); +} + +static void _save_TexCoord2f( GLfloat x, GLfloat y ) +{ + DISPATCH_ATTR2F( _TNL_ATTRIB_TEX0, x, y ); +} + +static void _save_TexCoord2fv( const GLfloat *v ) +{ + DISPATCH_ATTR2FV( _TNL_ATTRIB_TEX0, v ); +} + +static void _save_TexCoord3f( GLfloat x, GLfloat y, GLfloat z ) +{ + DISPATCH_ATTR3F( _TNL_ATTRIB_TEX0, x, y, z ); +} + +static void _save_TexCoord3fv( const GLfloat *v ) +{ + DISPATCH_ATTR3FV( _TNL_ATTRIB_TEX0, v ); +} + +static void _save_TexCoord4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + DISPATCH_ATTR4F( _TNL_ATTRIB_TEX0, x, y, z, w ); +} + +static void _save_TexCoord4fv( const GLfloat *v ) +{ + DISPATCH_ATTR4FV( _TNL_ATTRIB_TEX0, v ); +} + +static void _save_Normal3f( GLfloat x, GLfloat y, GLfloat z ) +{ + DISPATCH_ATTR3F( _TNL_ATTRIB_NORMAL, x, y, z ); +} + +static void _save_Normal3fv( const GLfloat *v ) +{ + DISPATCH_ATTR3FV( _TNL_ATTRIB_NORMAL, v ); +} + +static void _save_FogCoordfEXT( GLfloat x ) +{ + DISPATCH_ATTR1F( _TNL_ATTRIB_FOG, x ); +} + +static void _save_FogCoordfvEXT( const GLfloat *v ) +{ + DISPATCH_ATTR1FV( _TNL_ATTRIB_FOG, v ); +} + +static void _save_Color3f( GLfloat x, GLfloat y, GLfloat z ) +{ + DISPATCH_ATTR3F( _TNL_ATTRIB_COLOR0, x, y, z ); +} + +static void _save_Color3fv( const GLfloat *v ) +{ + DISPATCH_ATTR3FV( _TNL_ATTRIB_COLOR0, v ); +} + +static void _save_Color4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + DISPATCH_ATTR4F( _TNL_ATTRIB_COLOR0, x, y, z, w ); +} + +static void _save_Color4fv( const GLfloat *v ) +{ + DISPATCH_ATTR4FV( _TNL_ATTRIB_COLOR0, v ); +} + +static void _save_SecondaryColor3fEXT( GLfloat x, GLfloat y, GLfloat z ) +{ + DISPATCH_ATTR3F( _TNL_ATTRIB_COLOR1, x, y, z ); +} + +static void _save_SecondaryColor3fvEXT( const GLfloat *v ) +{ + DISPATCH_ATTR3FV( _TNL_ATTRIB_COLOR1, v ); +} + +static void _save_MultiTexCoord1f( GLenum target, GLfloat x ) +{ + GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0; + DISPATCH_ATTR1F( attr, x ); +} + +static void _save_MultiTexCoord1fv( GLenum target, const GLfloat *v ) +{ + GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0; + DISPATCH_ATTR1FV( attr, v ); +} + +static void _save_MultiTexCoord2f( GLenum target, GLfloat x, GLfloat y ) +{ + GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0; + DISPATCH_ATTR2F( attr, x, y ); +} + +static void _save_MultiTexCoord2fv( GLenum target, const GLfloat *v ) +{ + GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0; + DISPATCH_ATTR2FV( attr, v ); +} + +static void _save_MultiTexCoord3f( GLenum target, GLfloat x, GLfloat y, + GLfloat z) +{ + GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0; + DISPATCH_ATTR3F( attr, x, y, z ); +} + +static void _save_MultiTexCoord3fv( GLenum target, const GLfloat *v ) +{ + GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0; + DISPATCH_ATTR3FV( attr, v ); +} + +static void _save_MultiTexCoord4f( GLenum target, GLfloat x, GLfloat y, + GLfloat z, GLfloat w ) +{ + GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0; + DISPATCH_ATTR4F( attr, x, y, z, w ); +} + +static void _save_MultiTexCoord4fv( GLenum target, const GLfloat *v ) +{ + GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0; + DISPATCH_ATTR4FV( attr, v ); +} + +static void _save_VertexAttrib1fNV( GLuint index, GLfloat x ) +{ + if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX) + DISPATCH_ATTR1F( index, x ); + else + enum_error(); +} + +static void _save_VertexAttrib1fvNV( GLuint index, const GLfloat *v ) +{ + if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX) + DISPATCH_ATTR1FV( index, v ); + else + enum_error(); +} + +static void _save_VertexAttrib2fNV( GLuint index, GLfloat x, GLfloat y ) +{ + if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX) + DISPATCH_ATTR2F( index, x, y ); + else + enum_error(); +} + +static void _save_VertexAttrib2fvNV( GLuint index, const GLfloat *v ) +{ + if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX) + DISPATCH_ATTR2FV( index, v ); + else + enum_error(); +} + +static void _save_VertexAttrib3fNV( GLuint index, GLfloat x, GLfloat y, + GLfloat z ) +{ + if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX) + DISPATCH_ATTR3F( index, x, y, z ); + else + enum_error(); +} + +static void _save_VertexAttrib3fvNV( GLuint index, const GLfloat *v ) +{ + if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX) + DISPATCH_ATTR3FV( index, v ); + else + enum_error(); +} + +static void _save_VertexAttrib4fNV( GLuint index, GLfloat x, GLfloat y, + GLfloat z, GLfloat w ) +{ + if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX) + DISPATCH_ATTR4F( index, x, y, z, w ); + else + enum_error(); +} + +static void _save_VertexAttrib4fvNV( GLuint index, const GLfloat *v ) +{ + if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX) + DISPATCH_ATTR4FV( index, v ); + else + enum_error(); +} + + +/* Materials: + * + * These are treated as per-vertex attributes, at indices above where + * the NV_vertex_program leaves off. There are a lot of good things + * about treating materials this way. + * + * However: I don't want to double the number of generated functions + * just to cope with this, so I unroll the 'C' varients of CHOOSE and + * ATTRF into this function, and dispense with codegen and + * second-level dispatch. + * + * There is no aliasing of material attributes with other entrypoints. + */ +#define MAT_ATTR( A, N, params ) \ +do { \ + if (tnl->save.attrsz[A] < N) { \ + _save_upgrade_vertex( ctx, A, N ); \ + } \ + \ + { \ + GLfloat *dest = tnl->save.attrptr[A]; \ + if (N>0) dest[0] = params[0]; \ + if (N>1) dest[1] = params[1]; \ + if (N>2) dest[2] = params[2]; \ + if (N>3) dest[3] = params[3]; \ + } \ +} while (0) + + +#define MAT( ATTR, N, face, params ) \ +do { \ + if (face != GL_BACK) \ + MAT_ATTR( ATTR, N, params ); /* front */ \ + if (face != GL_FRONT) \ + MAT_ATTR( ATTR + 1, N, params ); /* back */ \ +} while (0) + + +/* NOTE: Have to remove/deal-with colormaterial crossovers, probably + * later on - in the meantime just store everything. + */ +static void _save_Materialfv( GLenum face, GLenum pname, + const GLfloat *params ) +{ + GET_CURRENT_CONTEXT( ctx ); + TNLcontext *tnl = TNL_CONTEXT(ctx); + + switch (pname) { + case GL_EMISSION: + MAT( _TNL_ATTRIB_MAT_FRONT_EMISSION, 4, face, params ); + break; + case GL_AMBIENT: + MAT( _TNL_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params ); + break; + case GL_DIFFUSE: + MAT( _TNL_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params ); + break; + case GL_SPECULAR: + MAT( _TNL_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params ); + break; + case GL_SHININESS: + MAT( _TNL_ATTRIB_MAT_FRONT_SHININESS, 1, face, params ); + break; + case GL_COLOR_INDEXES: + MAT( _TNL_ATTRIB_MAT_FRONT_INDEXES, 3, face, params ); + break; + case GL_AMBIENT_AND_DIFFUSE: + MAT( _TNL_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params ); + MAT( _TNL_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params ); + break; + default: + _mesa_compile_error( ctx, GL_INVALID_ENUM, __FUNCTION__ ); + return; + } +} + + +#define IDX_ATTR( A, IDX ) \ +do { \ + GET_CURRENT_CONTEXT( ctx ); \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + \ + if (tnl->save.attrsz[A] < 1) { \ + _save_upgrade_vertex( ctx, A, 1 ); \ + } \ + \ + { \ + GLfloat *dest = tnl->save.attrptr[A]; \ + dest[0] = IDX; \ + } \ +} while (0) + + +static void _save_EdgeFlag( GLboolean b ) +{ + IDX_ATTR( _TNL_ATTRIB_EDGEFLAG, (GLfloat)b ); +} + +static void _save_EdgeFlagv( const GLboolean *v ) +{ + IDX_ATTR( _TNL_ATTRIB_EDGEFLAG, (GLfloat)(v[0]) ); +} + +static void _save_Indexf( GLfloat f ) +{ + IDX_ATTR( _TNL_ATTRIB_INDEX, f ); +} + +static void _save_Indexfv( const GLfloat *f ) +{ + IDX_ATTR( _TNL_ATTRIB_INDEX, f[0] ); +} + + + + +/* Cope with EvalCoord/CallList called within a begin/end object: + * -- Flush current buffer + * -- Fallback to opcodes for the rest of the begin/end object. + */ +#define FALLBACK(ctx) \ +do { \ + TNLcontext *tnl = TNL_CONTEXT(ctx); \ + \ + fprintf(stderr, "fallback %s inside begin/end\n", __FUNCTION__); \ + \ + if (tnl->save.initial_counter != tnl->save.counter || \ + tnl->save.prim_count) \ + _save_compile_vertex_list( ctx ); \ + \ + _save_copy_to_current( ctx ); \ + _save_reset_vertex( ctx ); \ + _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt ); \ + ctx->Driver.SaveNeedFlush = 0; \ +} while (0) + +static void _save_EvalCoord1f( GLfloat u ) +{ + GET_CURRENT_CONTEXT(ctx); + FALLBACK(ctx); + ctx->Save->EvalCoord1f( u ); +} + +static void _save_EvalCoord1fv( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + FALLBACK(ctx); + ctx->Save->EvalCoord1fv( v ); +} + +static void _save_EvalCoord2f( GLfloat u, GLfloat v ) +{ + GET_CURRENT_CONTEXT(ctx); + FALLBACK(ctx); + ctx->Save->EvalCoord2f( u, v ); +} + +static void _save_EvalCoord2fv( const GLfloat *v ) +{ + GET_CURRENT_CONTEXT(ctx); + FALLBACK(ctx); + ctx->Save->EvalCoord2fv( v ); +} + +static void _save_EvalPoint1( GLint i ) +{ + GET_CURRENT_CONTEXT(ctx); + FALLBACK(ctx); + ctx->Save->EvalPoint1( i ); +} + +static void _save_EvalPoint2( GLint i, GLint j ) +{ + GET_CURRENT_CONTEXT(ctx); + FALLBACK(ctx); + ctx->Save->EvalPoint2( i, j ); +} + +static void _save_CallList( GLuint l ) +{ + GET_CURRENT_CONTEXT(ctx); + fprintf(stderr, "%s\n", __FUNCTION__); + FALLBACK(ctx); + ctx->Save->CallList( l ); +} + +static void _save_CallLists( GLsizei n, GLenum type, const GLvoid *v ) +{ + GET_CURRENT_CONTEXT(ctx); + fprintf(stderr, "%s\n", __FUNCTION__); + FALLBACK(ctx); + ctx->Save->CallLists( n, type, v ); +} + + + + +/* This begin is hooked into ... Updating of + * ctx->Driver.CurrentSavePrimitive is already taken care of. + */ +static GLboolean _save_NotifyBegin( GLcontext *ctx, GLenum mode ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + + if (1) { + int i = tnl->save.prim_count++; + + assert(i < tnl->save.prim_max); + tnl->save.prim[i].mode = mode | PRIM_BEGIN; + tnl->save.prim[i].start = tnl->save.initial_counter - tnl->save.counter; + tnl->save.prim[i].count = 0; + + _mesa_install_save_vtxfmt( ctx, &tnl->save_vtxfmt ); + ctx->Driver.SaveNeedFlush = 1; + return GL_TRUE; + } + else + return GL_FALSE; +} + + + +static void _save_End( void ) +{ + GET_CURRENT_CONTEXT( ctx ); + TNLcontext *tnl = TNL_CONTEXT(ctx); + int i = tnl->save.prim_count - 1; + + ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END; + tnl->save.prim[i].mode |= PRIM_END; + tnl->save.prim[i].count = ((tnl->save.initial_counter - tnl->save.counter) - + tnl->save.prim[i].start); + + if (i == tnl->save.prim_max - 1) { + _save_compile_vertex_list( ctx ); + assert(tnl->save.copied.nr == 0); + } + + /* Swap out this vertex format while outside begin/end. Any color, + * etc. received between here and the next begin will be compiled + * as opcodes. + */ + _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt ); +} + + +/* These are all errors as this vtxfmt is only installed inside + * begin/end pairs. + */ +static void _save_DrawElements(GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices) +{ + GET_CURRENT_CONTEXT(ctx); + _mesa_compile_error( ctx, GL_INVALID_OPERATION, __FUNCTION__); +} + + +static void _save_DrawRangeElements(GLenum mode, + GLuint start, GLuint end, + GLsizei count, GLenum type, + const GLvoid *indices) +{ + GET_CURRENT_CONTEXT(ctx); + _mesa_compile_error( ctx, GL_INVALID_OPERATION, __FUNCTION__); +} + +static void _save_DrawArrays(GLenum mode, GLint start, GLsizei count) +{ + GET_CURRENT_CONTEXT(ctx); + _mesa_compile_error( ctx, GL_INVALID_OPERATION, __FUNCTION__); +} + +static void _save_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 ) +{ + GET_CURRENT_CONTEXT(ctx); + _mesa_compile_error( ctx, GL_INVALID_OPERATION, __FUNCTION__); +} + +static void _save_EvalMesh1( GLenum mode, GLint i1, GLint i2 ) +{ + GET_CURRENT_CONTEXT(ctx); + _mesa_compile_error( ctx, GL_INVALID_OPERATION, __FUNCTION__); +} + +static void _save_EvalMesh2( GLenum mode, GLint i1, GLint i2, + GLint j1, GLint j2 ) +{ + GET_CURRENT_CONTEXT(ctx); + _mesa_compile_error( ctx, GL_INVALID_OPERATION, __FUNCTION__); +} + +static void _save_Begin( GLenum mode ) +{ + GET_CURRENT_CONTEXT( ctx ); + _mesa_compile_error( ctx, GL_INVALID_OPERATION, "Recursive begin" ); +} + + +/* Unlike the functions above, these are to be hooked into the vtxfmt + * maintained in ctx->ListState, active when the list is known or + * suspected to be outside any begin/end primitive. + */ +static void _save_OBE_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 ) +{ + GET_CURRENT_CONTEXT(ctx); + _save_NotifyBegin( ctx, GL_QUADS | PRIM_WEAK ); + glVertex2f( x1, y1 ); + glVertex2f( x2, y1 ); + glVertex2f( x2, y2 ); + glVertex2f( x1, y2 ); + glEnd(); +} + + +static void _save_OBE_DrawArrays(GLenum mode, GLint start, GLsizei count) +{ + GET_CURRENT_CONTEXT(ctx); + GLint i; + + if (!_mesa_validate_DrawArrays( ctx, mode, start, count )) + return; + + _save_NotifyBegin( ctx, mode | PRIM_WEAK ); + for (i = start ; i < count ; i++) + glArrayElement( i ); + glEnd(); +} + + +static void _save_OBE_DrawElements(GLenum mode, GLsizei count, GLenum type, + const GLvoid *indices) +{ + GET_CURRENT_CONTEXT(ctx); + GLint i; + + if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices )) + return; + + _save_NotifyBegin( ctx, mode | PRIM_WEAK ); + + switch (type) { + case GL_UNSIGNED_BYTE: + for (i = 0 ; i < count ; i++) + glArrayElement( ((GLubyte *)indices)[i] ); + break; + case GL_UNSIGNED_SHORT: + for (i = 0 ; i < count ; i++) + glArrayElement( ((GLushort *)indices)[i] ); + break; + case GL_UNSIGNED_INT: + for (i = 0 ; i < count ; i++) + glArrayElement( ((GLuint *)indices)[i] ); + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glDrawElements(type)" ); + break; + } + + glEnd(); +} + +static void _save_OBE_DrawRangeElements(GLenum mode, + GLuint start, GLuint end, + GLsizei count, GLenum type, + const GLvoid *indices) +{ + GET_CURRENT_CONTEXT(ctx); + if (_mesa_validate_DrawRangeElements( ctx, mode, + start, end, + count, type, indices )) + _save_OBE_DrawElements( mode, count, type, indices ); +} + + + + + +static void _save_vtxfmt_init( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLvertexformat *vfmt = &tnl->save_vtxfmt; + + vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */ + vfmt->Begin = _save_Begin; + vfmt->Color3f = _save_Color3f; + vfmt->Color3fv = _save_Color3fv; + vfmt->Color4f = _save_Color4f; + vfmt->Color4fv = _save_Color4fv; + vfmt->EdgeFlag = _save_EdgeFlag; + vfmt->EdgeFlagv = _save_EdgeFlagv; + vfmt->End = _save_End; + vfmt->FogCoordfEXT = _save_FogCoordfEXT; + vfmt->FogCoordfvEXT = _save_FogCoordfvEXT; + vfmt->Indexf = _save_Indexf; + vfmt->Indexfv = _save_Indexfv; + vfmt->Materialfv = _save_Materialfv; + vfmt->MultiTexCoord1fARB = _save_MultiTexCoord1f; + vfmt->MultiTexCoord1fvARB = _save_MultiTexCoord1fv; + vfmt->MultiTexCoord2fARB = _save_MultiTexCoord2f; + vfmt->MultiTexCoord2fvARB = _save_MultiTexCoord2fv; + vfmt->MultiTexCoord3fARB = _save_MultiTexCoord3f; + vfmt->MultiTexCoord3fvARB = _save_MultiTexCoord3fv; + vfmt->MultiTexCoord4fARB = _save_MultiTexCoord4f; + vfmt->MultiTexCoord4fvARB = _save_MultiTexCoord4fv; + vfmt->Normal3f = _save_Normal3f; + vfmt->Normal3fv = _save_Normal3fv; + vfmt->SecondaryColor3fEXT = _save_SecondaryColor3fEXT; + vfmt->SecondaryColor3fvEXT = _save_SecondaryColor3fvEXT; + vfmt->TexCoord1f = _save_TexCoord1f; + vfmt->TexCoord1fv = _save_TexCoord1fv; + vfmt->TexCoord2f = _save_TexCoord2f; + vfmt->TexCoord2fv = _save_TexCoord2fv; + vfmt->TexCoord3f = _save_TexCoord3f; + vfmt->TexCoord3fv = _save_TexCoord3fv; + vfmt->TexCoord4f = _save_TexCoord4f; + vfmt->TexCoord4fv = _save_TexCoord4fv; + vfmt->Vertex2f = _save_Vertex2f; + vfmt->Vertex2fv = _save_Vertex2fv; + vfmt->Vertex3f = _save_Vertex3f; + vfmt->Vertex3fv = _save_Vertex3fv; + vfmt->Vertex4f = _save_Vertex4f; + vfmt->Vertex4fv = _save_Vertex4fv; + vfmt->VertexAttrib1fNV = _save_VertexAttrib1fNV; + vfmt->VertexAttrib1fvNV = _save_VertexAttrib1fvNV; + vfmt->VertexAttrib2fNV = _save_VertexAttrib2fNV; + vfmt->VertexAttrib2fvNV = _save_VertexAttrib2fvNV; + vfmt->VertexAttrib3fNV = _save_VertexAttrib3fNV; + vfmt->VertexAttrib3fvNV = _save_VertexAttrib3fvNV; + vfmt->VertexAttrib4fNV = _save_VertexAttrib4fNV; + vfmt->VertexAttrib4fvNV = _save_VertexAttrib4fvNV; + + /* This will all require us to fallback to saving the list as opcodes: + */ + vfmt->CallList = _save_CallList; /* inside begin/end */ + vfmt->CallLists = _save_CallLists; /* inside begin/end */ + vfmt->EvalCoord1f = _save_EvalCoord1f; + vfmt->EvalCoord1fv = _save_EvalCoord1fv; + vfmt->EvalCoord2f = _save_EvalCoord2f; + vfmt->EvalCoord2fv = _save_EvalCoord2fv; + vfmt->EvalPoint1 = _save_EvalPoint1; + vfmt->EvalPoint2 = _save_EvalPoint2; + + /* These are all errors as we at least know we are in some sort of + * begin/end pair: + */ + vfmt->EvalMesh1 = _save_EvalMesh1; + vfmt->EvalMesh2 = _save_EvalMesh2; + vfmt->Begin = _save_Begin; + vfmt->Rectf = _save_Rectf; + vfmt->DrawArrays = _save_DrawArrays; + vfmt->DrawElements = _save_DrawElements; + vfmt->DrawRangeElements = _save_DrawRangeElements; + +} + + +void _tnl_SaveFlushVertices( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + + /* Noop when we are actually active: + */ + if (ctx->Driver.CurrentSavePrimitive == PRIM_INSIDE_UNKNOWN_PRIM || + ctx->Driver.CurrentSavePrimitive <= GL_POLYGON) + return; + + if (tnl->save.initial_counter != tnl->save.counter || + tnl->save.prim_count) + _save_compile_vertex_list( ctx ); + + _save_copy_to_current( ctx ); + _save_reset_vertex( ctx ); + ctx->Driver.SaveNeedFlush = 0; +} + +void _tnl_NewList( GLcontext *ctx, GLuint list, GLenum mode ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + + if (!tnl->save.prim_store) + tnl->save.prim_store = alloc_prim_store( ctx ); + + if (!tnl->save.vertex_store) { + tnl->save.vertex_store = alloc_vertex_store( ctx ); + tnl->save.vbptr = tnl->save.vertex_store->buffer; + } + + _save_reset_vertex( ctx ); + ctx->Driver.SaveNeedFlush = 0; +} + +void _tnl_EndList( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + assert(tnl->save.vertex_size == 0); +} + +void _tnl_BeginCallList( GLcontext *ctx, GLuint list ) +{ +} + +void _tnl_EndCallList( GLcontext *ctx ) +{ +} + + +static void _tnl_destroy_vertex_list( GLcontext *ctx, void *data ) +{ + struct tnl_vertex_list *node = (struct tnl_vertex_list *)data; + + if ( --node->vertex_store->refcount == 0 ) + FREE( node->vertex_store ); + + if ( --node->prim_store->refcount == 0 ) + FREE( node->prim_store ); + + if ( node->normal_lengths ) + FREE( node->normal_lengths ); +} + + +static void _tnl_print_vertex_list( GLcontext *ctx, void *data ) +{ + struct tnl_vertex_list *node = (struct tnl_vertex_list *)data; + GLuint i; + + _mesa_debug(0, "TNL-VERTEX-LIST, %u vertices %d primitives, %d vertsize\n", + node->count, + node->prim_count, + node->vertex_size); + + for (i = 0 ; i < node->prim_count ; i++) { + struct tnl_prim *prim = &node->prim[i]; + _mesa_debug(0, " prim %d: %s %d..%d %s %s\n", + i, + _mesa_lookup_enum_by_nr(prim->mode & PRIM_MODE_MASK), + prim->start, + prim->start + prim->count, + (prim->mode & PRIM_BEGIN) ? "BEGIN" : "(wrap)", + (prim->mode & PRIM_END) ? "END" : "(wrap)"); + } +} + + +static void _save_current_init( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLint i; + + for (i = 0; i < _TNL_ATTRIB_MAT_FRONT_AMBIENT; i++) { + tnl->save.currentsz[i] = &ctx->ListState.ActiveAttribSize[i]; + tnl->save.current[i] = ctx->ListState.CurrentAttrib[i]; + } + + for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT; i < _TNL_ATTRIB_INDEX; i++) { + tnl->save.currentsz[i] = &ctx->ListState.ActiveMaterialSize[i]; + tnl->save.current[i] = ctx->ListState.CurrentMaterial[i]; + } + + tnl->save.currentsz[_TNL_ATTRIB_INDEX] = &ctx->ListState.ActiveIndex; + tnl->save.current[_TNL_ATTRIB_INDEX] = &ctx->ListState.CurrentIndex; + + /* Current edgeflag is handled individually */ +} + +/** + * Initialize the display list compiler + */ +void _tnl_save_init( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct tnl_vertex_arrays *tmp = &tnl->save_inputs; + GLuint i; + + + for (i = 0; i < _TNL_ATTRIB_MAX; i++) + _mesa_vector4f_init( &tmp->Attribs[i], 0, 0); + + tnl->save.opcode_vertex_list = + _mesa_alloc_opcode( ctx, + sizeof(struct tnl_vertex_list), + _tnl_playback_vertex_list, + _tnl_destroy_vertex_list, + _tnl_print_vertex_list ); + + ctx->Driver.NotifySaveBegin = _save_NotifyBegin; + + _save_vtxfmt_init( ctx ); + _save_current_init( ctx ); + + /* Hook our array functions into the outside-begin-end vtxfmt in + * ctx->ListState. + */ + ctx->ListState.ListVtxfmt.Rectf = _save_OBE_Rectf; + ctx->ListState.ListVtxfmt.DrawArrays = _save_OBE_DrawArrays; + ctx->ListState.ListVtxfmt.DrawElements = _save_OBE_DrawElements; + ctx->ListState.ListVtxfmt.DrawRangeElements = _save_OBE_DrawRangeElements; + _mesa_install_save_vtxfmt( ctx, &ctx->ListState.ListVtxfmt ); +} + + +/** + * Deallocate the immediate-mode buffer for the given context, if + * its reference count goes to zero. + */ +void _tnl_save_destroy( GLcontext *ctx ) +{ +} diff --git a/src/mesa/tnl/t_save_api.h b/src/mesa/tnl/t_save_api.h new file mode 100644 index 00000000000..a6a8cd011bd --- /dev/null +++ b/src/mesa/tnl/t_save_api.h @@ -0,0 +1,58 @@ +/* $XFree86$ */ +/************************************************************************** + +Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas. + +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 +on the rights to use, copy, modify, merge, publish, distribute, sub +license, 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 (including the next +paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL +TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS 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 + * + */ + +#ifndef __T_SAVE_API_H__ +#define __T_SAVE_API_H__ + +#include "t_context.h" + +extern GLboolean _tnl_weak_begin( GLcontext *ctx, GLenum mode ); + +extern void _tnl_EndList( GLcontext *ctx ); +extern void _tnl_NewList( GLcontext *ctx, GLuint list, GLenum mode ); + +extern void _tnl_EndCallList( GLcontext *ctx ); +extern void _tnl_BeginCallList( GLcontext *ctx, GLuint list ); + +extern void _tnl_SaveFlushVertices( GLcontext *ctx ); + +extern void _tnl_save_init( GLcontext *ctx ); +extern void _tnl_save_destroy( GLcontext *ctx ); + +extern void _tnl_loopback_vertex_list( GLcontext *ctx, + struct tnl_vertex_list *list ); + +extern void _tnl_playback_vertex_list( GLcontext *ctx, void *data ); + +#endif diff --git a/src/mesa/tnl/t_save_loopback.c b/src/mesa/tnl/t_save_loopback.c new file mode 100644 index 00000000000..b496a784c35 --- /dev/null +++ b/src/mesa/tnl/t_save_loopback.c @@ -0,0 +1,301 @@ + +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * Copyright (C) 1999-2003 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. + */ + +/* Author: + * Keith Whitwell + */ + +#include "context.h" +#include "enums.h" +#include "glapi.h" +#include "imports.h" +#include "macros.h" +#include "mtypes.h" +#include "t_context.h" +#include "t_save_api.h" + +/* If someone compiles a display list like: + * glBegin(Triangles) + * glVertex() + * ... lots of vertices ... + * glEnd() + * + * or: + * glDrawArrays(...) + * + * and then tries to execute it like this: + * + * glBegin(Lines) + * glCallList() + * glEnd() + * + * it will wind up in here, as the vertex copying used when wrapping + * buffers in list compilation (Triangles) won't be right for how the + * list is being executed (as Lines). + * + * This could be avoided by not compiling as vertex_lists until after + * the first glEnd() has been seen. However, that would miss an + * important category of display lists, for the sake of a degenerate + * usage. + * + * Further, replaying degenerately-called lists in this fashion is + * probably still faster than the replay using opcodes. + */ + +typedef void (*attr_func)( GLcontext *ctx, GLint target, const GLfloat * ); + + +/* Wrapper functions in case glVertexAttrib*fvNV doesn't exist */ +static void VertexAttrib1fvNV(GLcontext *ctx, GLint target, const GLfloat *v) +{ + ctx->Exec->VertexAttrib1fvNV(target, v); +} + +static void VertexAttrib2fvNV(GLcontext *ctx, GLint target, const GLfloat *v) +{ + ctx->Exec->VertexAttrib2fvNV(target, v); +} + +static void VertexAttrib3fvNV(GLcontext *ctx, GLint target, const GLfloat *v) +{ + ctx->Exec->VertexAttrib3fvNV(target, v); +} + +static void VertexAttrib4fvNV(GLcontext *ctx, GLint target, const GLfloat *v) +{ + ctx->Exec->VertexAttrib4fvNV(target, v); +} + +static attr_func vert_attrfunc[4] = { + VertexAttrib1fvNV, + VertexAttrib2fvNV, + VertexAttrib3fvNV, + VertexAttrib4fvNV +}; + + +static void mat_attr1fv( GLcontext *ctx, GLint target, const GLfloat *v ) +{ + switch (target) { + case _TNL_ATTRIB_MAT_FRONT_SHININESS: + ctx->Exec->Materialfv( GL_FRONT, GL_SHININESS, v ); + break; + case _TNL_ATTRIB_MAT_BACK_SHININESS: + ctx->Exec->Materialfv( GL_BACK, GL_SHININESS, v ); + break; + } +} + + +static void mat_attr3fv( GLcontext *ctx, GLint target, const GLfloat *v ) +{ + switch (target) { + case _TNL_ATTRIB_MAT_FRONT_INDEXES: + ctx->Exec->Materialfv( GL_FRONT, GL_COLOR_INDEXES, v ); + break; + case _TNL_ATTRIB_MAT_BACK_INDEXES: + ctx->Exec->Materialfv( GL_BACK, GL_COLOR_INDEXES, v ); + break; + } +} + + +static void mat_attr4fv( GLcontext *ctx, GLint target, const GLfloat *v ) +{ + switch (target) { + case _TNL_ATTRIB_MAT_FRONT_EMISSION: + ctx->Exec->Materialfv( GL_FRONT, GL_EMISSION, v ); + break; + case _TNL_ATTRIB_MAT_BACK_EMISSION: + ctx->Exec->Materialfv( GL_BACK, GL_EMISSION, v ); + break; + case _TNL_ATTRIB_MAT_FRONT_AMBIENT: + ctx->Exec->Materialfv( GL_FRONT, GL_AMBIENT, v ); + break; + case _TNL_ATTRIB_MAT_BACK_AMBIENT: + ctx->Exec->Materialfv( GL_BACK, GL_AMBIENT, v ); + break; + case _TNL_ATTRIB_MAT_FRONT_DIFFUSE: + ctx->Exec->Materialfv( GL_FRONT, GL_DIFFUSE, v ); + break; + case _TNL_ATTRIB_MAT_BACK_DIFFUSE: + ctx->Exec->Materialfv( GL_BACK, GL_DIFFUSE, v ); + break; + case _TNL_ATTRIB_MAT_FRONT_SPECULAR: + ctx->Exec->Materialfv( GL_FRONT, GL_SPECULAR, v ); + break; + case _TNL_ATTRIB_MAT_BACK_SPECULAR: + ctx->Exec->Materialfv( GL_BACK, GL_SPECULAR, v ); + break; + } +} + + +static attr_func mat_attrfunc[4] = { + mat_attr1fv, + 0, + mat_attr3fv, + mat_attr4fv +}; + + +static void index_attr1fv(GLcontext *ctx, GLint target, const GLfloat *v) +{ + ctx->Exec->Indexf(v[0]); +} + +static void edgeflag_attr1fv(GLcontext *ctx, GLint target, const GLfloat *v) +{ + ctx->Exec->EdgeFlag((v[0] == 1.0)); +} + +struct loopback_attr { + GLint target; + GLint sz; + attr_func func; +}; + +/* Don't emit ends and begins on wrapped primitives. Don't replay + * wrapped vertices. If we get here, it's probably because the the + * precalculated wrapping is wrong. + */ +static void loopback_prim( GLcontext *ctx, + struct tnl_vertex_list *list, GLuint i, + struct loopback_attr *la, GLuint nr ) +{ + struct tnl_prim *prim = &list->prim[i]; + GLint begin = prim->start; + GLint end = begin + prim->count; + GLfloat *data; + GLint j, k; + + if (prim->mode & PRIM_BEGIN) { + glBegin( prim->mode & PRIM_MODE_MASK ); + } else { + assert(i == 0); + assert(begin == 0); + begin += list->wrap_count; + } + + data = list->buffer + begin * list->vertex_size; + + for (j = begin ; j < end ; j++) { + GLfloat *tmp = data + la[0].sz; + + for (k = 1 ; k < nr ; k++) { + la[k].func( ctx, la[k].target, tmp ); + tmp += la[k].sz; + } + + /* Fire the vertex + */ + la[0].func( ctx, VERT_ATTRIB_POS, data ); + data = tmp; + } + + if (prim->mode & PRIM_END) { + glEnd(); + } + else { + assert (i == list->prim_count-1); + } +} + +/* Primitives generated by DrawArrays/DrawElements/Rectf may be + * caught here. If there is no primitive in progress, execute them + * normally, otherwise need to track and discard the generated + * primitives. + */ +static void loopback_weak_prim( GLcontext *ctx, + struct tnl_vertex_list *list, GLuint i, + struct loopback_attr *la, GLuint nr ) +{ + if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) + loopback_prim( ctx, list, i, la, nr ); + else { + struct tnl_prim *prim = &list->prim[i]; + + /* Use the prim_weak flag to ensure that if this primitive + * wraps, we don't mistake future vertex_lists for part of the + * surrounding primitive. + * + * While this flag is set, we are simply disposing of data + * generated by an operation now known to be a noop. + */ + if (prim->mode & PRIM_BEGIN) + ctx->Driver.CurrentExecPrimitive |= PRIM_WEAK; + if (prim->mode & PRIM_END) + ctx->Driver.CurrentExecPrimitive &= ~PRIM_WEAK; + } +} + + + +void _tnl_loopback_vertex_list( GLcontext *ctx, struct tnl_vertex_list *list ) +{ + struct loopback_attr la[_TNL_ATTRIB_MAX]; + GLuint i, nr = 0; + + for (i = 0 ; i <= _TNL_ATTRIB_TEX7 ; i++) { + if (list->attrsz[i]) { + la[nr].target = i; + la[nr].sz = list->attrsz[i]; + la[nr].func = vert_attrfunc[list->attrsz[i]-1]; + nr++; + } + } + + for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT ; + i <= _TNL_ATTRIB_MAT_BACK_INDEXES ; + i++) { + if (list->attrsz[i]) { + la[nr].target = i; + la[nr].sz = list->attrsz[i]; + la[nr].func = mat_attrfunc[list->attrsz[i]-1]; + nr++; + } + } + + if (list->attrsz[_TNL_ATTRIB_EDGEFLAG]) { + la[nr].target = _TNL_ATTRIB_EDGEFLAG; + la[nr].sz = list->attrsz[_TNL_ATTRIB_EDGEFLAG]; + la[nr].func = edgeflag_attr1fv; + nr++; + } + + if (list->attrsz[_TNL_ATTRIB_INDEX]) { + la[nr].target = _TNL_ATTRIB_INDEX; + la[nr].sz = list->attrsz[_TNL_ATTRIB_INDEX]; + la[nr].func = index_attr1fv; + nr++; + } + + for (i = 0 ; i < list->prim_count ; i++) { + if (list->prim[i].mode & PRIM_WEAK) + loopback_weak_prim( ctx, list, i, la, nr ); + else + loopback_prim( ctx, list, i, la, nr ); + } +} diff --git a/src/mesa/tnl/t_save_playback.c b/src/mesa/tnl/t_save_playback.c new file mode 100644 index 00000000000..52011996b01 --- /dev/null +++ b/src/mesa/tnl/t_save_playback.c @@ -0,0 +1,218 @@ + +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * Copyright (C) 1999-2003 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. + */ + +/* Author: + * Keith Whitwell + */ + +#include "context.h" +#include "imports.h" +#include "mtypes.h" +#include "macros.h" +#include "light.h" +#include "state.h" +#include "t_pipeline.h" +#include "t_save_api.h" +#include "t_vtx_api.h" + +static GLint get_size( const GLfloat *f ) +{ + if (f[3] != 1.0) return 4; + if (f[2] != 0.0) return 3; + return 2; +} + + +/* Some nasty stuff still hanging on here. + * + * TODO - remove VB->ColorPtr, etc and just use the AttrPtr's. + */ +static void _tnl_bind_vertex_list( GLcontext *ctx, + struct tnl_vertex_list *node ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + struct tnl_vertex_arrays *tmp = &tnl->save_inputs; + GLfloat *data = node->buffer; + GLuint attr, i; + + /* Setup constant data in the VB. + */ + VB->Count = node->count; + VB->Primitive = node->prim; + VB->PrimitiveCount = node->prim_count; + VB->Elts = NULL; + VB->NormalLengthPtr = node->normal_lengths; + + for (attr = 0; attr <= _TNL_ATTRIB_INDEX; attr++) { + if (node->attrsz[attr]) { + tmp->Attribs[attr].count = node->count; + tmp->Attribs[attr].data = (GLfloat (*)[4]) data; + tmp->Attribs[attr].start = data; + tmp->Attribs[attr].size = node->attrsz[attr]; + tmp->Attribs[attr].stride = node->vertex_size * sizeof(GLfloat); + VB->AttribPtr[attr] = &tmp->Attribs[attr]; + data += node->attrsz[attr]; + } + else { + tmp->Attribs[attr].count = node->count; + tmp->Attribs[attr].data = (GLfloat (*)[4]) tnl->vtx.current[attr]; + tmp->Attribs[attr].start = tnl->vtx.current[attr]; + tmp->Attribs[attr].size = get_size( tnl->vtx.current[attr] ); + tmp->Attribs[attr].stride = 0; + VB->AttribPtr[attr] = &tmp->Attribs[attr]; + } + } + + + /* Copy edgeflag to a contiguous array + */ + if (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL) { + if (node->attrsz[_TNL_ATTRIB_EDGEFLAG]) { + VB->EdgeFlag = _tnl_translate_edgeflag( ctx, data, + node->count, + node->vertex_size ); + data++; + } + else + VB->EdgeFlag = _tnl_import_current_edgeflag( ctx, node->count ); + } + + /* Legacy pointers -- remove one day. + */ + VB->ObjPtr = VB->AttribPtr[_TNL_ATTRIB_POS]; + VB->NormalPtr = VB->AttribPtr[_TNL_ATTRIB_NORMAL]; + VB->ColorPtr[0] = VB->AttribPtr[_TNL_ATTRIB_COLOR0]; + VB->ColorPtr[1] = 0; + VB->IndexPtr[0] = VB->AttribPtr[_TNL_ATTRIB_INDEX]; + VB->IndexPtr[1] = 0; + VB->SecondaryColorPtr[0] = VB->AttribPtr[_TNL_ATTRIB_COLOR1]; + VB->SecondaryColorPtr[1] = 0; + + for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { + VB->TexCoordPtr[i] = VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]; + } +} + +static void _playback_copy_to_current( GLcontext *ctx, + struct tnl_vertex_list *node ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLfloat *data; + GLuint i; + + if (node->count) + data = node->buffer + (node->count-1) * node->vertex_size; + else + data = node->buffer; + + for (i = _TNL_ATTRIB_POS+1 ; i <= _TNL_ATTRIB_INDEX ; i++) { + if (node->attrsz[i]) { + ASSIGN_4V(tnl->vtx.current[i], 0, 0, 0, 1); + COPY_SZ_4V(tnl->vtx.current[i], node->attrsz[i], data); + data += node->attrsz[i]; + } + } + + /* Edgeflag requires special treatment: + */ + if (node->attrsz[_TNL_ATTRIB_EDGEFLAG]) { + ctx->Current.EdgeFlag = (data[0] == 1.0); + } + + /* Colormaterial -- this kindof sucks. + */ + if (ctx->Light.ColorMaterialEnabled) { + _mesa_update_color_material(ctx, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]); + } + + /* CurrentExecPrimitive + */ + if (node->prim_count) { + GLenum mode = node->prim[node->prim_count - 1].mode; + if (mode & PRIM_END) + ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; + else + ctx->Driver.CurrentExecPrimitive = (mode & PRIM_MODE_MASK); + } +} + + +/** + * Execute the buffer and save copied verts. + */ +void _tnl_playback_vertex_list( GLcontext *ctx, void *data ) +{ + struct tnl_vertex_list *node = (struct tnl_vertex_list *)data; + TNLcontext *tnl = TNL_CONTEXT(ctx); + + FLUSH_CURRENT(ctx, 0); + + if (node->prim_count) { + + if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END && + (node->prim[0].mode & PRIM_BEGIN)) { + + /* Degenerate case: list is called inside begin/end pair and + * includes operations such as glBegin or glDrawArrays. + */ + _mesa_error( ctx, GL_INVALID_OPERATION, "displaylist recursive begin"); + _tnl_loopback_vertex_list( ctx, data ); + return; + } + else if (tnl->LoopbackDListCassettes || + node->dangling_attr_ref) { + /* Degenerate case: list references current data and would + * require fixup. Take the easier option & loop it back. + */ + _mesa_debug( 0, "%s: loopback dangling attr ref\n", __FUNCTION__); + _tnl_loopback_vertex_list( ctx, data ); + return; + } + + if (ctx->NewState) + _mesa_update_state( ctx ); + + if (tnl->pipeline.build_state_changes) + _tnl_validate_pipeline( ctx ); + + _tnl_bind_vertex_list( ctx, node ); + + /* Invalidate all stored data before and after run: + */ + tnl->pipeline.run_input_changes |= tnl->pipeline.inputs; + tnl->Driver.RunPipeline( ctx ); + tnl->pipeline.run_input_changes |= tnl->pipeline.inputs; + } + + /* Copy to current? + */ + _playback_copy_to_current( ctx, node ); +} + + + + + diff --git a/src/mesa/tnl/t_vb_cliptmp.h b/src/mesa/tnl/t_vb_cliptmp.h index ab180facf74..47a3142e441 100644 --- a/src/mesa/tnl/t_vb_cliptmp.h +++ b/src/mesa/tnl/t_vb_cliptmp.h @@ -126,7 +126,7 @@ TAG(clip_line)( GLcontext *ctx, GLuint i, GLuint j, GLubyte mask ) GLfloat (*coord)[4] = VB->ClipPtr->data; GLuint ii = i, jj = j, p; - VB->LastClipped = VB->FirstClipped; + VB->LastClipped = VB->Count; if (mask & 0x3f) { LINE_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 ); @@ -174,7 +174,7 @@ TAG(clip_tri)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLubyte mask ) ASSIGN_3V(inlist, v2, v0, v1 ); /* pv rotated to slot zero */ - VB->LastClipped = VB->FirstClipped; + VB->LastClipped = VB->Count; if (mask & 0x3f) { POLY_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 ); @@ -199,7 +199,7 @@ TAG(clip_tri)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLubyte mask ) if (ctx->_TriangleCaps & DD_FLATSHADE) { if (pv != inlist[0]) { - ASSERT( inlist[0] >= VB->FirstClipped ); + ASSERT( inlist[0] >= VB->Count ); tnl->Driver.Render.CopyPV( ctx, inlist[0], pv ); } } @@ -227,7 +227,7 @@ TAG(clip_quad)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3, ASSIGN_4V(inlist, v3, v0, v1, v2 ); /* pv rotated to slot zero */ - VB->LastClipped = VB->FirstClipped; + VB->LastClipped = VB->Count; if (mask & 0x3f) { POLY_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 ); @@ -252,7 +252,7 @@ TAG(clip_quad)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3, if (ctx->_TriangleCaps & DD_FLATSHADE) { if (pv != inlist[0]) { - ASSERT( inlist[0] >= VB->FirstClipped ); + ASSERT( inlist[0] >= VB->Count ); tnl->Driver.Render.CopyPV( ctx, inlist[0], pv ); } } diff --git a/src/mesa/tnl/t_vb_fog.c b/src/mesa/tnl/t_vb_fog.c index 8968dfb4dfb..6d688ca0412 100644 --- a/src/mesa/tnl/t_vb_fog.c +++ b/src/mesa/tnl/t_vb_fog.c @@ -127,7 +127,7 @@ static void make_win_fog_coords( GLcontext *ctx, GLvector4f *out, static GLboolean run_fog_stage( GLcontext *ctx, - struct gl_pipeline_stage *stage ) + struct tnl_pipeline_stage *stage ) { struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; struct fog_stage_data *store = FOG_STAGE_DATA(stage); @@ -189,21 +189,21 @@ static GLboolean run_fog_stage( GLcontext *ctx, } -static void check_fog_stage( GLcontext *ctx, struct gl_pipeline_stage *stage ) +static void check_fog_stage( GLcontext *ctx, struct tnl_pipeline_stage *stage ) { stage->active = ctx->Fog.Enabled && !ctx->VertexProgram.Enabled; if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT) - stage->inputs = VERT_BIT_EYE; + stage->inputs = _TNL_BIT_POS; else - stage->inputs = VERT_BIT_FOG; + stage->inputs = _TNL_BIT_FOG; } /* Called the first time stage->run() is invoked. */ static GLboolean alloc_fog_data( GLcontext *ctx, - struct gl_pipeline_stage *stage ) + struct tnl_pipeline_stage *stage ) { TNLcontext *tnl = TNL_CONTEXT(ctx); struct fog_stage_data *store; @@ -225,7 +225,7 @@ static GLboolean alloc_fog_data( GLcontext *ctx, } -static void free_fog_data( struct gl_pipeline_stage *stage ) +static void free_fog_data( struct tnl_pipeline_stage *stage ) { struct fog_stage_data *store = FOG_STAGE_DATA(stage); if (store) { @@ -236,14 +236,14 @@ static void free_fog_data( struct gl_pipeline_stage *stage ) } -const struct gl_pipeline_stage _tnl_fog_coordinate_stage = +const struct tnl_pipeline_stage _tnl_fog_coordinate_stage = { "build fog coordinates", /* name */ _NEW_FOG, /* check_state */ _NEW_FOG, /* run_state */ GL_FALSE, /* active? */ 0, /* inputs */ - VERT_BIT_FOG, /* outputs */ + _TNL_BIT_FOG, /* outputs */ 0, /* changed_inputs */ NULL, /* private_data */ free_fog_data, /* dtr */ diff --git a/src/mesa/tnl/t_vb_light.c b/src/mesa/tnl/t_vb_light.c index 3252df9b30f..d7872675ca8 100644 --- a/src/mesa/tnl/t_vb_light.c +++ b/src/mesa/tnl/t_vb_light.c @@ -38,68 +38,93 @@ #include "t_context.h" #include "t_pipeline.h" -#define LIGHT_FLAGS 0x1 /* must be first */ -#define LIGHT_TWOSIDE 0x2 -#define LIGHT_COLORMATERIAL 0x4 -#define MAX_LIGHT_FUNC 0x8 +#define LIGHT_TWOSIDE 0x1 +#define LIGHT_MATERIAL 0x2 +#define MAX_LIGHT_FUNC 0x4 typedef void (*light_func)( GLcontext *ctx, struct vertex_buffer *VB, - struct gl_pipeline_stage *stage, + struct tnl_pipeline_stage *stage, GLvector4f *input ); +struct material_cursor { + const GLfloat *ptr; + GLuint stride; + GLfloat *current; +}; + struct light_stage_data { - struct gl_client_array FloatColor; - struct gl_client_array LitColor[2]; - struct gl_client_array LitSecondary[2]; - GLvector1ui LitIndex[2]; + GLvector4f Input; + GLvector4f LitColor[2]; + GLvector4f LitSecondary[2]; + GLvector4f LitIndex[2]; light_func *light_func_tab; + + struct material_cursor mat[MAT_ATTRIB_MAX]; + GLuint mat_count; + GLuint mat_bitmask; }; #define LIGHT_STAGE_DATA(stage) ((struct light_stage_data *)(stage->privatePtr)) -static void import_color_material( GLcontext *ctx, - struct gl_pipeline_stage *stage ) + +/* In the case of colormaterial, the effected material attributes + * should already have been bound to point to the incoming color data, + * prior to running the pipeline. + */ +static void update_materials( GLcontext *ctx, + struct light_stage_data *store ) { - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; - struct gl_client_array *to = &LIGHT_STAGE_DATA(stage)->FloatColor; - struct gl_client_array *from = VB->ColorPtr[0]; - GLuint count = VB->Count; - - if (!to->Ptr) { - to->Ptr = (GLubyte *) ALIGN_MALLOC( VB->Size * 4 * sizeof(GLfloat), 32 ); - to->Type = GL_FLOAT; + GLuint i; + + for (i = 0 ; i < store->mat_count ; i++) { + COPY_4V(store->mat[i].current, store->mat[i].ptr); + STRIDE_F(store->mat[i].ptr, store->mat[i].stride); } + + _mesa_update_material( ctx, store->mat_bitmask ); + _mesa_validate_all_lighting_tables( ctx ); +} + +static GLuint prepare_materials( GLcontext *ctx, + struct vertex_buffer *VB, + struct light_stage_data *store ) +{ + GLuint i; + + store->mat_count = 0; + store->mat_bitmask = 0; - /* No need to transform the same value 3000 times. + /* If ColorMaterial enabled, overwrite affected AttrPtr's with + * the color pointer. This could be done earlier. */ - if (!from->StrideB) { - to->StrideB = 0; - count = 1; + if (ctx->Light.ColorMaterialEnabled) { + GLuint bitmask = ctx->Light.ColorMaterialBitmask; + for (i = 0 ; i < MAT_ATTRIB_MAX ; i++) + if (bitmask & (1<AttribPtr[_TNL_ATTRIB_MAT_FRONT_AMBIENT + i] = VB->ColorPtr[0]; + } + + for (i = _TNL_ATTRIB_MAT_FRONT_AMBIENT ; i < _TNL_ATTRIB_INDEX ; i++) { + if (VB->AttribPtr[i]->stride) { + GLuint j = store->mat_count++; + GLuint attr = i - _TNL_ATTRIB_MAT_FRONT_AMBIENT; + store->mat[j].ptr = VB->AttribPtr[i]->start; + store->mat[j].stride = VB->AttribPtr[i]->stride; + store->mat[j].current = ctx->Light.Material.Attrib[attr]; + store->mat_bitmask |= (1<StrideB = 4 * sizeof(GLfloat); - _math_trans_4fc( (GLfloat (*)[4]) to->Ptr, - from->Ptr, - from->StrideB, - from->Type, - from->Size, - 0, - count); - - VB->ColorPtr[0] = to; -} + /* FIXME: Is this already done? + */ + _mesa_update_material( ctx, ~0 ); + _mesa_validate_all_lighting_tables( ctx ); -static void update_materials( GLcontext *ctx, - const struct gl_material *src, - GLuint bitmask ) -{ - _mesa_copy_materials( &ctx->Light.Material, src, bitmask ); - _mesa_update_material( ctx, bitmask ); + return store->mat_count; } /* Tables for all the shading functions. @@ -114,32 +139,16 @@ static light_func _tnl_light_ci_tab[MAX_LIGHT_FUNC]; #define IDX (0) #include "t_vb_lighttmp.h" -#define TAG(x) x##_tw +#define TAG(x) x##_twoside #define IDX (LIGHT_TWOSIDE) #include "t_vb_lighttmp.h" -#define TAG(x) x##_fl -#define IDX (LIGHT_FLAGS) -#include "t_vb_lighttmp.h" - -#define TAG(x) x##_tw_fl -#define IDX (LIGHT_FLAGS|LIGHT_TWOSIDE) +#define TAG(x) x##_material +#define IDX (LIGHT_MATERIAL) #include "t_vb_lighttmp.h" -#define TAG(x) x##_cm -#define IDX (LIGHT_COLORMATERIAL) -#include "t_vb_lighttmp.h" - -#define TAG(x) x##_tw_cm -#define IDX (LIGHT_TWOSIDE|LIGHT_COLORMATERIAL) -#include "t_vb_lighttmp.h" - -#define TAG(x) x##_fl_cm -#define IDX (LIGHT_FLAGS|LIGHT_COLORMATERIAL) -#include "t_vb_lighttmp.h" - -#define TAG(x) x##_tw_fl_cm -#define IDX (LIGHT_FLAGS|LIGHT_TWOSIDE|LIGHT_COLORMATERIAL) +#define TAG(x) x##_twoside_material +#define IDX (LIGHT_TWOSIDE|LIGHT_MATERIAL) #include "t_vb_lighttmp.h" @@ -149,55 +158,64 @@ static void init_lighting( void ) if (!done) { init_light_tab(); - init_light_tab_tw(); - init_light_tab_fl(); - init_light_tab_tw_fl(); - init_light_tab_cm(); - init_light_tab_tw_cm(); - init_light_tab_fl_cm(); - init_light_tab_tw_fl_cm(); + init_light_tab_twoside(); + init_light_tab_material(); + init_light_tab_twoside_material(); done = 1; } } -static GLboolean run_lighting( GLcontext *ctx, struct gl_pipeline_stage *stage ) +static GLboolean run_lighting( GLcontext *ctx, + struct tnl_pipeline_stage *stage ) { struct light_stage_data *store = LIGHT_STAGE_DATA(stage); TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; GLvector4f *input = ctx->_NeedEyeCoords ? VB->EyePtr : VB->ObjPtr; - GLuint ind; + GLuint idx; -/* _tnl_print_vert_flags( __FUNCTION__, stage->changed_inputs ); */ - - /* Make sure we can talk about elements 0..2 in the vector we are - * lighting. + /* Make sure we can talk about position x,y and z: */ - if (stage->changed_inputs & (VERT_BIT_EYE|VERT_BIT_POS)) { - if (input->size <= 2) { - if (input->flags & VEC_NOT_WRITEABLE) { - ASSERT(VB->importable_data & VERT_BIT_POS); - - VB->import_data( ctx, VERT_BIT_POS, VEC_NOT_WRITEABLE ); - input = ctx->_NeedEyeCoords ? VB->EyePtr : VB->ObjPtr; - - ASSERT((input->flags & VEC_NOT_WRITEABLE) == 0); + if (stage->changed_inputs & _TNL_BIT_POS) { + if (input->size <= 2 && input == VB->ObjPtr) { + + _math_trans_4f( store->Input.data, + VB->ObjPtr->data, + VB->ObjPtr->stride, + GL_FLOAT, + VB->ObjPtr->size, + 0, + VB->Count ); + + if (input->size <= 2) { + /* Clean z. + */ + _mesa_vector4f_clean_elem(&store->Input, VB->Count, 2); + } + + if (input->size <= 1) { + /* Clean y. + */ + _mesa_vector4f_clean_elem(&store->Input, VB->Count, 1); } - _mesa_vector4f_clean_elem(input, VB->Count, 2); + input = &store->Input; } } + + idx = 0; - if (VB->Flag) - ind = LIGHT_FLAGS; - else - ind = 0; + if (prepare_materials( ctx, VB, store )) + idx |= LIGHT_MATERIAL; + + if (ctx->Light.Model.TwoSide) + idx |= LIGHT_TWOSIDE; /* The individual functions know about replaying side-effects * vs. full re-execution. */ - store->light_func_tab[ind]( ctx, VB, stage, input ); + store->light_func_tab[idx]( ctx, VB, stage, input ); return GL_TRUE; } @@ -206,9 +224,8 @@ static GLboolean run_lighting( GLcontext *ctx, struct gl_pipeline_stage *stage ) /* Called in place of do_lighting when the light table may have changed. */ static GLboolean run_validate_lighting( GLcontext *ctx, - struct gl_pipeline_stage *stage ) + struct tnl_pipeline_stage *stage ) { - GLuint ind = 0; light_func *tab; if (ctx->Visual.rgbMode) { @@ -228,13 +245,8 @@ static GLboolean run_validate_lighting( GLcontext *ctx, else tab = _tnl_light_ci_tab; - if (ctx->Light.ColorMaterialEnabled) - ind |= LIGHT_COLORMATERIAL; - - if (ctx->Light.Model.TwoSide) - ind |= LIGHT_TWOSIDE; - LIGHT_STAGE_DATA(stage)->light_func_tab = &tab[ind]; + LIGHT_STAGE_DATA(stage)->light_func_tab = tab; /* This and the above should only be done on _NEW_LIGHT: */ @@ -246,23 +258,13 @@ static GLboolean run_validate_lighting( GLcontext *ctx, return stage->run( ctx, stage ); } -static void alloc_4chan( struct gl_client_array *a, GLuint sz ) -{ - a->Ptr = (GLubyte *) ALIGN_MALLOC( sz * sizeof(GLchan) * 4, 32 ); - a->Size = 4; - a->Type = CHAN_TYPE; - a->Stride = 0; - a->StrideB = sizeof(GLchan) * 4; - a->Enabled = 0; - a->Flags = 0; -} /* Called the first time stage->run is called. In effect, don't * allocate data until the first time the stage is run. */ static GLboolean run_init_lighting( GLcontext *ctx, - struct gl_pipeline_stage *stage ) + struct tnl_pipeline_stage *stage ) { TNLcontext *tnl = TNL_CONTEXT(ctx); struct light_stage_data *store; @@ -277,15 +279,18 @@ static GLboolean run_init_lighting( GLcontext *ctx, */ init_lighting(); - store->FloatColor.Ptr = 0; - - alloc_4chan( &store->LitColor[0], size ); - alloc_4chan( &store->LitColor[1], size ); - alloc_4chan( &store->LitSecondary[0], size ); - alloc_4chan( &store->LitSecondary[1], size ); + _mesa_vector4f_alloc( &store->Input, 0, size, 32 ); + _mesa_vector4f_alloc( &store->LitColor[0], 0, size, 32 ); + _mesa_vector4f_alloc( &store->LitColor[1], 0, size, 32 ); + _mesa_vector4f_alloc( &store->LitSecondary[0], 0, size, 32 ); + _mesa_vector4f_alloc( &store->LitSecondary[1], 0, size, 32 ); + _mesa_vector4f_alloc( &store->LitIndex[0], 0, size, 32 ); + _mesa_vector4f_alloc( &store->LitIndex[1], 0, size, 32 ); - _mesa_vector1ui_alloc( &store->LitIndex[0], 0, size, 32 ); - _mesa_vector1ui_alloc( &store->LitIndex[1], 0, size, 32 ); + store->LitIndex[0].size = 1; + store->LitIndex[0].stride = sizeof(GLfloat); + store->LitIndex[1].size = 1; + store->LitIndex[1].stride = sizeof(GLfloat); /* Now validate the stage derived data... */ @@ -299,52 +304,49 @@ static GLboolean run_init_lighting( GLcontext *ctx, * Check if lighting is enabled. If so, configure the pipeline stage's * type, inputs, and outputs. */ -static void check_lighting( GLcontext *ctx, struct gl_pipeline_stage *stage ) +static void check_lighting( GLcontext *ctx, struct tnl_pipeline_stage *stage ) { stage->active = ctx->Light.Enabled && !ctx->VertexProgram.Enabled; if (stage->active) { if (stage->privatePtr) stage->run = run_validate_lighting; - stage->inputs = VERT_BIT_NORMAL|VERT_BIT_MATERIAL; + stage->inputs = _TNL_BIT_NORMAL|_TNL_BITS_MAT_ANY; if (ctx->Light._NeedVertices) - stage->inputs |= VERT_BIT_EYE; /* effectively, even when lighting in obj */ + stage->inputs |= _TNL_BIT_POS; if (ctx->Light.ColorMaterialEnabled) - stage->inputs |= VERT_BIT_COLOR0; + stage->inputs |= _TNL_BIT_COLOR0; - stage->outputs = VERT_BIT_COLOR0; + stage->outputs = _TNL_BIT_COLOR0; if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) - stage->outputs |= VERT_BIT_COLOR1; + stage->outputs |= _TNL_BIT_COLOR1; } } -static void dtr( struct gl_pipeline_stage *stage ) +static void dtr( struct tnl_pipeline_stage *stage ) { struct light_stage_data *store = LIGHT_STAGE_DATA(stage); if (store) { - ALIGN_FREE( (void *) store->LitColor[0].Ptr ); - ALIGN_FREE( (void *) store->LitColor[1].Ptr ); - ALIGN_FREE( (void *) store->LitSecondary[0].Ptr ); - ALIGN_FREE( (void *) store->LitSecondary[1].Ptr ); - - if (store->FloatColor.Ptr) - ALIGN_FREE( (void *) store->FloatColor.Ptr ); - - _mesa_vector1ui_free( &store->LitIndex[0] ); - _mesa_vector1ui_free( &store->LitIndex[1] ); + _mesa_vector4f_free( &store->Input ); + _mesa_vector4f_free( &store->LitColor[0] ); + _mesa_vector4f_free( &store->LitColor[1] ); + _mesa_vector4f_free( &store->LitSecondary[0] ); + _mesa_vector4f_free( &store->LitSecondary[1] ); + _mesa_vector4f_free( &store->LitIndex[0] ); + _mesa_vector4f_free( &store->LitIndex[1] ); FREE( store ); stage->privatePtr = 0; } } -const struct gl_pipeline_stage _tnl_lighting_stage = +const struct tnl_pipeline_stage _tnl_lighting_stage = { "lighting", /* name */ _NEW_LIGHT, /* recheck */ _NEW_LIGHT|_NEW_MODELVIEW, /* recalc -- modelview dependency * otherwise not captured by inputs - * (which may be VERT_BIT_POS) */ + * (which may be _TNL_BIT_POS) */ GL_FALSE, /* active? */ 0, /* inputs */ 0, /* outputs */ diff --git a/src/mesa/tnl/t_vb_lighttmp.h b/src/mesa/tnl/t_vb_lighttmp.h index d1ca33d5d07..167325eae83 100644 --- a/src/mesa/tnl/t_vb_lighttmp.h +++ b/src/mesa/tnl/t_vb_lighttmp.h @@ -29,49 +29,6 @@ */ -#if (IDX & LIGHT_FLAGS) -# define VSTRIDE (4 * sizeof(GLfloat)) -# define NSTRIDE nstride /*(3 * sizeof(GLfloat))*/ -# define CHECK_MATERIAL(x) (flags[x] & VERT_BIT_MATERIAL) -# define CHECK_END_VB(x) (flags[x] & VERT_BIT_END_VB) -# if (IDX & LIGHT_COLORMATERIAL) -# define CMSTRIDE STRIDE_F(CMcolor, CMstride) -# define CHECK_COLOR_MATERIAL(x) (flags[x] & VERT_BIT_COLOR0) -# define CHECK_VALIDATE(x) (flags[x] & (VERT_BIT_COLOR0|VERT_BIT_MATERIAL)) -# define DO_ANOTHER_NORMAL(x) \ - ((flags[x] & (VERT_BIT_COLOR0|VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == VERT_BIT_NORMAL) -# define REUSE_LIGHT_RESULTS(x) \ - ((flags[x] & (VERT_BIT_COLOR0|VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == 0) -# else -# define CMSTRIDE (void)0 -# define CHECK_COLOR_MATERIAL(x) 0 -# define CHECK_VALIDATE(x) (flags[x] & (VERT_BIT_MATERIAL)) -# define DO_ANOTHER_NORMAL(x) \ - ((flags[x] & (VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == VERT_BIT_NORMAL) -# define REUSE_LIGHT_RESULTS(x) \ - ((flags[x] & (VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == 0) -# endif -#else -# define VSTRIDE vstride -# define NSTRIDE nstride -# define CHECK_MATERIAL(x) 0 /* no materials on array paths */ -# define CHECK_END_VB(XX) (XX >= nr) -# if (IDX & LIGHT_COLORMATERIAL) -# define CMSTRIDE STRIDE_F(CMcolor, CMstride) -# define CHECK_COLOR_MATERIAL(x) (x < nr) /* always have colormaterial */ -# define CHECK_VALIDATE(x) (x < nr) -# define DO_ANOTHER_NORMAL(x) 0 /* always stop to recalc colormat */ -# else -# define CMSTRIDE (void)0 -# define CHECK_COLOR_MATERIAL(x) 0 /* no colormaterial */ -# define CHECK_VALIDATE(x) (0) -# define DO_ANOTHER_NORMAL(XX) (XX < nr) /* keep going to end of vb */ -# endif -# define REUSE_LIGHT_RESULTS(x) 0 /* always have a new normal */ -#endif - - - #if (IDX & LIGHT_TWOSIDE) # define NR_SIDES 2 #else @@ -79,7 +36,7 @@ #endif -/* define TRACE if to trace lighting code */ +/* define TRACE to trace lighting code */ /* #define TRACE 1 */ /* @@ -90,12 +47,12 @@ */ static void TAG(light_rgba_spec)( GLcontext *ctx, struct vertex_buffer *VB, - struct gl_pipeline_stage *stage, + struct tnl_pipeline_stage *stage, GLvector4f *input ) { struct light_stage_data *store = LIGHT_STAGE_DATA(stage); GLfloat (*base)[3] = ctx->Light._BaseColor; - GLchan sumA[2]; + GLfloat sumA[2]; GLuint j; const GLuint vstride = input->stride; @@ -103,20 +60,13 @@ static void TAG(light_rgba_spec)( GLcontext *ctx, const GLuint nstride = VB->NormalPtr->stride; const GLfloat *normal = (GLfloat *)VB->NormalPtr->data; - GLfloat *CMcolor; - GLuint CMstride; - - GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr; - GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr; - GLchan (*Fspec)[4] = (GLchan (*)[4]) store->LitSecondary[0].Ptr; - GLchan (*Bspec)[4] = (GLchan (*)[4]) store->LitSecondary[1].Ptr; + GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data; + GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data; + GLfloat (*Fspec)[4] = (GLfloat (*)[4]) store->LitSecondary[0].data; + GLfloat (*Bspec)[4] = (GLfloat (*)[4]) store->LitSecondary[1].data; const GLuint nr = VB->Count; - const GLuint *flags = VB->Flag; - struct gl_material *new_material = VB->Material; - const GLuint *new_material_mask = VB->MaterialMask; - (void) flags; (void) nstride; (void) vstride; @@ -124,23 +74,14 @@ static void TAG(light_rgba_spec)( GLcontext *ctx, fprintf(stderr, "%s\n", __FUNCTION__ ); #endif - if (IDX & LIGHT_COLORMATERIAL) { - if (VB->ColorPtr[0]->Type != GL_FLOAT || - VB->ColorPtr[0]->Size != 4) - import_color_material( ctx, stage ); - - CMcolor = (GLfloat *) VB->ColorPtr[0]->Ptr; - CMstride = VB->ColorPtr[0]->StrideB; - } - VB->ColorPtr[0] = &store->LitColor[0]; VB->SecondaryColorPtr[0] = &store->LitSecondary[0]; - UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]); + sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; if (IDX & LIGHT_TWOSIDE) { VB->ColorPtr[1] = &store->LitColor[1]; VB->SecondaryColorPtr[1] = &store->LitSecondary[1]; - UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]); + sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; } /* Side-effects done, can we finish now? @@ -148,24 +89,15 @@ static void TAG(light_rgba_spec)( GLcontext *ctx, if (stage->changed_inputs == 0) return; - for ( j=0 ; - jDriver.NotifyMaterialChange( ctx ); - UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]); + if ( IDX & LIGHT_MATERIAL ) { + update_materials( ctx, store ); + sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; if (IDX & LIGHT_TWOSIDE) - UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]); + sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; } COPY_3V(sum[0], base[0]); @@ -288,13 +220,13 @@ static void TAG(light_rgba_spec)( GLcontext *ctx, } } /*loop over lights*/ - UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] ); - UNCLAMPED_FLOAT_TO_RGB_CHAN( Fspec[j], spec[0] ); + COPY_3V( Fcolor[j], sum[0] ); + COPY_3V( Fspec[j], spec[0] ); Fcolor[j][3] = sumA[0]; if (IDX & LIGHT_TWOSIDE) { - UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] ); - UNCLAMPED_FLOAT_TO_RGB_CHAN( Bspec[j], spec[1] ); + COPY_3V( Bcolor[j], sum[1] ); + COPY_3V( Bspec[j], spec[1] ); Bcolor[j][3] = sumA[1]; } } @@ -303,81 +235,56 @@ static void TAG(light_rgba_spec)( GLcontext *ctx, static void TAG(light_rgba)( GLcontext *ctx, struct vertex_buffer *VB, - struct gl_pipeline_stage *stage, + struct tnl_pipeline_stage *stage, GLvector4f *input ) { struct light_stage_data *store = LIGHT_STAGE_DATA(stage); GLuint j; GLfloat (*base)[3] = ctx->Light._BaseColor; - GLchan sumA[2]; + GLfloat sumA[2]; const GLuint vstride = input->stride; const GLfloat *vertex = (GLfloat *) input->data; const GLuint nstride = VB->NormalPtr->stride; const GLfloat *normal = (GLfloat *)VB->NormalPtr->data; - GLfloat *CMcolor; - GLuint CMstride; - - GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr; - GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr; - GLchan (*color[2])[4]; - const GLuint *flags = VB->Flag; + GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data; + GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data; + GLfloat (*color[2])[4]; - struct gl_material *new_material = VB->Material; - const GLuint *new_material_mask = VB->MaterialMask; const GLuint nr = VB->Count; #ifdef TRACE fprintf(stderr, "%s\n", __FUNCTION__ ); #endif - (void) flags; (void) nstride; (void) vstride; color[0] = Fcolor; color[1] = Bcolor; - if (IDX & LIGHT_COLORMATERIAL) { - if (VB->ColorPtr[0]->Type != GL_FLOAT || - VB->ColorPtr[0]->Size != 4) - import_color_material( ctx, stage ); - - CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr; - CMstride = VB->ColorPtr[0]->StrideB; - } - VB->ColorPtr[0] = &store->LitColor[0]; - UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]); + sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; if (IDX & LIGHT_TWOSIDE) { VB->ColorPtr[1] = &store->LitColor[1]; - UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]); + sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; } if (stage->changed_inputs == 0) return; - for ( j=0 ; - jDriver.NotifyMaterialChange( ctx ); - UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]); + if ( IDX & LIGHT_MATERIAL ) { + update_materials( ctx, store ); + sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; if (IDX & LIGHT_TWOSIDE) - UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]); + sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; } COPY_3V(sum[0], base[0]); @@ -503,11 +410,11 @@ static void TAG(light_rgba)( GLcontext *ctx, ACC_SCALE_SCALAR_3V( sum[side], attenuation, contrib ); } - UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] ); + COPY_3V( Fcolor[j], sum[0] ); Fcolor[j][3] = sumA[0]; if (IDX & LIGHT_TWOSIDE) { - UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] ); + COPY_3V( Bcolor[j], sum[1] ); Bcolor[j][3] = sumA[1]; } } @@ -520,23 +427,17 @@ static void TAG(light_rgba)( GLcontext *ctx, */ static void TAG(light_fast_rgba_single)( GLcontext *ctx, struct vertex_buffer *VB, - struct gl_pipeline_stage *stage, + struct tnl_pipeline_stage *stage, GLvector4f *input ) { struct light_stage_data *store = LIGHT_STAGE_DATA(stage); const GLuint nstride = VB->NormalPtr->stride; const GLfloat *normal = (GLfloat *)VB->NormalPtr->data; - GLfloat *CMcolor; - GLuint CMstride; - GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr; - GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr; + GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data; + GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data; const struct gl_light *light = ctx->Light.EnabledList.next; - const GLuint *flags = VB->Flag; - GLchan basechan[2][4]; GLuint j = 0; - struct gl_material *new_material = VB->Material; - const GLuint *new_material_mask = VB->MaterialMask; GLfloat base[2][3]; const GLuint nr = VB->Count; @@ -545,19 +446,9 @@ static void TAG(light_fast_rgba_single)( GLcontext *ctx, #endif (void) input; /* doesn't refer to Eye or Obj */ - (void) flags; (void) nr; (void) nstride; - if (IDX & LIGHT_COLORMATERIAL) { - if (VB->ColorPtr[0]->Type != GL_FLOAT || - VB->ColorPtr[0]->Size != 4) - import_color_material( ctx, stage ); - - CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr; - CMstride = VB->ColorPtr[0]->StrideB; - } - VB->ColorPtr[0] = &store->LitColor[0]; if (IDX & LIGHT_TWOSIDE) VB->ColorPtr[1] = &store->LitColor[1]; @@ -565,84 +456,61 @@ static void TAG(light_fast_rgba_single)( GLcontext *ctx, if (stage->changed_inputs == 0) return; - do { - - if ( CHECK_COLOR_MATERIAL(j) ) { - _mesa_update_color_material( ctx, CMcolor ); - } - - if ( CHECK_MATERIAL(j) ) - update_materials( ctx, &new_material[j], new_material_mask[j] ); + for (j = 0; j < nr; j++, STRIDE_F(normal,nstride)) { - if ( CHECK_VALIDATE(j) ) - TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx ); + GLfloat n_dot_VP; + if ( IDX & LIGHT_MATERIAL ) + update_materials( ctx, store ); /* No attenuation, so incoporate _MatAmbient into base color. */ - COPY_3V(base[0], light->_MatAmbient[0]); - ACC_3V(base[0], ctx->Light._BaseColor[0] ); - UNCLAMPED_FLOAT_TO_RGB_CHAN( basechan[0], base[0] ); - UNCLAMPED_FLOAT_TO_CHAN(basechan[0][3], - ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]); + if ( j == 0 || (IDX & LIGHT_MATERIAL) ) { + COPY_3V(base[0], light->_MatAmbient[0]); + ACC_3V(base[0], ctx->Light._BaseColor[0] ); + base[0][3] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; - if (IDX & LIGHT_TWOSIDE) { - COPY_3V(base[1], light->_MatAmbient[1]); - ACC_3V(base[1], ctx->Light._BaseColor[1]); - UNCLAMPED_FLOAT_TO_RGB_CHAN( basechan[1], base[1]); - UNCLAMPED_FLOAT_TO_CHAN(basechan[1][3], - ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]); + if (IDX & LIGHT_TWOSIDE) { + COPY_3V(base[1], light->_MatAmbient[1]); + ACC_3V(base[1], ctx->Light._BaseColor[1]); + base[1][3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; + } } - do { - GLfloat n_dot_VP = DOT3(normal, light->_VP_inf_norm); + n_dot_VP = DOT3(normal, light->_VP_inf_norm); - if (n_dot_VP < 0.0F) { - if (IDX & LIGHT_TWOSIDE) { - GLfloat n_dot_h = -DOT3(normal, light->_h_inf_norm); - GLfloat sum[3]; - COPY_3V(sum, base[1]); - ACC_SCALE_SCALAR_3V(sum, -n_dot_VP, light->_MatDiffuse[1]); - if (n_dot_h > 0.0F) { - GLfloat spec; - GET_SHINE_TAB_ENTRY( ctx->_ShineTable[1], n_dot_h, spec ); - ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[1]); - } - UNCLAMPED_FLOAT_TO_RGB_CHAN(Bcolor[j], sum ); - Bcolor[j][3] = basechan[1][3]; - } - COPY_CHAN4(Fcolor[j], basechan[0]); - } - else { - GLfloat n_dot_h = DOT3(normal, light->_h_inf_norm); + if (n_dot_VP < 0.0F) { + if (IDX & LIGHT_TWOSIDE) { + GLfloat n_dot_h = -DOT3(normal, light->_h_inf_norm); GLfloat sum[3]; - COPY_3V(sum, base[0]); - ACC_SCALE_SCALAR_3V(sum, n_dot_VP, light->_MatDiffuse[0]); + COPY_3V(sum, base[1]); + ACC_SCALE_SCALAR_3V(sum, -n_dot_VP, light->_MatDiffuse[1]); if (n_dot_h > 0.0F) { GLfloat spec; - GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec ); - ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[0]); - + GET_SHINE_TAB_ENTRY( ctx->_ShineTable[1], n_dot_h, spec ); + ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[1]); } - UNCLAMPED_FLOAT_TO_RGB_CHAN(Fcolor[j], sum ); - Fcolor[j][3] = basechan[0][3]; - if (IDX & LIGHT_TWOSIDE) COPY_CHAN4(Bcolor[j], basechan[1]); + COPY_3V(Bcolor[j], sum ); + Bcolor[j][3] = base[1][3]; } - - j++; - CMSTRIDE; - STRIDE_F(normal, NSTRIDE); - } while (DO_ANOTHER_NORMAL(j)); - - - for ( ; REUSE_LIGHT_RESULTS(j) ; j++, CMSTRIDE, STRIDE_F(normal,NSTRIDE)) - { - COPY_CHAN4(Fcolor[j], Fcolor[j-1]); - if (IDX & LIGHT_TWOSIDE) - COPY_CHAN4(Bcolor[j], Bcolor[j-1]); + COPY_4FV(Fcolor[j], base[0]); } + else { + GLfloat n_dot_h = DOT3(normal, light->_h_inf_norm); + GLfloat sum[3]; + COPY_3V(sum, base[0]); + ACC_SCALE_SCALAR_3V(sum, n_dot_VP, light->_MatDiffuse[0]); + if (n_dot_h > 0.0F) { + GLfloat spec; + GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec ); + ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[0]); - } while (!CHECK_END_VB(j)); + } + COPY_3V(Fcolor[j], sum ); + Fcolor[j][3] = base[0][3]; + if (IDX & LIGHT_TWOSIDE) COPY_4FV(Bcolor[j], base[1]); + } + } } @@ -650,44 +518,29 @@ static void TAG(light_fast_rgba_single)( GLcontext *ctx, */ static void TAG(light_fast_rgba)( GLcontext *ctx, struct vertex_buffer *VB, - struct gl_pipeline_stage *stage, + struct tnl_pipeline_stage *stage, GLvector4f *input ) { struct light_stage_data *store = LIGHT_STAGE_DATA(stage); - GLchan sumA[2]; + GLfloat sumA[2]; const GLuint nstride = VB->NormalPtr->stride; const GLfloat *normal = (GLfloat *)VB->NormalPtr->data; - GLfloat *CMcolor; - GLuint CMstride; - GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr; - GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr; - const GLuint *flags = VB->Flag; + GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data; + GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data; GLuint j = 0; - struct gl_material *new_material = VB->Material; - GLuint *new_material_mask = VB->MaterialMask; const GLuint nr = VB->Count; const struct gl_light *light; #ifdef TRACE - fprintf(stderr, "%s\n", __FUNCTION__ ); + fprintf(stderr, "%s %d\n", __FUNCTION__, nr ); #endif - (void) flags; (void) input; (void) nr; (void) nstride; - UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]); - UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]); - - if (IDX & LIGHT_COLORMATERIAL) { - if (VB->ColorPtr[0]->Type != GL_FLOAT || - VB->ColorPtr[0]->Size != 4) - import_color_material( ctx, stage ); - - CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr; - CMstride = VB->ColorPtr[0]->StrideB; - } + sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; + sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; VB->ColorPtr[0] = &store->LitColor[0]; if (IDX & LIGHT_TWOSIDE) @@ -696,84 +549,60 @@ static void TAG(light_fast_rgba)( GLcontext *ctx, if (stage->changed_inputs == 0) return; - do { - do { - GLfloat sum[2][3]; + for (j = 0; j < nr; j++, STRIDE_F(normal,nstride)) { - if ( CHECK_COLOR_MATERIAL(j) ) - _mesa_update_color_material( ctx, CMcolor ); + GLfloat sum[2][3]; - if ( CHECK_MATERIAL(j) ) - update_materials( ctx, &new_material[j], new_material_mask[j] ); + if ( IDX & LIGHT_MATERIAL ) { + update_materials( ctx, store ); - if ( CHECK_VALIDATE(j) ) { - TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx ); - UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]); - if (IDX & LIGHT_TWOSIDE) - UNCLAMPED_FLOAT_TO_CHAN(sumA[1], - ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]); - } + sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; + if (IDX & LIGHT_TWOSIDE) + sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; + } - COPY_3V(sum[0], ctx->Light._BaseColor[0]); - if (IDX & LIGHT_TWOSIDE) - COPY_3V(sum[1], ctx->Light._BaseColor[1]); + COPY_3V(sum[0], ctx->Light._BaseColor[0]); + if (IDX & LIGHT_TWOSIDE) + COPY_3V(sum[1], ctx->Light._BaseColor[1]); - foreach (light, &ctx->Light.EnabledList) { - GLfloat n_dot_h, n_dot_VP, spec; + foreach (light, &ctx->Light.EnabledList) { + GLfloat n_dot_h, n_dot_VP, spec; - ACC_3V(sum[0], light->_MatAmbient[0]); - if (IDX & LIGHT_TWOSIDE) - ACC_3V(sum[1], light->_MatAmbient[1]); + ACC_3V(sum[0], light->_MatAmbient[0]); + if (IDX & LIGHT_TWOSIDE) + ACC_3V(sum[1], light->_MatAmbient[1]); - n_dot_VP = DOT3(normal, light->_VP_inf_norm); + n_dot_VP = DOT3(normal, light->_VP_inf_norm); - if (n_dot_VP > 0.0F) { - ACC_SCALE_SCALAR_3V(sum[0], n_dot_VP, light->_MatDiffuse[0]); - n_dot_h = DOT3(normal, light->_h_inf_norm); - if (n_dot_h > 0.0F) { - struct gl_shine_tab *tab = ctx->_ShineTable[0]; - GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec ); - ACC_SCALE_SCALAR_3V( sum[0], spec, - light->_MatSpecular[0]); - } - } - else if (IDX & LIGHT_TWOSIDE) { - ACC_SCALE_SCALAR_3V(sum[1], -n_dot_VP, light->_MatDiffuse[1]); - n_dot_h = -DOT3(normal, light->_h_inf_norm); - if (n_dot_h > 0.0F) { - struct gl_shine_tab *tab = ctx->_ShineTable[1]; - GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec ); - ACC_SCALE_SCALAR_3V( sum[1], spec, - light->_MatSpecular[1]); - } + if (n_dot_VP > 0.0F) { + ACC_SCALE_SCALAR_3V(sum[0], n_dot_VP, light->_MatDiffuse[0]); + n_dot_h = DOT3(normal, light->_h_inf_norm); + if (n_dot_h > 0.0F) { + struct gl_shine_tab *tab = ctx->_ShineTable[0]; + GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec ); + ACC_SCALE_SCALAR_3V( sum[0], spec, light->_MatSpecular[0]); } } - - UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] ); - Fcolor[j][3] = sumA[0]; - - if (IDX & LIGHT_TWOSIDE) { - UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] ); - Bcolor[j][3] = sumA[1]; + else if (IDX & LIGHT_TWOSIDE) { + ACC_SCALE_SCALAR_3V(sum[1], -n_dot_VP, light->_MatDiffuse[1]); + n_dot_h = -DOT3(normal, light->_h_inf_norm); + if (n_dot_h > 0.0F) { + struct gl_shine_tab *tab = ctx->_ShineTable[1]; + GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec ); + ACC_SCALE_SCALAR_3V( sum[1], spec, light->_MatSpecular[1]); + } } + } - j++; - CMSTRIDE; - STRIDE_F(normal, NSTRIDE); - } while (DO_ANOTHER_NORMAL(j)); + COPY_3V( Fcolor[j], sum[0] ); + Fcolor[j][3] = sumA[0]; - /* Reuse the shading results while there is no change to - * normal or material values. - */ - for ( ; REUSE_LIGHT_RESULTS(j) ; j++, CMSTRIDE, STRIDE_F(normal, NSTRIDE)) - { - COPY_CHAN4(Fcolor[j], Fcolor[j-1]); - if (IDX & LIGHT_TWOSIDE) - COPY_CHAN4(Bcolor[j], Bcolor[j-1]); + if (IDX & LIGHT_TWOSIDE) { + COPY_3V( Bcolor[j], sum[1] ); + Bcolor[j][3] = sumA[1]; } - - } while (!CHECK_END_VB(j)); + } } @@ -791,7 +620,7 @@ static void TAG(light_fast_rgba)( GLcontext *ctx, */ static void TAG(light_ci)( GLcontext *ctx, struct vertex_buffer *VB, - struct gl_pipeline_stage *stage, + struct tnl_pipeline_stage *stage, GLvector4f *input ) { struct light_stage_data *store = LIGHT_STAGE_DATA(stage); @@ -800,19 +629,13 @@ static void TAG(light_ci)( GLcontext *ctx, const GLfloat *vertex = (GLfloat *) input->data; const GLuint nstride = VB->NormalPtr->stride; const GLfloat *normal = (GLfloat *)VB->NormalPtr->data; - GLfloat *CMcolor; - GLuint CMstride; - const GLuint *flags = VB->Flag; - GLuint *indexResult[2]; - struct gl_material *new_material = VB->Material; - GLuint *new_material_mask = VB->MaterialMask; + GLfloat *indexResult[2]; const GLuint nr = VB->Count; #ifdef TRACE fprintf(stderr, "%s\n", __FUNCTION__ ); #endif - (void) flags; (void) nstride; (void) vstride; @@ -823,36 +646,18 @@ static void TAG(light_ci)( GLcontext *ctx, if (stage->changed_inputs == 0) return; - indexResult[0] = VB->IndexPtr[0]->data; + indexResult[0] = (GLfloat *)VB->IndexPtr[0]->data; if (IDX & LIGHT_TWOSIDE) - indexResult[1] = VB->IndexPtr[1]->data; - - if (IDX & LIGHT_COLORMATERIAL) { - if (VB->ColorPtr[0]->Type != GL_FLOAT || - VB->ColorPtr[0]->Size != 4) - import_color_material( ctx, stage ); - - CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr; - CMstride = VB->ColorPtr[0]->StrideB; - } + indexResult[1] = (GLfloat *)VB->IndexPtr[1]->data; /* loop over vertices */ - for ( j=0 ; - jDriver.NotifyMaterialChange( ctx ); + if ( IDX & LIGHT_MATERIAL ) + update_materials( ctx, store ); diffuse[0] = specular[0] = 0.0F; @@ -962,7 +767,6 @@ static void TAG(light_ci)( GLcontext *ctx, else { GLfloat d_a = ind[MAT_INDEX_DIFFUSE] - ind[MAT_INDEX_AMBIENT]; GLfloat s_a = ind[MAT_INDEX_SPECULAR] - ind[MAT_INDEX_AMBIENT]; - index = (ind[MAT_INDEX_AMBIENT] + diffuse[side] * (1.0F-specular[side]) * d_a + specular[side] * s_a); @@ -970,7 +774,7 @@ static void TAG(light_ci)( GLcontext *ctx, index = ind[MAT_INDEX_SPECULAR]; } } - indexResult[side][j] = (GLuint) (GLint) index; + indexResult[side][j] = index; } } /*for vertex*/ } @@ -990,12 +794,3 @@ static void TAG(init_light_tab)( void ) #undef TAG #undef IDX #undef NR_SIDES -#undef NSTRIDE -#undef VSTRIDE -#undef CHECK_MATERIAL -#undef CHECK_END_VB -#undef DO_ANOTHER_NORMAL -#undef REUSE_LIGHT_RESULTS -#undef CMSTRIDE -#undef CHECK_COLOR_MATERIAL -#undef CHECK_VALIDATE diff --git a/src/mesa/tnl/t_vb_normals.c b/src/mesa/tnl/t_vb_normals.c index 22c97291435..96a43f68845 100644 --- a/src/mesa/tnl/t_vb_normals.c +++ b/src/mesa/tnl/t_vb_normals.c @@ -52,7 +52,7 @@ struct normal_stage_data { static GLboolean run_normal_stage( GLcontext *ctx, - struct gl_pipeline_stage *stage ) + struct tnl_pipeline_stage *stage ) { struct normal_stage_data *store = NORMAL_STAGE_DATA(stage); struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; @@ -83,7 +83,7 @@ static GLboolean run_normal_stage( GLcontext *ctx, static GLboolean run_validate_normal_stage( GLcontext *ctx, - struct gl_pipeline_stage *stage ) + struct tnl_pipeline_stage *stage ) { struct normal_stage_data *store = NORMAL_STAGE_DATA(stage); @@ -133,7 +133,7 @@ static GLboolean run_validate_normal_stage( GLcontext *ctx, static void check_normal_transform( GLcontext *ctx, - struct gl_pipeline_stage *stage ) + struct tnl_pipeline_stage *stage ) { stage->active = !ctx->VertexProgram.Enabled && (ctx->Light.Enabled || (ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS)); @@ -146,7 +146,7 @@ static void check_normal_transform( GLcontext *ctx, static GLboolean alloc_normal_data( GLcontext *ctx, - struct gl_pipeline_stage *stage ) + struct tnl_pipeline_stage *stage ) { TNLcontext *tnl = TNL_CONTEXT(ctx); struct normal_stage_data *store; @@ -165,7 +165,7 @@ static GLboolean alloc_normal_data( GLcontext *ctx, -static void free_normal_data( struct gl_pipeline_stage *stage ) +static void free_normal_data( struct tnl_pipeline_stage *stage ) { struct normal_stage_data *store = NORMAL_STAGE_DATA(stage); if (store) { @@ -182,14 +182,14 @@ static void free_normal_data( struct gl_pipeline_stage *stage ) -const struct gl_pipeline_stage _tnl_normal_transform_stage = +const struct tnl_pipeline_stage _tnl_normal_transform_stage = { "normal transform", /* name */ _TNL_NEW_NORMAL_TRANSFORM, /* re-check */ _TNL_NEW_NORMAL_TRANSFORM, /* re-run */ GL_FALSE, /* active? */ - VERT_BIT_NORMAL, /* inputs */ - VERT_BIT_NORMAL, /* outputs */ + _TNL_BIT_NORMAL, /* inputs */ + _TNL_BIT_NORMAL, /* outputs */ 0, /* changed_inputs */ NULL, /* private data */ free_normal_data, /* destructor */ diff --git a/src/mesa/tnl/t_vb_points.c b/src/mesa/tnl/t_vb_points.c index 06f2c8c1408..7a071ed3739 100644 --- a/src/mesa/tnl/t_vb_points.c +++ b/src/mesa/tnl/t_vb_points.c @@ -43,7 +43,7 @@ struct point_stage_data { * Compute attenuated point sizes */ static GLboolean run_point_stage( GLcontext *ctx, - struct gl_pipeline_stage *stage ) + struct tnl_pipeline_stage *stage ) { struct point_stage_data *store = POINT_STAGE_DATA(stage); struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; @@ -73,13 +73,13 @@ static GLboolean run_point_stage( GLcontext *ctx, /* If point size attenuation is on we'll compute the point size for * each vertex in a special pipeline stage. */ -static void check_point_size( GLcontext *ctx, struct gl_pipeline_stage *d ) +static void check_point_size( GLcontext *ctx, struct tnl_pipeline_stage *d ) { d->active = ctx->Point._Attenuated && !ctx->VertexProgram.Enabled; } static GLboolean alloc_point_data( GLcontext *ctx, - struct gl_pipeline_stage *stage ) + struct tnl_pipeline_stage *stage ) { struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; struct point_stage_data *store; @@ -97,7 +97,7 @@ static GLboolean alloc_point_data( GLcontext *ctx, } -static void free_point_data( struct gl_pipeline_stage *stage ) +static void free_point_data( struct tnl_pipeline_stage *stage ) { struct point_stage_data *store = POINT_STAGE_DATA(stage); if (store) { @@ -107,14 +107,14 @@ static void free_point_data( struct gl_pipeline_stage *stage ) } } -const struct gl_pipeline_stage _tnl_point_attenuation_stage = +const struct tnl_pipeline_stage _tnl_point_attenuation_stage = { "point size attenuation", /* name */ _NEW_POINT, /* build_state_change */ _NEW_POINT, /* run_state_change */ GL_FALSE, /* active */ - VERT_BIT_EYE, /* inputs */ - VERT_BIT_POINT_SIZE, /* outputs */ + _TNL_BIT_POS, /* inputs */ + _TNL_BIT_POS, /* outputs */ 0, /* changed_inputs (temporary value) */ NULL, /* stage private data */ free_point_data, /* destructor */ diff --git a/src/mesa/tnl/t_vb_program.c b/src/mesa/tnl/t_vb_program.c index 7fac7ec893b..6aa28902477 100644 --- a/src/mesa/tnl/t_vb_program.c +++ b/src/mesa/tnl/t_vb_program.c @@ -49,8 +49,6 @@ #include "t_context.h" #include "t_pipeline.h" -#include "t_imm_api.h" -#include "t_imm_exec.h" /** @@ -81,10 +79,6 @@ struct vp_stage_data { /** The results of running the vertex program go into these arrays. */ GLvector4f attribs[15]; - /* These point to the attribs[VERT_RESULT_COL0, COL1, BFC0, BFC1] arrays */ - struct gl_client_array color0[2]; /**< diffuse front and back */ - struct gl_client_array color1[2]; /**< specular front and back */ - GLvector4f ndcCoords; /**< normalized device coords */ GLubyte *clipmask; /**< clip flags */ GLubyte ormask, andmask; /**< for clipping */ @@ -97,7 +91,7 @@ struct vp_stage_data { /** * This function executes vertex programs */ -static GLboolean run_vp( GLcontext *ctx, struct gl_pipeline_stage *stage ) +static GLboolean run_vp( GLcontext *ctx, struct tnl_pipeline_stage *stage ) { TNLcontext *tnl = TNL_CONTEXT(ctx); struct vp_stage_data *store = VP_STAGE_DATA(stage); @@ -129,28 +123,16 @@ static GLboolean run_vp( GLcontext *ctx, struct gl_pipeline_stage *stage ) VB->AttribPtr[2]->data[i][3]); #endif - /* load the input attribute registers */ - if (VB->Flag) { - /* the traditional glBegin/glVertex/glEnd case */ - for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { - if (attr == 0 || (program->InputsRead & (1 << attr))) { - COPY_4V(ctx->VertexProgram.Inputs[attr], - VB->AttribPtr[attr]->data[i]); - } - } - } - else { - /* the vertex array case */ - for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { - if (program->InputsRead & (1 << attr)) { - const GLubyte *ptr = (const GLubyte*) VB->AttribPtr[attr]->data; - const GLuint stride = VB->AttribPtr[attr]->stride; - const GLfloat *data = (GLfloat *) (ptr + stride * i); - COPY_4V(ctx->VertexProgram.Inputs[attr], data); - /*ASSERT(VB->AttribPtr[attr]->size == 4);*/ - ASSERT(stride == 4 * sizeof(GLfloat) || stride == 0); - } - } + /* the vertex array case */ + for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { + if (program->InputsRead & (1 << attr)) { + const GLubyte *ptr = (const GLubyte*) VB->AttribPtr[attr]->data; + const GLuint size = VB->AttribPtr[attr]->size; + const GLuint stride = VB->AttribPtr[attr]->stride; + const GLfloat *data = (GLfloat *) (ptr + stride * i); + ASSIGN_4V(ctx->VertexProgram.Inputs[attr], 0, 0, 0, 1); + COPY_SZ_4V(ctx->VertexProgram.Inputs[attr], size, data); + } } /* execute the program */ @@ -182,10 +164,10 @@ static GLboolean run_vp( GLcontext *ctx, struct gl_pipeline_stage *stage ) VB->ClipPtr = &store->attribs[VERT_RESULT_HPOS]; VB->ClipPtr->size = 4; VB->ClipPtr->count = VB->Count; - VB->ColorPtr[0] = &store->color0[0]; - VB->ColorPtr[1] = &store->color0[1]; - VB->SecondaryColorPtr[0] = &store->color1[0]; - VB->SecondaryColorPtr[1] = &store->color1[1]; + VB->ColorPtr[0] = &store->attribs[VERT_RESULT_COL0]; + VB->ColorPtr[1] = &store->attribs[VERT_RESULT_BFC0]; + VB->SecondaryColorPtr[0] = &store->attribs[VERT_RESULT_COL1]; + VB->SecondaryColorPtr[1] = &store->attribs[VERT_RESULT_BFC1]; VB->FogCoordPtr = &store->attribs[VERT_RESULT_FOGC]; VB->PointSizePtr = &store->attribs[VERT_RESULT_PSIZ]; for (i = 0; i < ctx->Const.MaxTextureUnits; i++) @@ -225,11 +207,6 @@ static GLboolean run_vp( GLcontext *ctx, struct gl_pipeline_stage *stage ) VB->ClipOrMask = store->ormask; VB->ClipMask = store->clipmask; - /* XXXX what's this? - if (VB->ClipPtr == VB->ObjPtr && (VB->importable_data & VERT_BIT_POS)) - VB->importable_data |= VERT_BIT_CLIP; - */ - return GL_TRUE; } @@ -238,7 +215,7 @@ static GLboolean run_vp( GLcontext *ctx, struct gl_pipeline_stage *stage ) * This function validates stuff. */ static GLboolean run_validate_program( GLcontext *ctx, - struct gl_pipeline_stage *stage ) + struct tnl_pipeline_stage *stage ) { #if 000 /* XXX do we need any validation for vertex programs? */ @@ -282,27 +259,13 @@ static GLboolean run_validate_program( GLcontext *ctx, } -/** - * Initialize a gl_client_array to point into a GLvector4f color vector. - */ -static void init_color_array( struct gl_client_array *a, GLvector4f *vec ) -{ - a->Ptr = (GLubyte *) vec->data; - a->Size = 4; - a->Type = GL_FLOAT; - a->Stride = 0; - a->StrideB = sizeof(GLfloat) * 4; - a->Enabled = 0; - a->Flags = 0; -} - /** * Called the first time stage->run is called. In effect, don't * allocate data until the first time the stage is run. */ static GLboolean run_init_vp( GLcontext *ctx, - struct gl_pipeline_stage *stage ) + struct tnl_pipeline_stage *stage ) { TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &(tnl->vb); @@ -321,12 +284,6 @@ static GLboolean run_init_vp( GLcontext *ctx, store->attribs[i].size = 4; } - /* Make the color0[] and color1[] arrays point into the attribs[] arrays */ - init_color_array( &store->color0[0], &store->attribs[VERT_RESULT_COL0] ); - init_color_array( &store->color0[1], &store->attribs[VERT_RESULT_BFC0] ); - init_color_array( &store->color1[0], &store->attribs[VERT_RESULT_COL1] ); - init_color_array( &store->color1[1], &store->attribs[VERT_RESULT_BFC1] ); - /* a few other misc allocations */ _mesa_vector4f_alloc( &store->ndcCoords, 0, size, 32 ); store->clipmask = (GLubyte *) ALIGN_MALLOC(sizeof(GLubyte)*size, 32 ); @@ -343,31 +300,15 @@ static GLboolean run_init_vp( GLcontext *ctx, * Check if vertex program mode is enabled. * If so, configure the pipeline stage's type, inputs, and outputs. */ -static void check_vp( GLcontext *ctx, struct gl_pipeline_stage *stage ) +static void check_vp( GLcontext *ctx, struct tnl_pipeline_stage *stage ) { stage->active = ctx->VertexProgram.Enabled; if (stage->active) { - /* I believe this is right - Keith? - * Set stage->inputs equal to the bitmask of vertex attributes + /* Set stage->inputs equal to the bitmask of vertex attributes * which the program needs for inputs. */ - stage->inputs = ctx->VertexProgram.Current->InputsRead; - -#if 000 - if (stage->privatePtr) - stage->run = run_validate_program; - stage->inputs = VERT_BIT_NORMAL|VERT_BIT_MATERIAL; - if (ctx->Light._NeedVertices) - stage->inputs |= VERT_BIT_EYE; /* effectively, even when lighting in obj */ - if (ctx->Light.ColorMaterialEnabled) - stage->inputs |= VERT_BIT_COLOR0; - - stage->outputs = VERT_BIT_COLOR0; - if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) - stage->outputs |= VERT_BIT_COLOR1; -#endif } } @@ -375,7 +316,7 @@ static void check_vp( GLcontext *ctx, struct gl_pipeline_stage *stage ) /** * Destructor for this pipeline stage. */ -static void dtr( struct gl_pipeline_stage *stage ) +static void dtr( struct tnl_pipeline_stage *stage ) { struct vp_stage_data *store = VP_STAGE_DATA(stage); @@ -398,16 +339,14 @@ static void dtr( struct gl_pipeline_stage *stage ) /** * Public description of this pipeline stage. */ -const struct gl_pipeline_stage _tnl_vertex_program_stage = +const struct tnl_pipeline_stage _tnl_vertex_program_stage = { "vertex-program", _NEW_ALL, /*XXX FIX */ /* recheck */ - _NEW_ALL, /*XXX FIX */ /* recalc -- modelview dependency - * otherwise not captured by inputs - * (which may be VERT_BIT_POS) */ + _NEW_ALL, /*XXX FIX */ /* recalc */ GL_FALSE, /* active */ - /*0*/ VERT_BIT_POS, /* inputs XXX OK? */ - VERT_BIT_CLIP | VERT_BIT_COLOR0, /* outputs XXX OK? */ + 0, /* inputs - calculated on the fly */ + _TNL_BITS_PROG_ANY, /* outputs -- could calculate */ 0, /* changed_inputs */ NULL, /* private_data */ dtr, /* destroy */ diff --git a/src/mesa/tnl/t_vb_render.c b/src/mesa/tnl/t_vb_render.c index dd06874304b..ec0d11bf84c 100644 --- a/src/mesa/tnl/t_vb_render.c +++ b/src/mesa/tnl/t_vb_render.c @@ -261,7 +261,7 @@ void _tnl_RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj ) static GLboolean run_render( GLcontext *ctx, - struct gl_pipeline_stage *stage ) + struct tnl_pipeline_stage *stage ) { TNLcontext *tnl = TNL_CONTEXT(ctx); struct vertex_buffer *VB = &tnl->vb; @@ -304,29 +304,29 @@ static GLboolean run_render( GLcontext *ctx, do { - GLuint i, length, flags = 0; - for (i = VB->FirstPrimitive ; !(flags & PRIM_LAST) ; i += length) + GLint i; + + for (i = 0 ; i < VB->PrimitiveCount ; i++) { - flags = VB->Primitive[i]; - length= VB->PrimitiveLength[i]; - ASSERT(length || (flags & PRIM_LAST)); - ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1); + GLuint prim = VB->Primitive[i].mode; + GLuint start = VB->Primitive[i].start; + GLuint length = VB->Primitive[i].count; + + assert((prim & PRIM_MODE_MASK) < GL_POLYGON+1); - if (MESA_VERBOSE & VERBOSE_PRIMS) + if (MESA_VERBOSE & VERBOSE_PRIMS) _mesa_debug(NULL, "MESA prim %s %d..%d\n", - _mesa_lookup_enum_by_nr(flags & PRIM_MODE_MASK), - i, i+length); + _mesa_lookup_enum_by_nr(prim & PRIM_MODE_MASK), + start, start+length); if (length) - tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags ); + tab[prim & PRIM_MODE_MASK]( ctx, start, start + length, prim ); } } while (tnl->Driver.Render.Multipass && tnl->Driver.Render.Multipass( ctx, ++pass )); - tnl->Driver.Render.Finish( ctx ); -/* _swrast_flush(ctx); */ -/* usleep(1000000); */ + return GL_FALSE; /* finished the pipe */ } @@ -340,41 +340,38 @@ static GLboolean run_render( GLcontext *ctx, /* Quite a bit of work involved in finding out the inputs for the * render stage. */ -static void check_render( GLcontext *ctx, struct gl_pipeline_stage *stage ) +static void check_render( GLcontext *ctx, struct tnl_pipeline_stage *stage ) { - GLuint inputs = VERT_BIT_CLIP; + GLuint inputs = _TNL_BIT_POS; GLuint i; if (ctx->Visual.rgbMode) { - inputs |= VERT_BIT_COLOR0; + inputs |= _TNL_BIT_COLOR0; if (NEED_SECONDARY_COLOR(ctx)) - inputs |= VERT_BIT_COLOR1; + inputs |= _TNL_BIT_COLOR1; if (ctx->Texture._EnabledCoordUnits) { for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) { if (ctx->Texture._EnabledCoordUnits & (1 << i)) - inputs |= VERT_BIT_TEX(i); + inputs |= _TNL_BIT_TEX(i); } } } else { - inputs |= VERT_BIT_INDEX; + inputs |= _TNL_BIT_INDEX; } - if (ctx->Point._Attenuated) - inputs |= VERT_BIT_POINT_SIZE; - /* How do drivers turn this off? */ if (ctx->Fog.Enabled) - inputs |= VERT_BIT_FOG; + inputs |= _TNL_BIT_FOG; if (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL) - inputs |= VERT_BIT_EDGEFLAG; + inputs |= _TNL_BIT_EDGEFLAG; if (ctx->RenderMode==GL_FEEDBACK) - inputs |= VERT_BITS_TEX_ANY; + inputs |= _TNL_BITS_TEX_ANY; stage->inputs = inputs; } @@ -382,12 +379,12 @@ static void check_render( GLcontext *ctx, struct gl_pipeline_stage *stage ) -static void dtr( struct gl_pipeline_stage *stage ) +static void dtr( struct tnl_pipeline_stage *stage ) { } -const struct gl_pipeline_stage _tnl_render_stage = +const struct tnl_pipeline_stage _tnl_render_stage = { "render", /* name */ (_NEW_BUFFERS | diff --git a/src/mesa/tnl/t_vb_rendertmp.h b/src/mesa/tnl/t_vb_rendertmp.h index 7bc0e37facc..3db94bc0934 100644 --- a/src/mesa/tnl/t_vb_rendertmp.h +++ b/src/mesa/tnl/t_vb_rendertmp.h @@ -52,7 +52,6 @@ #ifndef TEST_PRIM_END #define TEST_PRIM_END(flags) (flags & PRIM_END) #define TEST_PRIM_BEGIN(flags) (flags & PRIM_BEGIN) -#define TEST_PRIM_PARITY(flags) (flags & PRIM_PARITY) #endif #ifndef ELT @@ -187,9 +186,6 @@ static void TAG(render_tri_strip)( GLcontext *ctx, GLuint parity = 0; LOCAL_VARS; - if (TEST_PRIM_PARITY(flags)) - parity = 1; - INIT(GL_TRIANGLE_STRIP); if (NEED_EDGEFLAG_SETUP) { for (j=start+2;jtmp_f; GLfloat *m = store->tmp_m; - -/* _mesa_debug(NULL, "%s normstride %d eyestride %d\n", */ -/* __FUNCTION__, VB->NormalPtr->stride, */ -/* VB->EyePtr->stride); */ - (build_m_tab[VB->EyePtr->size])( store->tmp_f, store->tmp_m, VB->NormalPtr, @@ -518,7 +513,7 @@ static void texgen( GLcontext *ctx, static GLboolean run_texgen_stage( GLcontext *ctx, - struct gl_pipeline_stage *stage ) + struct tnl_pipeline_stage *stage ) { struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; struct texgen_stage_data *store = TEXGEN_STAGE_DATA( stage ); @@ -526,7 +521,7 @@ static GLboolean run_texgen_stage( GLcontext *ctx, for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) if (ctx->Texture._TexGenEnabled & ENABLE_TEXGEN(i)) { - if (stage->changed_inputs & (VERT_BIT_EYE | VERT_BIT_NORMAL | VERT_BIT_TEX(i))) + if (stage->changed_inputs & (_TNL_BIT_POS | _TNL_BIT_NORMAL | _TNL_BIT_TEX(i))) store->TexgenFunc[i]( ctx, store, i ); VB->TexCoordPtr[i] = &store->texcoord[i]; @@ -539,7 +534,7 @@ static GLboolean run_texgen_stage( GLcontext *ctx, static GLboolean run_validate_texgen_stage( GLcontext *ctx, - struct gl_pipeline_stage *stage ) + struct tnl_pipeline_stage *stage ) { struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage); GLuint i; @@ -584,7 +579,7 @@ static GLboolean run_validate_texgen_stage( GLcontext *ctx, } -static void check_texgen( GLcontext *ctx, struct gl_pipeline_stage *stage ) +static void check_texgen( GLcontext *ctx, struct tnl_pipeline_stage *stage ) { GLuint i; stage->active = 0; @@ -593,24 +588,21 @@ static void check_texgen( GLcontext *ctx, struct gl_pipeline_stage *stage ) GLuint inputs = 0; GLuint outputs = 0; - if (ctx->Texture._GenFlags & TEXGEN_OBJ_LINEAR) - inputs |= VERT_BIT_POS; - - if (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD) - inputs |= VERT_BIT_EYE; + if (ctx->Texture._GenFlags & (TEXGEN_OBJ_LINEAR | TEXGEN_NEED_EYE_COORD)) + inputs |= _TNL_BIT_POS; if (ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS) - inputs |= VERT_BIT_NORMAL; + inputs |= _TNL_BIT_NORMAL; for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) if (ctx->Texture._TexGenEnabled & ENABLE_TEXGEN(i)) { - outputs |= VERT_BIT_TEX(i); + outputs |= _TNL_BIT_TEX(i); /* Need the original input in case it contains a Q coord: * (sigh) */ - inputs |= VERT_BIT_TEX(i); + inputs |= _TNL_BIT_TEX(i); /* Something for Feedback? */ } @@ -629,7 +621,7 @@ static void check_texgen( GLcontext *ctx, struct gl_pipeline_stage *stage ) /* Called the first time stage->run() is invoked. */ static GLboolean alloc_texgen_data( GLcontext *ctx, - struct gl_pipeline_stage *stage ) + struct tnl_pipeline_stage *stage ) { struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; struct texgen_stage_data *store; @@ -653,7 +645,7 @@ static GLboolean alloc_texgen_data( GLcontext *ctx, } -static void free_texgen_data( struct gl_pipeline_stage *stage ) +static void free_texgen_data( struct tnl_pipeline_stage *stage ) { struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage); @@ -674,7 +666,7 @@ static void free_texgen_data( struct gl_pipeline_stage *stage ) -const struct gl_pipeline_stage _tnl_texgen_stage = +const struct tnl_pipeline_stage _tnl_texgen_stage = { "texgen", /* name */ _NEW_TEXTURE, /* when to call check() */ diff --git a/src/mesa/tnl/t_vb_texmat.c b/src/mesa/tnl/t_vb_texmat.c index 3d5c43dd637..b6e672a8d4e 100644 --- a/src/mesa/tnl/t_vb_texmat.c +++ b/src/mesa/tnl/t_vb_texmat.c @@ -52,7 +52,7 @@ struct texmat_stage_data { #define TEXMAT_STAGE_DATA(stage) ((struct texmat_stage_data *)stage->privatePtr) -static void check_texmat( GLcontext *ctx, struct gl_pipeline_stage *stage ) +static void check_texmat( GLcontext *ctx, struct tnl_pipeline_stage *stage ) { GLuint i; stage->active = 0; @@ -62,7 +62,7 @@ static void check_texmat( GLcontext *ctx, struct gl_pipeline_stage *stage ) for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) if (ctx->Texture._TexMatEnabled & ENABLE_TEXMAT(i)) - flags |= VERT_BIT_TEX(i); + flags |= _TNL_BIT_TEX(i); stage->active = 1; stage->inputs = flags; @@ -71,7 +71,7 @@ static void check_texmat( GLcontext *ctx, struct gl_pipeline_stage *stage ) } static GLboolean run_texmat_stage( GLcontext *ctx, - struct gl_pipeline_stage *stage ) + struct tnl_pipeline_stage *stage ) { struct texmat_stage_data *store = TEXMAT_STAGE_DATA(stage); struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; @@ -82,7 +82,7 @@ static GLboolean run_texmat_stage( GLcontext *ctx, */ for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) if (ctx->Texture._TexMatEnabled & ENABLE_TEXMAT(i)) { - if (stage->changed_inputs & VERT_BIT_TEX(i)) + if (stage->changed_inputs & _TNL_BIT_TEX(i)) (void) TransformRaw( &store->texcoord[i], ctx->TextureMatrixStack[i].Top, VB->TexCoordPtr[i]); @@ -96,7 +96,7 @@ static GLboolean run_texmat_stage( GLcontext *ctx, /* Called the first time stage->run() is invoked. */ static GLboolean alloc_texmat_data( GLcontext *ctx, - struct gl_pipeline_stage *stage ) + struct tnl_pipeline_stage *stage ) { struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; struct texmat_stage_data *store; @@ -117,7 +117,7 @@ static GLboolean alloc_texmat_data( GLcontext *ctx, } -static void free_texmat_data( struct gl_pipeline_stage *stage ) +static void free_texmat_data( struct tnl_pipeline_stage *stage ) { struct texmat_stage_data *store = TEXMAT_STAGE_DATA(stage); GLuint i; @@ -133,7 +133,7 @@ static void free_texmat_data( struct gl_pipeline_stage *stage ) -const struct gl_pipeline_stage _tnl_texture_transform_stage = +const struct tnl_pipeline_stage _tnl_texture_transform_stage = { "texture transform", /* name */ _NEW_TEXTURE|_NEW_TEXTURE_MATRIX, /* check_state */ diff --git a/src/mesa/tnl/t_vb_vertex.c b/src/mesa/tnl/t_vb_vertex.c index 25453933a12..63dc653245d 100644 --- a/src/mesa/tnl/t_vb_vertex.c +++ b/src/mesa/tnl/t_vb_vertex.c @@ -129,7 +129,7 @@ static void (*(usercliptab[5]))( GLcontext *, static GLboolean run_vertex_stage( GLcontext *ctx, - struct gl_pipeline_stage *stage ) + struct tnl_pipeline_stage *stage ) { struct vertex_stage_data *store = (struct vertex_stage_data *)stage->privatePtr; TNLcontext *tnl = TNL_CONTEXT(ctx); @@ -149,36 +149,23 @@ static GLboolean run_vertex_stage( GLcontext *ctx, VB->EyePtr = TransformRaw( &store->eye, ctx->ModelviewMatrixStack.Top, VB->ObjPtr); - - if (ctx->ProjectionMatrixStack.Top->type == MATRIX_IDENTITY) - VB->ClipPtr = VB->EyePtr; - else - VB->ClipPtr = TransformRaw( &store->clip, - &ctx->_ModelProjectMatrix, - VB->ObjPtr ); - } - else { - /* Combined modelviewproject transform: - */ - if (ctx->_ModelProjectMatrix.type == MATRIX_IDENTITY) - VB->ClipPtr = VB->ObjPtr; - else - VB->ClipPtr = TransformRaw( &store->clip, - &ctx->_ModelProjectMatrix, - VB->ObjPtr ); } + VB->ClipPtr = TransformRaw( &store->clip, + &ctx->_ModelProjectMatrix, + VB->ObjPtr ); + /* Drivers expect this to be clean to element 4... */ - if (VB->ClipPtr->size < 4) { - if (VB->ClipPtr->flags & VEC_NOT_WRITEABLE) { - ASSERT(VB->ClipPtr == VB->ObjPtr); - VB->import_data( ctx, VERT_BIT_POS, VEC_NOT_WRITEABLE ); - VB->ClipPtr = VB->ObjPtr; - } - if (VB->ClipPtr->size == 2) - _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 2 ); + switch (VB->ClipPtr->size) { + case 1: + /* impossible */ + case 2: + _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 2 ); + case 3: _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 3 ); + case 4: + break; } /* Cliptest and perspective divide. Clip functions must clear @@ -225,9 +212,6 @@ static GLboolean run_vertex_stage( GLcontext *ctx, VB->ClipOrMask = store->ormask; VB->ClipMask = store->clipmask; - if (VB->ClipPtr == VB->ObjPtr && (VB->importable_data & VERT_BIT_POS)) - VB->importable_data |= VERT_BIT_CLIP; - store->save_eyeptr = VB->EyePtr; store->save_clipptr = VB->ClipPtr; store->save_ndcptr = VB->NdcPtr; @@ -240,8 +224,6 @@ static GLboolean run_vertex_stage( GLcontext *ctx, VB->NdcPtr = store->save_ndcptr; VB->ClipMask = store->clipmask; VB->ClipOrMask = store->ormask; - if (VB->ClipPtr == VB->ObjPtr && (VB->importable_data & VERT_BIT_POS)) - VB->importable_data |= VERT_BIT_CLIP; if (store->andmask) return GL_FALSE; } @@ -250,13 +232,13 @@ static GLboolean run_vertex_stage( GLcontext *ctx, } -static void check_vertex( GLcontext *ctx, struct gl_pipeline_stage *stage ) +static void check_vertex( GLcontext *ctx, struct tnl_pipeline_stage *stage ) { stage->active = !ctx->VertexProgram.Enabled; } static GLboolean init_vertex_stage( GLcontext *ctx, - struct gl_pipeline_stage *stage ) + struct tnl_pipeline_stage *stage ) { struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; struct vertex_stage_data *store; @@ -285,7 +267,7 @@ static GLboolean init_vertex_stage( GLcontext *ctx, return stage->run( ctx, stage ); } -static void dtr( struct gl_pipeline_stage *stage ) +static void dtr( struct tnl_pipeline_stage *stage ) { struct vertex_stage_data *store = VERTEX_STAGE_DATA(stage); @@ -301,7 +283,7 @@ static void dtr( struct gl_pipeline_stage *stage ) } -const struct gl_pipeline_stage _tnl_vertex_transform_stage = +const struct tnl_pipeline_stage _tnl_vertex_transform_stage = { "modelview/project/cliptest/divide", _NEW_PROGRAM, /* check_state: only care about vertex prog */ @@ -311,8 +293,8 @@ const struct gl_pipeline_stage _tnl_vertex_transform_stage = _NEW_PROGRAM| _NEW_TRANSFORM, GL_TRUE, /* active */ - VERT_BIT_POS, /* inputs */ - VERT_BIT_EYE|VERT_BIT_CLIP, /* outputs */ + _TNL_BIT_POS, /* inputs */ + _TNL_BIT_POS, /* outputs */ 0, /* changed_inputs */ NULL, /* private data */ dtr, /* destructor */ diff --git a/src/mesa/tnl/t_vtx_api.c b/src/mesa/tnl/t_vtx_api.c index d734b67dbd8..21ec1c9a7b2 100644 --- a/src/mesa/tnl/t_vtx_api.c +++ b/src/mesa/tnl/t_vtx_api.c @@ -30,19 +30,303 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. * Authors: * Keith Whitwell */ -#include "mtypes.h" + #include "context.h" -#include "colormac.h" -#include "simple_list.h" +#include "macros.h" +#include "vtxfmt.h" +#include "dlist.h" +#include "state.h" +#include "light.h" #include "api_arrayelt.h" - -#include "t_context.h" +#include "api_noop.h" #include "t_vtx_api.h" +static void init_attrfv( TNLcontext *tnl ); + + +/* Close off the last primitive, execute the buffer, restart the + * primitive. + */ +static void _tnl_wrap_buffers( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + + if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) { + GLint i = tnl->vtx.prim_count - 1; + assert(i >= 0); + tnl->vtx.prim[i].count = ((tnl->vtx.initial_counter - tnl->vtx.counter) - + tnl->vtx.prim[i].start); + } + + /* Execute the buffer and save copied vertices. + */ + _tnl_flush_vtx( ctx ); + + /* Emit a glBegin to start the new list. + */ + assert(tnl->vtx.prim_count == 0); + + if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) { + tnl->vtx.prim[0].mode = ctx->Driver.CurrentExecPrimitive; + tnl->vtx.prim[0].start = 0; + tnl->vtx.prim[0].count = 0; + tnl->vtx.prim_count++; + } +} + + +static void _tnl_wrap_filled_vertex( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLfloat *data = tnl->vtx.copied.buffer; + int i; + + /* Run pipeline on current vertices, copy wrapped vertices + * to tnl->copied. + */ + _tnl_wrap_buffers( ctx ); + + /* Copy stored stored vertices to start of new list. + */ + assert(tnl->vtx.counter > tnl->vtx.copied.nr); + + for (i = 0 ; i < tnl->vtx.copied.nr ; i++) { + memcpy( tnl->vtx.vbptr, data, tnl->vtx.vertex_size * sizeof(GLfloat)); + tnl->vtx.vbptr += tnl->vtx.vertex_size; + data += tnl->vtx.vertex_size; + tnl->vtx.counter--; + } + + tnl->vtx.copied.nr = 0; +} + +static void _tnl_copy_to_current( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint i; + + for (i = _TNL_ATTRIB_POS+1 ; i <= _TNL_ATTRIB_INDEX ; i++) + if (tnl->vtx.attrsz[i]) { + ASSIGN_4V( tnl->vtx.current[i], 0, 0, 0, 1 ); + COPY_SZ_4V(tnl->vtx.current[i], + tnl->vtx.attrsz[i], + tnl->vtx.attrptr[i]); + } + + /* Edgeflag requires special treatment: + */ + if (tnl->vtx.attrsz[_TNL_ATTRIB_EDGEFLAG]) + ctx->Current.EdgeFlag = + (tnl->vtx.attrptr[_TNL_ATTRIB_EDGEFLAG][0] == 1.0); + + + /* Colormaterial -- this kindof sucks. + */ + if (ctx->Light.ColorMaterialEnabled) { + _mesa_update_color_material(ctx, ctx->Current.Attrib[VERT_ATTRIB_COLOR0]); + } + + ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT; +} + + +static void _tnl_copy_from_current( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLint i; + + for (i = _TNL_ATTRIB_POS+1 ; i <= _TNL_ATTRIB_INDEX ; i++) + switch (tnl->vtx.attrsz[i]) { + case 4: tnl->vtx.attrptr[i][3] = tnl->vtx.current[i][3]; + case 3: tnl->vtx.attrptr[i][2] = tnl->vtx.current[i][2]; + case 2: tnl->vtx.attrptr[i][1] = tnl->vtx.current[i][1]; + case 1: tnl->vtx.attrptr[i][0] = tnl->vtx.current[i][0]; + break; + } + + /* Edgeflag requires special treatment: + */ + if (tnl->vtx.attrsz[_TNL_ATTRIB_EDGEFLAG]) + tnl->vtx.attrptr[_TNL_ATTRIB_EDGEFLAG][0] = + (GLfloat)ctx->Current.EdgeFlag; + + + ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; +} + + + + + +/* Flush existing data, set new attrib size, replay copied vertices. + */ +static void _tnl_wrap_upgrade_vertex( GLcontext *ctx, + GLuint attr, + GLuint newsz ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint oldsz; + GLint i; + GLfloat *tmp; + GLint lastcount = tnl->vtx.initial_counter - tnl->vtx.counter; + + + /* Run pipeline on current vertices, copy wrapped vertices + * to tnl->vtx.copied. + */ + _tnl_wrap_buffers( ctx ); + + /* Do a COPY_TO_CURRENT to ensure back-copying works for the case + * when the attribute already exists in the vertex and is having + * its size increased. + */ + _tnl_copy_to_current( ctx ); + + + /* Heuristic: Attempt to isolate attributes received outside + * begin/end so that they don't bloat the vertices. + */ +#if 1 + if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END && + tnl->vtx.attrsz[attr] == 0 + && lastcount > 8 + ) { + init_attrfv( tnl ); + } +#endif + + + /* Fix up sizes: + */ + oldsz = tnl->vtx.attrsz[attr]; + tnl->vtx.attrsz[attr] = newsz; + + tnl->vtx.vertex_size += newsz - oldsz; + tnl->vtx.counter = MIN2( VERT_BUFFER_SIZE / tnl->vtx.vertex_size, + ctx->Const.MaxArrayLockSize ); + tnl->vtx.initial_counter = tnl->vtx.counter; + tnl->vtx.vbptr = tnl->vtx.buffer; + + + /* Recalculate all the attrptr[] values + */ + for (i = 0, tmp = tnl->vtx.vertex ; i < _TNL_ATTRIB_MAX ; i++) { + if (tnl->vtx.attrsz[i]) { + tnl->vtx.attrptr[i] = tmp; + tmp += tnl->vtx.attrsz[i]; + } + else + tnl->vtx.attrptr[i] = 0; /* will not be dereferenced */ + } + + /* Copy from current to repopulate the vertex with correct values. + */ + _tnl_copy_from_current( ctx ); + + /* Replay stored vertices to translate them + * to new format here. + * + * -- No need to replay - just copy piecewise + */ + if (tnl->vtx.copied.nr) + { + GLfloat *data = tnl->vtx.copied.buffer; + GLfloat *dest = tnl->vtx.buffer; + GLuint j; + + for (i = 0 ; i < tnl->vtx.copied.nr ; i++) { + for (j = 0 ; j < _TNL_ATTRIB_MAX ; j++) { + if (tnl->vtx.attrsz[j]) { + if (j == attr) { + COPY_SZ_4V( dest, newsz, tnl->vtx.current[j] ); + COPY_SZ_4V( dest, oldsz, data ); + data += oldsz; + dest += newsz; + } + else { + GLuint sz = tnl->vtx.attrsz[j]; + COPY_SZ_4V( dest, sz, data ); + dest += sz; + data += sz; + } + } + } + } + + tnl->vtx.vbptr = dest; + tnl->vtx.counter -= tnl->vtx.copied.nr; + tnl->vtx.copied.nr = 0; + } +} + + +static void _tnl_fixup_vertex( GLcontext *ctx, GLuint attr, GLuint sz ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + static float id[4] = { 0, 0, 0, 1 }; + int i; + + if (tnl->vtx.attrsz[attr] < sz) { + /* New size is larger. Need to flush existing vertices and get + * an enlarged vertex format. + */ + _tnl_wrap_upgrade_vertex( ctx, attr, sz ); + } + else if (tnl->vtx.attrsz[attr] > sz) { + /* New size is smaller - just need to fill in some + * zeros. Don't need to flush or wrap. + */ + for (i = sz ; i <= tnl->vtx.attrsz[attr] ; i++) + tnl->vtx.attrptr[attr][i-1] = id[i-1]; + } +} + + + + +/* Helper function for 'CHOOSE' macro. Do what's necessary when an + * entrypoint is called for the first time. + */ +static void do_choose( GLuint attr, GLuint sz, + void (*fallback_attr_func)( const GLfloat *), + void (*choose1)( const GLfloat *), + void (*choose2)( const GLfloat *), + void (*choose3)( const GLfloat *), + void (*choose4)( const GLfloat *), + const GLfloat *v ) +{ + GET_CURRENT_CONTEXT( ctx ); + TNLcontext *tnl = TNL_CONTEXT(ctx); + + if (tnl->vtx.attrsz[attr] != sz) + _tnl_fixup_vertex( ctx, attr, sz ); + + /* Does this belong here? Necessitates resetting vtxfmt on each + * flush (otherwise flags won't get reset afterwards). + */ + if (attr == 0) + ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; + else + ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; + + /* Reset any active pointers for this attribute + */ + tnl->vtx.tabfv[attr][0] = choose1; + tnl->vtx.tabfv[attr][1] = choose2; + tnl->vtx.tabfv[attr][2] = choose3; + tnl->vtx.tabfv[attr][3] = choose4; + + /* Update the secondary dispatch table with the new function + */ + tnl->vtx.tabfv[attr][sz-1] = fallback_attr_func; + + (*fallback_attr_func)(v); +} + + /* Versions of all the entrypoints for situations where codegen isn't - * available. This is slowed significantly by all the gumph necessary - * to get to the tnl pointer, which can be avoided with codegen. + * available. * * Note: Only one size for each attribute may be active at once. * Eg. if Color3f is installed/active, then Color4f may not be, even @@ -51,7 +335,10 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. * is the job of the chooser function when switching between Color4f * and Color3f. */ -#define ATTRF( ATTR, N, A, B, C, D ) \ +#define ATTRFV( ATTR, N ) \ +static void choose_##ATTR##_##N( const GLfloat *v ); \ + \ +static void attrib_##ATTR##_##N( const GLfloat *v ) \ { \ GET_CURRENT_CONTEXT( ctx ); \ TNLcontext *tnl = TNL_CONTEXT(ctx); \ @@ -59,75 +346,61 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. if ((ATTR) == 0) { \ int i; \ \ - if (N>0) tnl->vtx.vbptr[0].f = A; \ - if (N>1) tnl->vtx.vbptr[1].f = B; \ - if (N>2) tnl->vtx.vbptr[2].f = C; \ - if (N>3) tnl->vtx.vbptr[3].f = D; \ + if (N>0) tnl->vtx.vbptr[0] = v[0]; \ + if (N>1) tnl->vtx.vbptr[1] = v[1]; \ + if (N>2) tnl->vtx.vbptr[2] = v[2]; \ + if (N>3) tnl->vtx.vbptr[3] = v[3]; \ \ for (i = N; i < tnl->vtx.vertex_size; i++) \ - tnl->vtx.vbptr[i].ui = tnl->vtx.vertex[i].ui; \ + tnl->vtx.vbptr[i] = tnl->vtx.vertex[i]; \ \ tnl->vtx.vbptr += tnl->vtx.vertex_size; \ \ if (--tnl->vtx.counter == 0) \ - _tnl_FlushVertices( ctx, FLUSH_STORED_VERTICES ); \ + _tnl_wrap_filled_vertex( ctx ); \ } \ else { \ - union uif *dest = tnl->vtx.attrptr[ATTR]; \ - if (N>0) dest[0].f = A; \ - if (N>1) dest[1].f = B; \ - if (N>2) dest[2].f = C; \ - if (N>3) dest[3].f = D; \ + GLfloat *dest = tnl->vtx.attrptr[ATTR]; \ + if (N>0) dest[0] = v[0]; \ + if (N>1) dest[1] = v[1]; \ + if (N>2) dest[2] = v[2]; \ + if (N>3) dest[3] = v[3]; \ } \ } -#define ATTR4F( ATTR, A, B, C, D ) ATTRF( ATTR, 4, A, B, C, D ) -#define ATTR3F( ATTR, A, B, C ) ATTRF( ATTR, 3, A, B, C, 1 ) -#define ATTR2F( ATTR, A, B ) ATTRF( ATTR, 2, A, B, 0, 1 ) -#define ATTR1F( ATTR, A ) ATTRF( ATTR, 1, A, 0, 0, 1 ) - -#define ATTRS( ATTRIB ) \ -static void attrib_##ATTRIB##_1_0( GLfloat s ) \ -{ \ - ATTR1F( ATTRIB, s ); \ -} \ - \ -static void attrib_##ATTRIB##_1_1( const GLfloat *v ) \ -{ \ - ATTR1F( ATTRIB, v[0] ); \ -} \ - \ -static void attrib_##ATTRIB##_2_0( GLfloat s, GLfloat t ) \ -{ \ - ATTR2F( ATTRIB, s, t ); \ -} \ - \ -static void attrib_##ATTRIB##_2_1( const GLfloat *v ) \ -{ \ - ATTR2F( ATTRIB, v[0], v[1] ); \ -} \ - \ -static void attrib_##ATTRIB##_3_0( GLfloat s, GLfloat t, \ - GLfloat r ) \ -{ \ - ATTR3F( ATTRIB, s, t, r ); \ -} \ - \ -static void attrib_##ATTRIB##_3_1( const GLfloat *v ) \ -{ \ - ATTR3F( ATTRIB, v[0], v[1], v[2] ); \ -} \ - \ -static void attrib_##ATTRIB##_4_0( GLfloat s, GLfloat t, \ - GLfloat r, GLfloat q ) \ -{ \ - ATTR4F( ATTRIB, s, t, r, q ); \ -} \ - \ -static void attrib_##ATTRIB##_4_1( const GLfloat *v ) \ -{ \ - ATTR4F( ATTRIB, v[0], v[1], v[2], v[3] ); \ +#define CHOOSE( ATTR, N ) \ +static void choose_##ATTR##_##N( const GLfloat *v ) \ +{ \ + do_choose(ATTR, N, \ + attrib_##ATTR##_##N, \ + choose_##ATTR##_1, \ + choose_##ATTR##_2, \ + choose_##ATTR##_3, \ + choose_##ATTR##_4, \ + v ); \ +} + +#define INIT(ATTR) \ +static void init_##ATTR( TNLcontext *tnl ) \ +{ \ + tnl->vtx.tabfv[ATTR][0] = choose_##ATTR##_1; \ + tnl->vtx.tabfv[ATTR][1] = choose_##ATTR##_2; \ + tnl->vtx.tabfv[ATTR][2] = choose_##ATTR##_3; \ + tnl->vtx.tabfv[ATTR][3] = choose_##ATTR##_4; \ } + + +#define ATTRS( ATTRIB ) \ + ATTRFV( ATTRIB, 1 ) \ + ATTRFV( ATTRIB, 2 ) \ + ATTRFV( ATTRIB, 3 ) \ + ATTRFV( ATTRIB, 4 ) \ + CHOOSE( ATTRIB, 1 ) \ + CHOOSE( ATTRIB, 2 ) \ + CHOOSE( ATTRIB, 3 ) \ + CHOOSE( ATTRIB, 4 ) \ + INIT( ATTRIB ) \ + /* Generate a lot of functions. These are the actual worker * functions, which are equivalent to those generated via codegen @@ -150,214 +423,46 @@ ATTRS( 13 ) ATTRS( 14 ) ATTRS( 15 ) -/* Flush existing data, set new attrib size, replay copied vertices. - */ -static void _tnl_upgrade_vertex( GLcontext *ctx, - GLuint attr, - GLuint newsz ) +static void init_attrfv( TNLcontext *tnl ) { - GLuint oldsz = tnl->vtx.attrib[attr].sz; - - _tnl_flush_immediate( ctx ); - - tnl->vtx.attrib[attr].sz = newsz; - /* What else to do here? - */ - - /* Replay stored vertices to translate them to new format: Use - * bitmap and ffs() to speed inner loop: - */ - for (i = 0 ; i < tnl->copied_verts.nr ; i++) { - GLfloat *data = old_data + tnl->copied_verts.offset[i]; - - for (j = 1 ; j < MAX_ATTRIB ; j++) { - if (tnl->vtx.attrib[j].sz) { - if (j == attr) { - GLfloat tmp[4]; - COPY_4FV( tmp, id ); - COPY_SZ_4V( tmp, oldsz, data ); - data += oldsz; - tnl->vtx.attrib[attr].fv( tmp ); - } - else { - GLfloat *tmp = data; - data += tnl->vtx.attrib[j].sz; - tnl->vtx.attrib[j].fv( tmp ); - } - } - } - } -} - -static void _tnl_wrap_buffers( GLcontext *ctx ) -{ - _tnl_flush_immediate( ctx ); - - /* Replay stored vertices - don't really need to do this, memcpy - * would be fine. - */ - for (i = 0 ; i < tnl->copied_verts.nr ; i++) { - for (j = 1 ; j < MAX_ATTRIB ; j++) { - GLfloat *tmp = data; - data += tnl->vtx.attrib[j].sz; - tnl->vtx.attrib[j].fv( tmp ); - } - } -} - - - -/* The functions defined below (CHOOSERS) are the initial state for - * dispatch entries for all entrypoints except those requiring - * double-dispatch (multitexcoord, material, vertexattrib). - * - * These may provoke a vertex-upgrade where the existing vertex buffer - * is flushed and a new element is added to the active vertex layout. - * This can happen between begin/end pairs. - */ - -/* An active attribute has changed size. - */ -static void _tnl_fixup_vertex( GLcontext *ctx, GLuint attr, GLuint sz ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - - if (tnl->vtx.attrib_sz[attr] < sz) { - /* New size is larger. Need to flush existing vertices and get - * an enlarged vertex format. - */ - _tnl_upgrade_vertex( tnl, attr, sz ); - } - else { - static float id[4] = { 0, 0, 0, 1 }; - int i; - - /* New size is smaller - just need to fill in some zeros. - */ - for (i = sz ; i < tnl->vtx.attrib_sz[attr] ; i++) - tnl->vtx.attrptr[attr][i].f = id[i]; - } + if (0) fprintf(stderr, "%s %d\n", __FUNCTION__, tnl->vtx.vertex_size); - /* Reset the dispatch table - aliasing entrypoints are invalidated. - */ - _tnl_reset_attr_dispatch_tab( ctx ); -} - -static int dispatch_offset[TNL_ATTRIB_MAX][4][2]; - - -static void *lookup_or_generate( GLuint attr, GLuint sz, GLuint v, - void *fallback_attr_func ) -{ - GET_CURRENT_CONTEXT( ctx ); - TNLcontext *tnl = TNL_CONTEXT(ctx); - void *ptr = 0; - struct dynfn *dfn; - int key; - - /* This will remove any installed handlers for attr with different - * sz, will flush, copy and expand the copied vertices if sz won't - * fit in the current vertex, or will clean the current vertex if - * it already has this attribute in a larger size. - */ - if (tnl->vtx.attrib_sz[attr] != sz) - _tnl_fixup_vertex( ctx, attr, sz ); - - - if (attr == 0) - key = tnl->vtx.vertex_size; - else - key = (GLuint)tnl->vtx.attrptr[attr]; - - for (dfn = tnl->vtx.generated[sz-1][v][isvertex]; dfn; dfn = dfn->next) { - if (dfn->key == key) { - ptr = dfn->code; - break; - } - } - - if (ptr == 0) { - dfn = tnl->vtx.codegen[sz-1][v][isvertex]( ctx, key ); - if (dfn) { - ptr = dfn->code; - dfn->next = tnl->vtx.generated[sz-1][v][isvertex]; - tnl->vtx.generated[sz-1][v][isvertex] = dfn; - } - } + if (tnl->vtx.vertex_size) { + GLuint i; - if (ptr == 0) - ptr = fallback_attr_func; - - ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; - - /* Need to set all the aliases to this function, too - */ - if (dispatch_offset[attr][sz-1][v]) - ((void **)tnl->Exec)[dispatch_offset[attr][sz-1][v]] = ptr; - - return ptr; + init_0( tnl ); + init_1( tnl ); + init_2( tnl ); + init_3( tnl ); + init_4( tnl ); + init_5( tnl ); + init_6( tnl ); + init_7( tnl ); + init_8( tnl ); + init_9( tnl ); + init_10( tnl ); + init_11( tnl ); + init_12( tnl ); + init_13( tnl ); + init_14( tnl ); + init_15( tnl ); + + for (i = 0 ; i < _TNL_ATTRIB_MAX ; i++) + tnl->vtx.attrsz[i] = 0; + + tnl->vtx.vertex_size = 0; + } } - -/* These functions choose one of the ATTR's generated above (or from - * codegen). Like the ATTR functions, they live in the GL dispatch - * table and in the second-level dispatch table for MultiTexCoord, - * AttribNV, etc. - * - * Need ATTR1 for use in constructing name of 'attrib_x_y_z' function. - */ -#define CHOOSE( ATTR1, ATTR2, SZ, V, FNTYPE, ARGS1, ARGS2 ) \ -static void choose_##ATTR2##_##SZ##_##V ARGS1 \ -{ \ - void *ptr = lookup_or_generate(ATTR1, SZ, V, \ - (void *)attrib_##ATTR1##_##SZ##_##V ); \ - \ - assert(ATTR1 == ATTR2); \ - ((FNTYPE) ptr) ARGS2; \ -} - -#define afv (const GLfloat *v) -#define a1f (GLfloat a) -#define a2f (GLfloat a, GLfloat b) -#define a3f (GLfloat a, GLfloat b, GLfloat c) -#define a4f (GLfloat a, GLfloat b, GLfloat c, GLfloat d) - -/* Not that many entrypoints when it all boils down: - */ -CHOOSE( 0, VERT_ATTRIB_POS, 2, 1, pfv, afv, (v) ) -CHOOSE( 0, VERT_ATTRIB_POS, 2, 0, p2f, a2f, (a,b) ) -CHOOSE( 0, VERT_ATTRIB_POS, 3, 1, pfv, afv, (v) ) -CHOOSE( 0, VERT_ATTRIB_POS, 3, 0, p3f, a3f, (a,b,c) ) -CHOOSE( 0, VERT_ATTRIB_POS, 4, 1, pfv, afv, (v) ) -CHOOSE( 0, VERT_ATTRIB_POS, 4, 0, p4f, a4f, (a,b,c,d) ) -CHOOSE( 2, VERT_ATTRIB_NORMAL, 3, 1, pfv, afv, (v) ) -CHOOSE( 2, VERT_ATTRIB_NORMAL, 3, 0, p3f, a3f, (a,b,c) ) -CHOOSE( 3, VERT_ATTRIB_COLOR0, 3, 1, pfv, afv, (v) ) -CHOOSE( 3, VERT_ATTRIB_COLOR0, 3, 0, p3f, a3f, (a,b,c) ) -CHOOSE( 3, VERT_ATTRIB_COLOR0, 4, 1, pfv, afv, (v) ) -CHOOSE( 3, VERT_ATTRIB_COLOR0, 4, 0, p4f, a4f, (a,b,c,d) ) -CHOOSE( 4, VERT_ATTRIB_COLOR1, 3, 1, pfv, afv, (v) ) -CHOOSE( 4, VERT_ATTRIB_COLOR1, 3, 0, p3f, a3f, (a,b,c) ) -CHOOSE( 5, VERT_ATTRIB_FOG, 1, 1, pfv, afv, (v) ) -CHOOSE( 5, VERT_ATTRIB_FOG, 1, 0, p1f, a1f, (a) ) -CHOOSE( 8, VERT_ATTRIB_TEX0, 1, 1, pfv, afv, (v) ) -CHOOSE( 8, VERT_ATTRIB_TEX0, 1, 0, p1f, a1f, (a) ) -CHOOSE( 8, VERT_ATTRIB_TEX0, 2, 1, pfv, afv, (v) ) -CHOOSE( 8, VERT_ATTRIB_TEX0, 2, 0, p2f, a2f, (a,b) ) -CHOOSE( 8, VERT_ATTRIB_TEX0, 3, 1, pfv, afv, (v) ) -CHOOSE( 8, VERT_ATTRIB_TEX0, 3, 0, p3f, a3f, (a,b,c) ) -CHOOSE( 8, VERT_ATTRIB_TEX0, 4, 1, pfv, afv, (v) ) -CHOOSE( 8, VERT_ATTRIB_TEX0, 4, 0, p4f, a4f, (a,b,c,d) ) - - -/* Gack. Need to do this without going through the - * GET_CURRENT_CONTEXT hoohah. Could codegen this, I suppose... +/* These can be made efficient with codegen. Further, by adding more + * logic to do_choose(), the double-dispatch for legacy entrypoints + * like glVertex3f() can be removed. */ #define DISPATCH_ATTRFV( ATTR, COUNT, P ) \ do { \ GET_CURRENT_CONTEXT( ctx ); \ TNLcontext *tnl = TNL_CONTEXT(ctx); \ - tnl->vtx.tabfv[COUNT-1][ATTR]( P ); \ + tnl->vtx.tabfv[ATTR][COUNT-1]( P ); \ } while (0) #define DISPATCH_ATTR1FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 1, V ) @@ -366,15 +471,7 @@ do { \ #define DISPATCH_ATTR4FV( ATTR, V ) DISPATCH_ATTRFV( ATTR, 4, V ) #define DISPATCH_ATTR1F( ATTR, S ) DISPATCH_ATTRFV( ATTR, 1, &(S) ) -#ifdef USE_X86_ASM -/* Naughty cheat: - */ -#define DISPATCH_ATTR2F( ATTR, S,T ) DISPATCH_ATTRFV( ATTR, 2, &(S) ) -#define DISPATCH_ATTR3F( ATTR, S,T,R ) DISPATCH_ATTRFV( ATTR, 3, &(S) ) -#define DISPATCH_ATTR4F( ATTR, S,T,R,Q ) DISPATCH_ATTRFV( ATTR, 4, &(S) ) -#else -/* Safe: - */ + #define DISPATCH_ATTR2F( ATTR, S,T ) \ do { \ GLfloat v[2]; \ @@ -393,8 +490,6 @@ do { \ v[0] = S; v[1] = T; v[2] = R; v[3] = Q; \ DISPATCH_ATTR4FV( ATTR, v ); \ } while (0) -#endif - static void enum_error( void ) @@ -403,136 +498,237 @@ static void enum_error( void ) _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ ); } -static void op_error( void ) +static void _tnl_Vertex2f( GLfloat x, GLfloat y ) { - GET_CURRENT_CONTEXT( ctx ); - _mesa_error( ctx, GL_INVALID_OPERATION, __FUNCTION__ ); + DISPATCH_ATTR2F( _TNL_ATTRIB_POS, x, y ); } +static void _tnl_Vertex2fv( const GLfloat *v ) +{ + DISPATCH_ATTR2FV( _TNL_ATTRIB_POS, v ); +} -/* First level for MultiTexcoord: Send through second level dispatch. - * These are permanently installed in the toplevel dispatch. - * - * Assembly can optimize the generation of arrays by using &s instead - * of building 'v'. - */ -static void _tnl_MultiTexCoord1f( GLenum target, GLfloat s ) +static void _tnl_Vertex3f( GLfloat x, GLfloat y, GLfloat z ) +{ + DISPATCH_ATTR3F( _TNL_ATTRIB_POS, x, y, z ); +} + +static void _tnl_Vertex3fv( const GLfloat *v ) +{ + DISPATCH_ATTR3FV( _TNL_ATTRIB_POS, v ); +} + +static void _tnl_Vertex4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + DISPATCH_ATTR4F( _TNL_ATTRIB_POS, x, y, z, w ); +} + +static void _tnl_Vertex4fv( const GLfloat *v ) +{ + DISPATCH_ATTR4FV( _TNL_ATTRIB_POS, v ); +} + +static void _tnl_TexCoord1f( GLfloat x ) +{ + DISPATCH_ATTR1F( _TNL_ATTRIB_TEX0, x ); +} + +static void _tnl_TexCoord1fv( const GLfloat *v ) +{ + DISPATCH_ATTR1FV( _TNL_ATTRIB_TEX0, v ); +} + +static void _tnl_TexCoord2f( GLfloat x, GLfloat y ) +{ + DISPATCH_ATTR2F( _TNL_ATTRIB_TEX0, x, y ); +} + +static void _tnl_TexCoord2fv( const GLfloat *v ) +{ + DISPATCH_ATTR2FV( _TNL_ATTRIB_TEX0, v ); +} + +static void _tnl_TexCoord3f( GLfloat x, GLfloat y, GLfloat z ) +{ + DISPATCH_ATTR3F( _TNL_ATTRIB_TEX0, x, y, z ); +} + +static void _tnl_TexCoord3fv( const GLfloat *v ) { - GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; - DISPATCH_ATTR1FV( attr, &s ); + DISPATCH_ATTR3FV( _TNL_ATTRIB_TEX0, v ); +} + +static void _tnl_TexCoord4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + DISPATCH_ATTR4F( _TNL_ATTRIB_TEX0, x, y, z, w ); +} + +static void _tnl_TexCoord4fv( const GLfloat *v ) +{ + DISPATCH_ATTR4FV( _TNL_ATTRIB_TEX0, v ); +} + +static void _tnl_Normal3f( GLfloat x, GLfloat y, GLfloat z ) +{ + DISPATCH_ATTR3F( _TNL_ATTRIB_NORMAL, x, y, z ); +} + +static void _tnl_Normal3fv( const GLfloat *v ) +{ + DISPATCH_ATTR3FV( _TNL_ATTRIB_NORMAL, v ); +} + +static void _tnl_FogCoordfEXT( GLfloat x ) +{ + DISPATCH_ATTR1F( _TNL_ATTRIB_FOG, x ); +} + +static void _tnl_FogCoordfvEXT( const GLfloat *v ) +{ + DISPATCH_ATTR1FV( _TNL_ATTRIB_FOG, v ); +} + +static void _tnl_Color3f( GLfloat x, GLfloat y, GLfloat z ) +{ + DISPATCH_ATTR3F( _TNL_ATTRIB_COLOR0, x, y, z ); +} + +static void _tnl_Color3fv( const GLfloat *v ) +{ + DISPATCH_ATTR3FV( _TNL_ATTRIB_COLOR0, v ); +} + +static void _tnl_Color4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) +{ + DISPATCH_ATTR4F( _TNL_ATTRIB_COLOR0, x, y, z, w ); +} + +static void _tnl_Color4fv( const GLfloat *v ) +{ + DISPATCH_ATTR4FV( _TNL_ATTRIB_COLOR0, v ); +} + +static void _tnl_SecondaryColor3fEXT( GLfloat x, GLfloat y, GLfloat z ) +{ + DISPATCH_ATTR3F( _TNL_ATTRIB_COLOR1, x, y, z ); +} + +static void _tnl_SecondaryColor3fvEXT( const GLfloat *v ) +{ + DISPATCH_ATTR3FV( _TNL_ATTRIB_COLOR1, v ); +} + +static void _tnl_MultiTexCoord1f( GLenum target, GLfloat x ) +{ + GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0; + DISPATCH_ATTR1F( attr, x ); } static void _tnl_MultiTexCoord1fv( GLenum target, const GLfloat *v ) { - GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; + GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0; DISPATCH_ATTR1FV( attr, v ); } -static void _tnl_MultiTexCoord2f( GLenum target, GLfloat s, GLfloat t ) +static void _tnl_MultiTexCoord2f( GLenum target, GLfloat x, GLfloat y ) { - GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; - DISPATCH_ATTR2F( attr, s, t ); + GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0; + DISPATCH_ATTR2F( attr, x, y ); } static void _tnl_MultiTexCoord2fv( GLenum target, const GLfloat *v ) { - GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; + GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0; DISPATCH_ATTR2FV( attr, v ); } -static void _tnl_MultiTexCoord3f( GLenum target, GLfloat s, GLfloat t, - GLfloat r) +static void _tnl_MultiTexCoord3f( GLenum target, GLfloat x, GLfloat y, + GLfloat z) { - GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; - DISPATCH_ATTR3F( attr, s, t, r ); + GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0; + DISPATCH_ATTR3F( attr, x, y, z ); } static void _tnl_MultiTexCoord3fv( GLenum target, const GLfloat *v ) { - GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; + GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0; DISPATCH_ATTR3FV( attr, v ); } -static void _tnl_MultiTexCoord4f( GLenum target, GLfloat s, GLfloat t, - GLfloat r, GLfloat q ) +static void _tnl_MultiTexCoord4f( GLenum target, GLfloat x, GLfloat y, + GLfloat z, GLfloat w ) { - GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; - DISPATCH_ATTR4F( attr, s, t, r, q ); + GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0; + DISPATCH_ATTR4F( attr, x, y, z, w ); } static void _tnl_MultiTexCoord4fv( GLenum target, const GLfloat *v ) { - GLuint attr = (target & 0x7) + VERT_ATTRIB_TEX0; + GLuint attr = (target & 0x7) + _TNL_ATTRIB_TEX0; DISPATCH_ATTR4FV( attr, v ); } - -/* First level for NV_vertex_program: - * - * Check for errors & reroute through second dispatch layer to get - * size tracking per-attribute. - */ -static void _tnl_VertexAttrib1fNV( GLuint index, GLfloat s ) +static void _tnl_VertexAttrib1fNV( GLuint index, GLfloat x ) { - if (index < TNL_ATTRIB_MAX) - DISPATCH_ATTR1F( index, s ); + if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX) + DISPATCH_ATTR1F( index, x ); else enum_error(); } static void _tnl_VertexAttrib1fvNV( GLuint index, const GLfloat *v ) { - if (index < TNL_ATTRIB_MAX) + if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX) DISPATCH_ATTR1FV( index, v ); else enum_error(); } -static void _tnl_VertexAttrib2fNV( GLuint index, GLfloat s, GLfloat t ) +static void _tnl_VertexAttrib2fNV( GLuint index, GLfloat x, GLfloat y ) { - if (index < TNL_ATTRIB_MAX) - DISPATCH_ATTR2F( index, s, t ); + if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX) + DISPATCH_ATTR2F( index, x, y ); else enum_error(); } static void _tnl_VertexAttrib2fvNV( GLuint index, const GLfloat *v ) { - if (index < TNL_ATTRIB_MAX) + if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX) DISPATCH_ATTR2FV( index, v ); else enum_error(); } -static void _tnl_VertexAttrib3fNV( GLuint index, GLfloat s, GLfloat t, - GLfloat r ) +static void _tnl_VertexAttrib3fNV( GLuint index, GLfloat x, GLfloat y, + GLfloat z ) { - if (index < TNL_ATTRIB_MAX) - DISPATCH_ATTR3F( index, s, t, r ); + if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX) + DISPATCH_ATTR3F( index, x, y, z ); else enum_error(); } static void _tnl_VertexAttrib3fvNV( GLuint index, const GLfloat *v ) { - if (index < TNL_ATTRIB_MAX) + if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX) DISPATCH_ATTR3FV( index, v ); else enum_error(); } -static void _tnl_VertexAttrib4fNV( GLuint index, GLfloat s, GLfloat t, - GLfloat r, GLfloat q ) +static void _tnl_VertexAttrib4fNV( GLuint index, GLfloat x, GLfloat y, + GLfloat z, GLfloat w ) { - if (index < TNL_ATTRIB_MAX) - DISPATCH_ATTR4F( index, s, t, r, q ); + if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX) + DISPATCH_ATTR4F( index, x, y, z, w ); else enum_error(); } static void _tnl_VertexAttrib4fvNV( GLuint index, const GLfloat *v ) { - if (index < TNL_ATTRIB_MAX) + if (index >= VERT_ATTRIB_POS && index < VERT_ATTRIB_MAX) DISPATCH_ATTR4FV( index, v ); else enum_error(); @@ -549,19 +745,21 @@ static void _tnl_VertexAttrib4fvNV( GLuint index, const GLfloat *v ) * just to cope with this, so I unroll the 'C' varients of CHOOSE and * ATTRF into this function, and dispense with codegen and * second-level dispatch. + * + * There is no aliasing of material attributes with other entrypoints. */ #define MAT_ATTR( A, N, params ) \ do { \ - if (tnl->vtx.attrib_sz[A] != N) { \ - tnl_fixup_vertex( ctx, A, N ); \ + if (tnl->vtx.attrsz[A] != N) { \ + _tnl_fixup_vertex( ctx, A, N ); \ } \ \ { \ - union uif *dest = tnl->vtx.attrptr[A]; \ - if (N>0) dest[0].f = params[0]; \ - if (N>1) dest[1].f = params[1]; \ - if (N>2) dest[2].f = params[2]; \ - if (N>3) dest[3].f = params[3]; \ + GLfloat *dest = tnl->vtx.attrptr[A]; \ + if (N>0) dest[0] = params[0]; \ + if (N>1) dest[1] = params[1]; \ + if (N>2) dest[2] = params[2]; \ + if (N>3) dest[3] = params[3]; \ ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \ } \ } while (0) @@ -585,28 +783,39 @@ static void _tnl_Materialfv( GLenum face, GLenum pname, GET_CURRENT_CONTEXT( ctx ); TNLcontext *tnl = TNL_CONTEXT(ctx); + switch (face) { + case GL_FRONT: + case GL_BACK: + case GL_FRONT_AND_BACK: + break; + + default: + _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__); + return; + } + switch (pname) { case GL_EMISSION: - MAT( VERT_ATTRIB_MAT_FRONT_EMISSION, 4, face, params ); + MAT( _TNL_ATTRIB_MAT_FRONT_EMISSION, 4, face, params ); break; case GL_AMBIENT: - MAT( VERT_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params ); + MAT( _TNL_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params ); break; case GL_DIFFUSE: - MAT( VERT_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params ); + MAT( _TNL_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params ); break; case GL_SPECULAR: - MAT( VERT_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params ); + MAT( _TNL_ATTRIB_MAT_FRONT_SPECULAR, 4, face, params ); break; case GL_SHININESS: - MAT( VERT_ATTRIB_MAT_FRONT_SHININESS, 1, face, params ); + MAT( _TNL_ATTRIB_MAT_FRONT_SHININESS, 1, face, params ); break; case GL_COLOR_INDEXES: - MAT( VERT_ATTRIB_MAT_FRONT_INDEXES, 3, face, params ); + MAT( _TNL_ATTRIB_MAT_FRONT_INDEXES, 3, face, params ); break; case GL_AMBIENT_AND_DIFFUSE: - MAT( VERT_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params ); - MAT( VERT_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params ); + MAT( _TNL_ATTRIB_MAT_FRONT_AMBIENT, 4, face, params ); + MAT( _TNL_ATTRIB_MAT_FRONT_DIFFUSE, 4, face, params ); break; default: _mesa_error( ctx, GL_INVALID_ENUM, __FUNCTION__ ); @@ -620,248 +829,313 @@ do { \ GET_CURRENT_CONTEXT( ctx ); \ TNLcontext *tnl = TNL_CONTEXT(ctx); \ \ - if (tnl->vtx.attrib_sz[A] != 1) { \ - tnl_fixup_vertex( ctx, A, 1 ); \ + if (tnl->vtx.attrsz[A] != 1) { \ + _tnl_fixup_vertex( ctx, A, 1 ); \ } \ \ { \ - union uif *dest = tnl->vtx.attrptr[A]; \ - dest[0].ui = IDX; \ + GLfloat *dest = tnl->vtx.attrptr[A]; \ + dest[0] = IDX; \ ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \ } \ } while (0) -static void _tnl_EdgeFlag( GLboolean f ) +static void _tnl_EdgeFlag( GLboolean b ) { - IDX_ATTR( VERT_ATTRIB_EDGEFLAG, f ); + IDX_ATTR( _TNL_ATTRIB_EDGEFLAG, (GLfloat)b ); } -static void _tnl_EdgeFlagv( const GLboolean *f ) +static void _tnl_EdgeFlagv( const GLboolean *v ) { - IDX_ATTR( VERT_ATTRIB_EDGEFLAG, f[0] ); + IDX_ATTR( _TNL_ATTRIB_EDGEFLAG, (GLfloat)v[0] ); } -static void _tnl_Indexi( GLint i ) +static void _tnl_Indexf( GLfloat f ) { - IDX_ATTR( VERT_ATTRIB_INDEX, i ); + IDX_ATTR( _TNL_ATTRIB_INDEX, f ); } -static void _tnl_Indexiv( const GLint *i ) +static void _tnl_Indexfv( const GLfloat *v ) { - IDX_ATTR( VERT_ATTRIB_INDEX, i[0] ); + IDX_ATTR( _TNL_ATTRIB_INDEX, v[0] ); } - - -/* EvalCoord needs special treatment as ususal: +/* Eval */ -static void evalcoord( GLfloat a, GLfloat b, GLuint type ) +static void _tnl_EvalCoord1f( GLfloat u ) { -#if 0 - GET_CURRENT_CONTEXT( ctx ); - TNLcontext *tnl = TNL_CONTEXT(ctx); - - /* Initialize the list of eval fixups: - */ - if (!tnl->evalptr) { - init_eval_ptr( ctx ); + GET_CURRENT_CONTEXT( ctx ); + TNLcontext *tnl = TNL_CONTEXT(ctx); + + /* TODO: use a CHOOSE() function for this: */ + { + GLint i; + if (tnl->vtx.eval.new_state) + _tnl_update_eval( ctx ); + + for (i = 0 ; i <= _TNL_ATTRIB_INDEX ; i++) { + if (tnl->vtx.eval.map1[i].map) + if (tnl->vtx.attrsz[i] < tnl->vtx.eval.map1[i].sz) + _tnl_fixup_vertex( ctx, i, tnl->vtx.eval.map1[i].sz ); + } } - /* Note that this vertex will need to be fixed up: - */ - tnl->evalptr[0].vert = tnl->initial_counter - tnl->counter; - tnl->evalptr[0].type = type; - /* Now emit the vertex with eval data in obj coordinates: - */ - ATTRF( 0, 2, a, b, 0, 1 ); -#endif -} + memcpy( tnl->vtx.copied.buffer, tnl->vtx.vertex, + tnl->vtx.vertex_size * sizeof(GLfloat)); + _tnl_do_EvalCoord1f( ctx, u ); -static void _tnl_EvalCoord1f( GLfloat u ) -{ - evalcoord( u, 0, TNL_EVAL_COORD1 ); + memcpy( tnl->vtx.vertex, tnl->vtx.copied.buffer, + tnl->vtx.vertex_size * sizeof(GLfloat)); } -static void _tnl_EvalCoord1fv( const GLfloat *v ) +static void _tnl_EvalCoord2f( GLfloat u, GLfloat v ) { - evalcoord( v[0], 0, TNL_EVAL_COORD1 ); + GET_CURRENT_CONTEXT( ctx ); + TNLcontext *tnl = TNL_CONTEXT(ctx); + + /* TODO: use a CHOOSE() function for this: */ + { + GLint i; + if (tnl->vtx.eval.new_state) + _tnl_update_eval( ctx ); + + for (i = 0 ; i <= _TNL_ATTRIB_INDEX ; i++) { + if (tnl->vtx.eval.map2[i].map) + if (tnl->vtx.attrsz[i] < tnl->vtx.eval.map2[i].sz) + _tnl_fixup_vertex( ctx, i, tnl->vtx.eval.map2[i].sz ); + } + + if (ctx->Eval.AutoNormal) + if (tnl->vtx.attrsz[_TNL_ATTRIB_NORMAL] < 3) + _tnl_fixup_vertex( ctx, _TNL_ATTRIB_NORMAL, 3 ); + } + + memcpy( tnl->vtx.copied.buffer, tnl->vtx.vertex, + tnl->vtx.vertex_size * sizeof(GLfloat)); + + _tnl_do_EvalCoord2f( ctx, u, v ); + + memcpy( tnl->vtx.vertex, tnl->vtx.copied.buffer, + tnl->vtx.vertex_size * sizeof(GLfloat)); } -static void _tnl_EvalCoord2f( GLfloat u, GLfloat v ) +static void _tnl_EvalCoord1fv( const GLfloat *u ) { - evalcoord( u, v, TNL_EVAL_COORD2 ); + _tnl_EvalCoord1f( u[0] ); } -static void _tnl_EvalCoord2fv( const GLfloat *v ) +static void _tnl_EvalCoord2fv( const GLfloat *u ) { - evalcoord( v[0], v[1], TNL_EVAL_COORD2 ); + _tnl_EvalCoord2f( u[0], u[1] ); } static void _tnl_EvalPoint1( GLint i ) { - evalcoord( (GLfloat)i, 0, TNL_EVAL_POINT1 ); + GET_CURRENT_CONTEXT( ctx ); + GLfloat du = ((ctx->Eval.MapGrid1u2 - ctx->Eval.MapGrid1u1) / + (GLfloat) ctx->Eval.MapGrid1un); + GLfloat u = i * du + ctx->Eval.MapGrid1u1; + + _tnl_EvalCoord1f( u ); } + static void _tnl_EvalPoint2( GLint i, GLint j ) { - evalcoord( (GLfloat)i, (GLfloat)j, TNL_EVAL_POINT2 ); + GET_CURRENT_CONTEXT( ctx ); + GLfloat du = ((ctx->Eval.MapGrid2u2 - ctx->Eval.MapGrid2u1) / + (GLfloat) ctx->Eval.MapGrid2un); + GLfloat dv = ((ctx->Eval.MapGrid2v2 - ctx->Eval.MapGrid2v1) / + (GLfloat) ctx->Eval.MapGrid2vn); + GLfloat u = i * du + ctx->Eval.MapGrid2u1; + GLfloat v = j * dv + ctx->Eval.MapGrid2v1; + + _tnl_EvalCoord2f( u, v ); } -/* Don't do a lot of processing here - errors are raised when this - * list is scanned later on (perhaps in display list playback) to - * build tnl_prim structs. + +/* Build a list of primitives on the fly. Keep + * ctx->Driver.CurrentExecPrimitive uptodate as well. */ static void _tnl_Begin( GLenum mode ) { GET_CURRENT_CONTEXT( ctx ); - TNLcontext *tnl = TNL_CONTEXT(ctx); - int i; - i = tnl->vtx.be_count++; - tnl->vtx.be[i].type = TNL_BEGIN; - tnl->vtx.be[i].idx = tnl->vtx.initial_counter - tnl->vtx.counter; - tnl->vtx.be[i].mode = mode; + if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) { + TNLcontext *tnl = TNL_CONTEXT(ctx); + int i; + + if (ctx->NewState) { + _mesa_update_state( ctx ); + ctx->Exec->Begin(mode); + return; + } + +#if 1 + /* Heuristic: attempt to isolate attributes occuring outside + * begin/end pairs. + */ + if (tnl->vtx.vertex_size && !tnl->vtx.attrsz[0]) + _tnl_FlushVertices( ctx, ~0 ); +#endif + + i = tnl->vtx.prim_count++; + tnl->vtx.prim[i].mode = mode | PRIM_BEGIN; + tnl->vtx.prim[i].start = tnl->vtx.initial_counter - tnl->vtx.counter; + tnl->vtx.prim[i].count = 0; - if (tnl->vtx.be_count == TNL_BE_MAX) - _tnl_FlushVertices( ctx, FLUSH_STORED_VERTICES ); + ctx->Driver.CurrentExecPrimitive = mode; + } + else + _mesa_error( ctx, GL_INVALID_OPERATION, __FUNCTION__ ); + } static void _tnl_End( void ) { GET_CURRENT_CONTEXT( ctx ); - TNLcontext *tnl = TNL_CONTEXT(ctx); - int i; - i = tnl->vtx.be_count++; - tnl->vtx.be[i].type = TNL_END; - tnl->vtx.be[i].idx = tnl->vtx.initial_counter - tnl->vtx.counter; - tnl->vtx.be[i].mode = 0; + if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) { + TNLcontext *tnl = TNL_CONTEXT(ctx); + int idx = tnl->vtx.initial_counter - tnl->vtx.counter; + int i = tnl->vtx.prim_count - 1; - if (tnl->vtx.be_count == TNL_BE_MAX) - _tnl_FlushVertices( ctx, FLUSH_STORED_VERTICES ); -} + tnl->vtx.prim[i].mode |= PRIM_END; + tnl->vtx.prim[i].count = idx - tnl->vtx.prim[i].start; + + ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1; + +#if 0 + if (tnl->vtx.counter * 2 > tnl->vtx.initial_counter) + _tnl_FlushVertices( ctx, ~0 ); +#endif + if (tnl->vtx.prim_count == TNL_MAX_PRIM) { +#if 0 + _tnl_FlushVertices( ctx, ~0 ); +#else + _tnl_flush_vtx( ctx ); +#endif + } + } + else + _mesa_error( ctx, GL_INVALID_OPERATION, __FUNCTION__ ); +} +static void _tnl_exec_vtxfmt_init( GLcontext *ctx ) +{ + GLvertexformat *vfmt = &(TNL_CONTEXT(ctx)->exec_vtxfmt); + vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */ + vfmt->Begin = _tnl_Begin; + vfmt->CallList = _mesa_CallList; + vfmt->CallLists = _mesa_CallLists; + vfmt->Color3f = _tnl_Color3f; + vfmt->Color3fv = _tnl_Color3fv; + vfmt->Color4f = _tnl_Color4f; + vfmt->Color4fv = _tnl_Color4fv; + vfmt->EdgeFlag = _tnl_EdgeFlag; + vfmt->EdgeFlagv = _tnl_EdgeFlagv; + vfmt->End = _tnl_End; + vfmt->EvalCoord1f = _tnl_EvalCoord1f; + vfmt->EvalCoord1fv = _tnl_EvalCoord1fv; + vfmt->EvalCoord2f = _tnl_EvalCoord2f; + vfmt->EvalCoord2fv = _tnl_EvalCoord2fv; + vfmt->EvalPoint1 = _tnl_EvalPoint1; + vfmt->EvalPoint2 = _tnl_EvalPoint2; + vfmt->FogCoordfEXT = _tnl_FogCoordfEXT; + vfmt->FogCoordfvEXT = _tnl_FogCoordfvEXT; + vfmt->Indexf = _tnl_Indexf; + vfmt->Indexfv = _tnl_Indexfv; + vfmt->Materialfv = _tnl_Materialfv; + vfmt->MultiTexCoord1fARB = _tnl_MultiTexCoord1f; + vfmt->MultiTexCoord1fvARB = _tnl_MultiTexCoord1fv; + vfmt->MultiTexCoord2fARB = _tnl_MultiTexCoord2f; + vfmt->MultiTexCoord2fvARB = _tnl_MultiTexCoord2fv; + vfmt->MultiTexCoord3fARB = _tnl_MultiTexCoord3f; + vfmt->MultiTexCoord3fvARB = _tnl_MultiTexCoord3fv; + vfmt->MultiTexCoord4fARB = _tnl_MultiTexCoord4f; + vfmt->MultiTexCoord4fvARB = _tnl_MultiTexCoord4fv; + vfmt->Normal3f = _tnl_Normal3f; + vfmt->Normal3fv = _tnl_Normal3fv; + vfmt->SecondaryColor3fEXT = _tnl_SecondaryColor3fEXT; + vfmt->SecondaryColor3fvEXT = _tnl_SecondaryColor3fvEXT; + vfmt->TexCoord1f = _tnl_TexCoord1f; + vfmt->TexCoord1fv = _tnl_TexCoord1fv; + vfmt->TexCoord2f = _tnl_TexCoord2f; + vfmt->TexCoord2fv = _tnl_TexCoord2fv; + vfmt->TexCoord3f = _tnl_TexCoord3f; + vfmt->TexCoord3fv = _tnl_TexCoord3fv; + vfmt->TexCoord4f = _tnl_TexCoord4f; + vfmt->TexCoord4fv = _tnl_TexCoord4fv; + vfmt->Vertex2f = _tnl_Vertex2f; + vfmt->Vertex2fv = _tnl_Vertex2fv; + vfmt->Vertex3f = _tnl_Vertex3f; + vfmt->Vertex3fv = _tnl_Vertex3fv; + vfmt->Vertex4f = _tnl_Vertex4f; + vfmt->Vertex4fv = _tnl_Vertex4fv; + vfmt->VertexAttrib1fNV = _tnl_VertexAttrib1fNV; + vfmt->VertexAttrib1fvNV = _tnl_VertexAttrib1fvNV; + vfmt->VertexAttrib2fNV = _tnl_VertexAttrib2fNV; + vfmt->VertexAttrib2fvNV = _tnl_VertexAttrib2fvNV; + vfmt->VertexAttrib3fNV = _tnl_VertexAttrib3fNV; + vfmt->VertexAttrib3fvNV = _tnl_VertexAttrib3fvNV; + vfmt->VertexAttrib4fNV = _tnl_VertexAttrib4fNV; + vfmt->VertexAttrib4fvNV = _tnl_VertexAttrib4fvNV; + + vfmt->Rectf = _mesa_noop_Rectf; + vfmt->EvalMesh1 = _mesa_noop_EvalMesh1; + vfmt->EvalMesh2 = _mesa_noop_EvalMesh2; +} -static void _tnl_InitDispatch( struct _glapi_table *tab ) +void _tnl_FlushVertices( GLcontext *ctx, GLuint flags ) { - GLint i; - - /* Most operations boil down to error/transition behaviour. - * However if we transition eagerly, all that's needed is a single - * 'error' operation. This will do for now, but requires that the - * old 'flush' stuff lives on in the state functions, and is - * wasteful if swapping is expensive (threads?). - */ - for (i = 0 ; i < sizeof(tab)/sizeof(void*) ; i++) - ((void **)tab)[i] = (void *)op_error; - - tab->Begin = _tnl_Begin; - tab->End = _tnl_End; - tab->Color3f = choose_VERT_ATTRIB_COLOR0_3_0; - tab->Color3fv = choose_VERT_ATTRIB_COLOR0_3_1; - tab->Color4f = choose_VERT_ATTRIB_COLOR0_4_0; - tab->Color4fv = choose_VERT_ATTRIB_COLOR0_4_1; - tab->SecondaryColor3fEXT = choose_VERT_ATTRIB_COLOR1_3_0; - tab->SecondaryColor3fvEXT = choose_VERT_ATTRIB_COLOR1_3_1; - tab->MultiTexCoord1fARB = _tnl_MultiTexCoord1f; - tab->MultiTexCoord1fvARB = _tnl_MultiTexCoord1fv; - tab->MultiTexCoord2fARB = _tnl_MultiTexCoord2f; - tab->MultiTexCoord2fvARB = _tnl_MultiTexCoord2fv; - tab->MultiTexCoord3fARB = _tnl_MultiTexCoord3f; - tab->MultiTexCoord3fvARB = _tnl_MultiTexCoord3fv; - tab->MultiTexCoord4fARB = _tnl_MultiTexCoord4f; - tab->MultiTexCoord4fvARB = _tnl_MultiTexCoord4fv; - tab->Normal3f = choose_VERT_ATTRIB_NORMAL_3_0; - tab->Normal3fv = choose_VERT_ATTRIB_NORMAL_3_1; - tab->TexCoord1f = choose_VERT_ATTRIB_TEX0_1_0; - tab->TexCoord1fv = choose_VERT_ATTRIB_TEX0_1_1; - tab->TexCoord2f = choose_VERT_ATTRIB_TEX0_2_0; - tab->TexCoord2fv = choose_VERT_ATTRIB_TEX0_2_1; - tab->TexCoord3f = choose_VERT_ATTRIB_TEX0_3_0; - tab->TexCoord3fv = choose_VERT_ATTRIB_TEX0_3_1; - tab->TexCoord4f = choose_VERT_ATTRIB_TEX0_4_0; - tab->TexCoord4fv = choose_VERT_ATTRIB_TEX0_4_1; - tab->Vertex2f = choose_VERT_ATTRIB_POS_2_0; - tab->Vertex2fv = choose_VERT_ATTRIB_POS_2_1; - tab->Vertex3f = choose_VERT_ATTRIB_POS_3_0; - tab->Vertex3fv = choose_VERT_ATTRIB_POS_3_1; - tab->Vertex4f = choose_VERT_ATTRIB_POS_4_0; - tab->Vertex4fv = choose_VERT_ATTRIB_POS_4_1; - tab->FogCoordfEXT = choose_VERT_ATTRIB_FOG_1_0; - tab->FogCoordfvEXT = choose_VERT_ATTRIB_FOG_1_1; - tab->EdgeFlag = _tnl_EdgeFlag; - tab->EdgeFlagv = _tnl_EdgeFlagv; - tab->Indexi = _tnl_Indexi; - tab->Indexiv = _tnl_Indexiv; - tab->EvalCoord1f = _tnl_EvalCoord1f; - tab->EvalCoord1fv = _tnl_EvalCoord1fv; - tab->EvalCoord2f = _tnl_EvalCoord2f; - tab->EvalCoord2fv = _tnl_EvalCoord2fv; - tab->Materialfv = _tnl_Materialfv; - tab->ArrayElement = _ae_loopback_array_elt; /* generic helper */ -} - - - -static struct dynfn *codegen_noop( GLcontext *ctx, int key ) -{ - (void) ctx; (void) key; - return 0; -} - -static void _tnl_InitCodegen( GLcontext *ctx ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - int sz, v, z; - - /* attr[n][v] - * vertex[n][v] - * - * Generated functions parameterized by: - * nr 1..4 - * v y/n - * vertex y/n - * - * Vertex functions also parameterized by: - * vertex_size - * - * Attr functions also parameterized by: - * pointer (destination to receive data) - */ - for (sz = 1 ; sz < 5 ; sz++) { - for (v = 0 ; v < 2 ; v++) { - for (z = 0 ; z < 2 ; z++) { - tnl->vtx.codegen[sz-1][v][z] = codegen_noop; - tnl->vtx.generated[sz-1][v][z] = 0; - } - } - } + TNLcontext *tnl = TNL_CONTEXT(ctx); -#if 0 - if (!getenv("MESA_NO_CODEGEN")) { -#if defined(USE_X86_ASM) - _tnl_InitX86Codegen( gen ); -#endif + if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) + return; -#if defined(USE_SSE_ASM) - _tnl_InitSSECodegen( gen ); + if (tnl->vtx.counter != tnl->vtx.initial_counter) { + _tnl_flush_vtx( ctx ); +#if 0 + init_0(tnl); #endif + } -#if defined(USE_3DNOW_ASM) +#if 0 + if (flags & FLUSH_UPDATE_CURRENT) #endif + { + _tnl_copy_to_current( ctx ); -#if defined(USE_SPARC_ASM) -#endif + /* reset attrfv table + */ + init_attrfv( tnl ); + flags |= FLUSH_UPDATE_CURRENT; } -#endif + + ctx->Driver.NeedFlush = 0; +} + +static void _tnl_current_init( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLint i; + + for (i = 0; i < VERT_ATTRIB_MAX; i++) + tnl->vtx.current[i] = ctx->Current.Attrib[i]; + + for (i = 0; i < MAT_ATTRIB_MAX; i++) + tnl->vtx.current[_TNL_ATTRIB_MAT_FRONT_AMBIENT + i] = + ctx->Light.Material.Attrib[i]; + + tnl->vtx.current[_TNL_ATTRIB_INDEX] = &ctx->Current.Index; } @@ -870,29 +1144,22 @@ static void _tnl_InitCodegen( GLcontext *ctx ) void _tnl_vtx_init( GLcontext *ctx ) { TNLcontext *tnl = TNL_CONTEXT(ctx); - _tnl_InitDispatch( tnl->Exec ); - _tnl_InitCodegen( ctx ); + struct tnl_vertex_arrays *tmp = &tnl->vtx_inputs; + GLuint i; + + for (i = 0; i < _TNL_ATTRIB_INDEX; i++) + _mesa_vector4f_init( &tmp->Attribs[i], 0, 0); + + _tnl_current_init( ctx ); + _tnl_exec_vtxfmt_init( ctx ); + + _mesa_install_exec_vtxfmt( ctx, &tnl->exec_vtxfmt ); + tnl->vtx.vertex_size = 1; init_attrfv( tnl ); } void _tnl_vtx_destroy( GLcontext *ctx ) { - TNLcontext *tnl = TNL_CONTEXT(ctx); - int sz, v, z; - struct dynfn *dfn, *next; - - for (sz = 1 ; sz <= 4 ; sz++) { - for (v = 0 ; v <= 1 ; v++) { - for (z = 0 ; z <= 1 ; z++) { - dfn = tnl->vtx.generated[sz-1][v][z]; - while (dfn) { - next = dfn->next; - FREE(dfn); - dfn = next; - } - } - } - } } diff --git a/src/mesa/tnl/t_vtx_api.h b/src/mesa/tnl/t_vtx_api.h index 6bfdbe8fe39..25003202132 100644 --- a/src/mesa/tnl/t_vtx_api.h +++ b/src/mesa/tnl/t_vtx_api.h @@ -32,203 +32,27 @@ USE OR OTHER DEALINGS IN THE SOFTWARE. * */ -#ifndef __RADEON_VTXFMT_H__ -#define __RADEON_VTXFMT_H__ +#ifndef __T_VTX_API_H__ +#define __T_VTX_API_H__ -#ifdef GLX_DIRECT_RENDERING +#include "t_context.h" -#include "_tnl__context.h" +extern void _tnl_vtx_init( GLcontext *ctx ); +extern void _tnl_vtx_destroy( GLcontext *ctx ); -extern void _tnl_UpdateVtxfmt( GLcontext *ctx ); -extern void _tnl_InitVtxfmt( GLcontext *ctx ); -extern void _tnl_InvalidateVtxfmt( GLcontext *ctx ); -extern void _tnl_DestroyVtxfmt( GLcontext *ctx ); +extern void _tnl_FlushVertices( GLcontext *ctx, GLuint flags ); +extern void _tnl_flush_vtx( GLcontext *ctx ); -typedef void (*p4f)( GLfloat, GLfloat, GLfloat, GLfloat ); -typedef void (*p3f)( GLfloat, GLfloat, GLfloat ); -typedef void (*p2f)( GLfloat, GLfloat ); -typedef void (*p1f)( GLfloat ); -typedef void (*pe2f)( GLenum, GLfloat, GLfloat ); -typedef void (*pe1f)( GLenum, GLfloat ); -typedef void (*p4ub)( GLubyte, GLubyte, GLubyte, GLubyte ); -typedef void (*p3ub)( GLubyte, GLubyte, GLubyte ); -typedef void (*pfv)( const GLfloat * ); -typedef void (*pefv)( GLenum, const GLfloat * ); -typedef void (*pubv)( const GLubyte * ); +extern void _tnl_do_EvalCoord2f( GLcontext* ctx, GLfloat u, GLfloat v ); +extern void _tnl_do_EvalCoord1f(GLcontext* ctx, GLfloat u); +extern void _tnl_update_eval( GLcontext *ctx ); -/* Want to keep a cache of these around. Each is parameterized by - * only a single value which has only a small range. Only expect a - * few, so just rescan the list each time? - */ -struct dynfn { - struct dynfn *next, *prev; - int key; - char *code; -}; - -struct dfn_lists { - struct dynfn Vertex2f; - struct dynfn Vertex2fv; - struct dynfn Vertex3f; - struct dynfn Vertex3fv; - struct dynfn Color4ub; - struct dynfn Color4ubv; - struct dynfn Color3ub; - struct dynfn Color3ubv; - struct dynfn Color4f; - struct dynfn Color4fv; - struct dynfn Color3f; - struct dynfn Color3fv; - struct dynfn SecondaryColor3ubEXT; - struct dynfn SecondaryColor3ubvEXT; - struct dynfn SecondaryColor3fEXT; - struct dynfn SecondaryColor3fvEXT; - struct dynfn Normal3f; - struct dynfn Normal3fv; - struct dynfn TexCoord2f; - struct dynfn TexCoord2fv; - struct dynfn TexCoord1f; - struct dynfn TexCoord1fv; - struct dynfn MultiTexCoord2fARB; - struct dynfn MultiTexCoord2fvARB; - struct dynfn MultiTexCoord1fARB; - struct dynfn MultiTexCoord1fvARB; -}; - -struct _vb; - -struct dfn_generators { - struct dynfn *(*Vertex2f)( struct _vb *, int ); - struct dynfn *(*Vertex2fv)( struct _vb *, int ); - struct dynfn *(*Vertex3f)( struct _vb *, int ); - struct dynfn *(*Vertex3fv)( struct _vb *, int ); - struct dynfn *(*Color4ub)( struct _vb *, int ); - struct dynfn *(*Color4ubv)( struct _vb *, int ); - struct dynfn *(*Color3ub)( struct _vb *, int ); - struct dynfn *(*Color3ubv)( struct _vb *, int ); - struct dynfn *(*Color4f)( struct _vb *, int ); - struct dynfn *(*Color4fv)( struct _vb *, int ); - struct dynfn *(*Color3f)( struct _vb *, int ); - struct dynfn *(*Color3fv)( struct _vb *, int ); - struct dynfn *(*SecondaryColor3ubEXT)( struct _vb *, int ); - struct dynfn *(*SecondaryColor3ubvEXT)( struct _vb *, int ); - struct dynfn *(*SecondaryColor3fEXT)( struct _vb *, int ); - struct dynfn *(*SecondaryColor3fvEXT)( struct _vb *, int ); - struct dynfn *(*Normal3f)( struct _vb *, int ); - struct dynfn *(*Normal3fv)( struct _vb *, int ); - struct dynfn *(*TexCoord2f)( struct _vb *, int ); - struct dynfn *(*TexCoord2fv)( struct _vb *, int ); - struct dynfn *(*TexCoord1f)( struct _vb *, int ); - struct dynfn *(*TexCoord1fv)( struct _vb *, int ); - struct dynfn *(*MultiTexCoord2fARB)( struct _vb *, int ); - struct dynfn *(*MultiTexCoord2fvARB)( struct _vb *, int ); - struct dynfn *(*MultiTexCoord1fARB)( struct _vb *, int ); - struct dynfn *(*MultiTexCoord1fvARB)( struct _vb *, int ); -}; - -struct prim { - GLuint start; - GLuint end; - GLuint prim; -}; - -#define _TNL__MAX_PRIMS 64 - - - -struct tnl_vbinfo { - /* Keep these first: referenced from codegen templates: - */ - GLint counter; - GLint *dmaptr; - void (*notify)( void ); - union { float f; int i; GLubyte ub4[4]; } vertex[16*4]; - - GLfloat *attrptr[16]; - GLuint size[16]; - - GLenum *prim; /* &ctx->Driver.CurrentExecPrimitive */ - GLuint primflags; - - GLboolean installed; - GLboolean recheck; - - GLint vertex_size; - GLint initial_counter; - GLint nrverts; - GLuint vertex_format; - - GLuint installed_vertex_format; - - struct prim primlist[RADEON_MAX_PRIMS]; - int nrprims; +extern GLboolean *_tnl_translate_edgeflag( GLcontext *ctx, + const GLfloat *data, + GLuint count, + GLuint stride ); - struct dfn_lists dfn_cache; - struct dfn_generators codegen; - GLvertexformat vtxfmt; -}; +extern GLboolean *_tnl_import_current_edgeflag( GLcontext *ctx, + GLuint count ); - -extern void _tnl_InitVtxfmtChoosers( GLvertexformat *vfmt ); - - -#define FIXUP( CODE, OFFSET, CHECKVAL, NEWVAL ) \ -do { \ - int *icode = (int *)(CODE+OFFSET); \ - assert (*icode == CHECKVAL); \ - *icode = (int)NEWVAL; \ -} while (0) - - -/* Useful for figuring out the offsets: - */ -#define FIXUP2( CODE, OFFSET, CHECKVAL, NEWVAL ) \ -do { \ - while (*(int *)(CODE+OFFSET) != CHECKVAL) OFFSET++; \ - fprintf(stderr, "%s/%d CVAL %x OFFSET %d\n", __FUNCTION__, \ - __LINE__, CHECKVAL, OFFSET); \ - *(int *)(CODE+OFFSET) = (int)NEWVAL; \ - OFFSET += 4; \ -} while (0) - -/* - */ -void _tnl_InitCodegen( struct dfn_generators *gen ); -void _tnl_InitX86Codegen( struct dfn_generators *gen ); -void _tnl_InitSSECodegen( struct dfn_generators *gen ); - -void _tnl_copy_to_current( GLcontext *ctx ); - - -/* Defined in tnl_vtxfmt_c.c. - */ -struct dynfn *tnl_makeX86Vertex2f( TNLcontext *, int ); -struct dynfn *tnl_makeX86Vertex2fv( TNLcontext *, int ); -struct dynfn *tnl_makeX86Vertex3f( TNLcontext *, int ); -struct dynfn *tnl_makeX86Vertex3fv( TNLcontext *, int ); -struct dynfn *tnl_makeX86Color4ub( TNLcontext *, int ); -struct dynfn *tnl_makeX86Color4ubv( TNLcontext *, int ); -struct dynfn *tnl_makeX86Color3ub( TNLcontext *, int ); -struct dynfn *tnl_makeX86Color3ubv( TNLcontext *, int ); -struct dynfn *tnl_makeX86Color4f( TNLcontext *, int ); -struct dynfn *tnl_makeX86Color4fv( TNLcontext *, int ); -struct dynfn *tnl_makeX86Color3f( TNLcontext *, int ); -struct dynfn *tnl_makeX86Color3fv( TNLcontext *, int ); -struct dynfn *tnl_makeX86SecondaryColor3ubEXT( TNLcontext *, int ); -struct dynfn *tnl_makeX86SecondaryColor3ubvEXT( TNLcontext *, int ); -struct dynfn *tnl_makeX86SecondaryColor3fEXT( TNLcontext *, int ); -struct dynfn *tnl_makeX86SecondaryColor3fvEXT( TNLcontext *, int ); -struct dynfn *tnl_makeX86Normal3f( TNLcontext *, int ); -struct dynfn *tnl_makeX86Normal3fv( TNLcontext *, int ); -struct dynfn *tnl_makeX86TexCoord2f( TNLcontext *, int ); -struct dynfn *tnl_makeX86TexCoord2fv( TNLcontext *, int ); -struct dynfn *tnl_makeX86TexCoord1f( TNLcontext *, int ); -struct dynfn *tnl_makeX86TexCoord1fv( TNLcontext *, int ); -struct dynfn *tnl_makeX86MultiTexCoord2fARB( TNLcontext *, int ); -struct dynfn *tnl_makeX86MultiTexCoord2fvARB( TNLcontext *, int ); -struct dynfn *tnl_makeX86MultiTexCoord1fARB( TNLcontext *, int ); -struct dynfn *tnl_makeX86MultiTexCoord1fvARB( TNLcontext *, int ); - - -#endif #endif diff --git a/src/mesa/tnl/t_vtx_eval.c b/src/mesa/tnl/t_vtx_eval.c new file mode 100644 index 00000000000..5b5cb624c9a --- /dev/null +++ b/src/mesa/tnl/t_vtx_eval.c @@ -0,0 +1,253 @@ +/* + * Mesa 3-D graphics library + * Version: 5.1 + * + * Copyright (C) 1999-2003 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 + */ + +#include "glheader.h" +#include "api_eval.h" +#include "context.h" +#include "macros.h" +#include "math/m_eval.h" +#include "t_vtx_api.h" + + +static void clear_active_eval1( TNLcontext *tnl, GLuint attr ) +{ + tnl->vtx.eval.map1[attr].map = 0; +} + +static void clear_active_eval2( TNLcontext *tnl, GLuint attr ) +{ + tnl->vtx.eval.map2[attr].map = 0; +} + +static void set_active_eval1( TNLcontext *tnl, GLuint attr, GLuint dim, + struct gl_1d_map *map ) +{ + if (!tnl->vtx.eval.map1[attr].map) { + tnl->vtx.eval.map1[attr].map = map; + tnl->vtx.eval.map1[attr].sz = dim; + } +} + +static void set_active_eval2( TNLcontext *tnl, GLuint attr, GLuint dim, + struct gl_2d_map *map ) +{ + if (!tnl->vtx.eval.map2[attr].map) { + tnl->vtx.eval.map2[attr].map = map; + tnl->vtx.eval.map2[attr].sz = dim; + } +} + +void _tnl_update_eval( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint attr; + + /* Vertex program maps have priority over conventional attribs */ + + for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { + clear_active_eval1( tnl, attr ); + clear_active_eval2( tnl, attr ); + } + + if (ctx->VertexProgram.Enabled) { + for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { + if (ctx->Eval.Map1Attrib[attr]) + set_active_eval1( tnl, attr, 4, &ctx->EvalMap.Map1Attrib[attr] ); + + if (ctx->Eval.Map2Attrib[attr]) + set_active_eval2( tnl, attr, 4, &ctx->EvalMap.Map2Attrib[attr] ); + } + } + + if (ctx->Eval.Map1Color4) + set_active_eval1( tnl, VERT_ATTRIB_COLOR0, 4, &ctx->EvalMap.Map1Color4 ); + + if (ctx->Eval.Map2Color4) + set_active_eval2( tnl, VERT_ATTRIB_COLOR0, 4, &ctx->EvalMap.Map2Color4 ); + + if (ctx->Eval.Map1TextureCoord4) + set_active_eval1( tnl, VERT_ATTRIB_TEX0, 4, &ctx->EvalMap.Map1Texture4 ); + else if (ctx->Eval.Map1TextureCoord3) + set_active_eval1( tnl, VERT_ATTRIB_TEX0, 3, &ctx->EvalMap.Map1Texture3 ); + else if (ctx->Eval.Map1TextureCoord2) + set_active_eval1( tnl, VERT_ATTRIB_TEX0, 2, &ctx->EvalMap.Map1Texture2 ); + else if (ctx->Eval.Map1TextureCoord1) + set_active_eval1( tnl, VERT_ATTRIB_TEX0, 1, &ctx->EvalMap.Map1Texture1 ); + + if (ctx->Eval.Map2TextureCoord4) + set_active_eval2( tnl, VERT_ATTRIB_TEX0, 4, &ctx->EvalMap.Map2Texture4 ); + else if (ctx->Eval.Map2TextureCoord3) + set_active_eval2( tnl, VERT_ATTRIB_TEX0, 3, &ctx->EvalMap.Map2Texture3 ); + else if (ctx->Eval.Map2TextureCoord2) + set_active_eval2( tnl, VERT_ATTRIB_TEX0, 2, &ctx->EvalMap.Map2Texture2 ); + else if (ctx->Eval.Map2TextureCoord1) + set_active_eval2( tnl, VERT_ATTRIB_TEX0, 1, &ctx->EvalMap.Map2Texture1 ); + + if (ctx->Eval.Map1Normal) + set_active_eval1( tnl, VERT_ATTRIB_NORMAL, 3, &ctx->EvalMap.Map1Normal ); + + if (ctx->Eval.Map2Normal) + set_active_eval2( tnl, VERT_ATTRIB_NORMAL, 3, &ctx->EvalMap.Map2Normal ); + + if (ctx->Eval.Map1Vertex4) + set_active_eval1( tnl, VERT_ATTRIB_POS, 4, &ctx->EvalMap.Map1Vertex4 ); + else if (ctx->Eval.Map1Vertex3) + set_active_eval1( tnl, VERT_ATTRIB_POS, 3, &ctx->EvalMap.Map1Vertex3 ); + + if (ctx->Eval.Map2Vertex4) + set_active_eval2( tnl, VERT_ATTRIB_POS, 4, &ctx->EvalMap.Map2Vertex4 ); + else if (ctx->Eval.Map2Vertex3) + set_active_eval2( tnl, VERT_ATTRIB_POS, 3, &ctx->EvalMap.Map2Vertex3 ); + + tnl->vtx.eval.new_state = 0; +} + + + +void _tnl_do_EvalCoord1f(GLcontext* ctx, GLfloat u) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint attr; + + for (attr = 1; attr <= _TNL_ATTRIB_INDEX; attr++) { + struct gl_1d_map *map = tnl->vtx.eval.map1[attr].map; + if (map) { + GLfloat uu = (u - map->u1) * map->du; + GLfloat data[4]; + + ASSIGN_4V(data, 0, 0, 0, 1); + + _math_horner_bezier_curve(map->Points, data, uu, + tnl->vtx.eval.map1[attr].sz, + map->Order); + + COPY_SZ_4V( tnl->vtx.attrptr[attr], + tnl->vtx.attrsz[attr], + data ); + } + } + + /** Vertex -- EvalCoord1f is a noop if this map not enabled: + **/ + if (tnl->vtx.eval.map1[0].map) { + struct gl_1d_map *map = tnl->vtx.eval.map1[0].map; + GLfloat uu = (u - map->u1) * map->du; + GLfloat vertex[4]; + + ASSIGN_4V(vertex, 0, 0, 0, 1); + + _math_horner_bezier_curve(map->Points, vertex, uu, + tnl->vtx.eval.map1[0].sz, + map->Order); + + if (tnl->vtx.eval.map1[0].sz == 4) + glVertex4fv( vertex ); + else + glVertex3fv( vertex ); + } +} + + + +void _tnl_do_EvalCoord2f( GLcontext* ctx, GLfloat u, GLfloat v ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint attr; + + for (attr = 1; attr <= _TNL_ATTRIB_INDEX; attr++) { + struct gl_2d_map *map = tnl->vtx.eval.map2[attr].map; + if (map) { + GLfloat uu = (u - map->u1) * map->du; + GLfloat vv = (v - map->v1) * map->dv; + GLfloat data[4]; + + ASSIGN_4V(data, 0, 0, 0, 1); + + _math_horner_bezier_surf(map->Points, + data, + uu, vv, + tnl->vtx.eval.map2[attr].sz, + map->Uorder, map->Vorder); + + COPY_SZ_4V( tnl->vtx.attrptr[attr], + tnl->vtx.attrsz[attr], + data ); + } + } + + /** Vertex -- EvalCoord2f is a noop if this map not enabled: + **/ + if (tnl->vtx.eval.map2[0].map) { + struct gl_2d_map *map = tnl->vtx.eval.map2[0].map; + GLfloat uu = (u - map->u1) * map->du; + GLfloat vv = (v - map->v1) * map->dv; + GLfloat vertex[4]; + + ASSIGN_4V(vertex, 0, 0, 0, 1); + + if (ctx->Eval.AutoNormal) { + GLfloat normal[3]; + GLfloat du[4], dv[4]; + + _math_de_casteljau_surf(map->Points, vertex, du, dv, uu, vv, + tnl->vtx.eval.map2[0].sz, + map->Uorder, map->Vorder); + + if (tnl->vtx.eval.map2[0].sz == 4) { + du[0] = du[0]*vertex[3] - du[3]*vertex[0]; + du[1] = du[1]*vertex[3] - du[3]*vertex[1]; + du[2] = du[2]*vertex[3] - du[3]*vertex[2]; + + dv[0] = dv[0]*vertex[3] - dv[3]*vertex[0]; + dv[1] = dv[1]*vertex[3] - dv[3]*vertex[1]; + dv[2] = dv[2]*vertex[3] - dv[3]*vertex[2]; + } + + + CROSS3(normal, du, dv); + NORMALIZE_3FV(normal); + normal[3] = 1.0; + + COPY_SZ_4V( tnl->vtx.attrptr[_TNL_ATTRIB_NORMAL], + tnl->vtx.attrsz[_TNL_ATTRIB_NORMAL], + normal ); + + } + else { + _math_horner_bezier_surf(map->Points, vertex, uu, vv, + tnl->vtx.eval.map2[0].sz, + map->Uorder, map->Vorder); + } + + if (tnl->vtx.attrsz[0] == 4) + glVertex4fv( vertex ); + else + glVertex3fv( vertex ); + } +} + + diff --git a/src/mesa/tnl/t_vtx_exec.c b/src/mesa/tnl/t_vtx_exec.c index 5b2f713cc1b..4c59e5d9ad0 100644 --- a/src/mesa/tnl/t_vtx_exec.c +++ b/src/mesa/tnl/t_vtx_exec.c @@ -1,244 +1,252 @@ -/* $XFree86$ */ -/************************************************************************** - -Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas. - -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 -on the rights to use, copy, modify, merge, publish, distribute, sub -license, 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 (including the next -paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL -TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS 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 + * Mesa 3-D graphics library + * Version: 5.1 + * + * Copyright (C) 1999-2003 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 */ -#include "api_noop.h" -#include "api_arrayelt.h" + +#include "glheader.h" +#include "api_eval.h" #include "context.h" -#include "imports.h" -#include "mtypes.h" -#include "enums.h" -#include "glapi.h" -#include "colormac.h" -#include "light.h" #include "state.h" -#include "vtxfmt.h" - -#include "tnl/tnl.h" -#include "tnl/t_context.h" -#include "tnl/t_array_api.h" +#include "macros.h" +#include "math/m_eval.h" +#include "t_vtx_api.h" +#include "t_pipeline.h" -static void _tnl_FlushVertices( GLcontext *, GLuint ); +static void _tnl_print_vtx( GLcontext *ctx ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLuint count = tnl->vtx.initial_counter - tnl->vtx.counter; + GLuint i; + _mesa_debug(0, "%s: %u vertices %d primitives, %d vertsize\n", + __FUNCTION__, + count, + tnl->vtx.prim_count, + tnl->vtx.vertex_size); + + for (i = 0 ; i < tnl->vtx.prim_count ; i++) { + struct tnl_prim *prim = &tnl->vtx.prim[i]; + _mesa_debug(0, " prim %d: %s %d..%d %s %s\n", + i, + _mesa_lookup_enum_by_nr(prim->mode & PRIM_MODE_MASK), + prim->start, + prim->start + prim->count, + (prim->mode & PRIM_BEGIN) ? "BEGIN" : "(wrap)", + (prim->mode & PRIM_END) ? "END" : "(wrap)"); + } +} -void tnl_copy_to_current( GLcontext *ctx ) +GLboolean *_tnl_translate_edgeflag( GLcontext *ctx, const GLfloat *data, + GLuint count, GLuint stride ) { TNLcontext *tnl = TNL_CONTEXT(ctx); - GLuint flag = tnl->vertex_format; - GLint i; - - assert(ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT); + GLboolean *ef = tnl->vtx.edgeflag_tmp; + GLuint i; - for (i = 0 ; i < 16 ; i++) - if (flag & (1<Current.Attrib[i], tnl->attribptr[i] ); + if (!ef) + ef = tnl->vtx.edgeflag_tmp = MALLOC( tnl->vb.Size ); + + for (i = 0 ; i < count ; i++, data += stride) + ef[i] = (data[0] == 1.0); - if (flag & VERT_BIT_INDEX) - ctx->Current.Index = tnl->indexptr[0]; + return ef; +} - if (flag & VERT_BIT_EDGEFLAG) - ctx->Current.EdgeFlag = tnl->edgeflagptr[0]; - if (flag & VERT_BIT_MATERIAL) { - _mesa_update_material( ctx, - IM->Material[IM->LastMaterial], - IM->MaterialOrMask ); +GLboolean *_tnl_import_current_edgeflag( GLcontext *ctx, + GLuint count ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + GLboolean *ef = tnl->vtx.edgeflag_tmp; + GLboolean tmp = ctx->Current.EdgeFlag; + GLuint i; - tnl->Driver.NotifyMaterialChange( ctx ); - } + if (!ef) + ef = tnl->vtx.edgeflag_tmp = MALLOC( tnl->vb.Size ); + for (i = 0 ; i < count ; i++) + ef[i] = tmp; - ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT; + return ef; } -static GLboolean discreet_gl_prim[GL_POLYGON+1] = { - 1, /* 0 points */ - 1, /* 1 lines */ - 0, /* 2 line_strip */ - 0, /* 3 line_loop */ - 1, /* 4 tris */ - 0, /* 5 tri_fan */ - 0, /* 6 tri_strip */ - 1, /* 7 quads */ - 0, /* 8 quadstrip */ - 0, /* 9 poly */ -}; - -/* Optimize the primitive list: ONLY FOR EXECUTE ATM - */ -static void optimize_prims( TNLcontext *tnl ) +static GLint get_size( const GLfloat *f ) { - int i, j; - - if (tnl->nrprims <= 1) - return; - - for (j = 0, i = 1 ; i < tnl->nrprims; i++) { - int pj = tnl->primlist[j].prim & 0xf; - int pi = tnl->primlist[i].prim & 0xf; - - if (pj == pi && discreet_gl_prim[pj] && - tnl->primlist[i].start == tnl->primlist[j].end) { - tnl->primlist[j].end = tnl->primlist[i].end; - } - else { - j++; - if (j != i) tnl->primlist[j] = tnl->primlist[i]; - } - } - - tnl->nrprims = j+1; + if (f[3] != 1.0) return 4; + if (f[2] != 0.0) return 3; + return 2; } - -/* Bind vertex buffer pointers, run pipeline: +/* Some nasty stuff still hanging on here. + * + * TODO - remove VB->NormalPtr, etc and just use the AttrPtr's. */ -static void flush_prims( TNLcontext *tnl ) +static void _tnl_vb_bind_vtx( GLcontext *ctx ) { - int i,j; - - tnl->dma.current.ptr = tnl->dma.current.start += - (tnl->initial_counter - tnl->counter) * tnl->vertex_size * 4; + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + struct tnl_vertex_arrays *tmp = &tnl->vtx_inputs; + GLfloat *data = tnl->vtx.buffer; + GLuint count = tnl->vtx.initial_counter - tnl->vtx.counter; + GLuint attr, i; - tnl->tcl.vertex_format = tnl->vertex_format; - tnl->tcl.aos_components[0] = &tmp; - tnl->tcl.nr_aos_components = 1; - tnl->dma.flush = 0; + if (0) fprintf(stderr, "%s: %d verts %d vertsize\n", + __FUNCTION__, count, tnl->vtx.vertex_size); - tnl->Driver.RunPipeline( ... ); - - tnl->nrprims = 0; -} + /* Setup constant data in the VB. + */ + VB->Count = count; + VB->Primitive = tnl->vtx.prim; + VB->PrimitiveCount = tnl->vtx.prim_count; + VB->Elts = NULL; + VB->NormalLengthPtr = NULL; + + for (attr = 0; attr <= _TNL_ATTRIB_INDEX ; attr++) { + if (tnl->vtx.attrsz[attr]) { + tmp->Attribs[attr].count = count; + tmp->Attribs[attr].data = (GLfloat (*)[4]) data; + tmp->Attribs[attr].start = data; + tmp->Attribs[attr].size = tnl->vtx.attrsz[attr]; + tmp->Attribs[attr].stride = tnl->vtx.vertex_size * sizeof(GLfloat); + VB->AttribPtr[attr] = &tmp->Attribs[attr]; + data += tnl->vtx.attrsz[attr]; + } + else { +/* VB->AttribPtr[attr] = &tnl->current.Attribs[attr]; */ -static void start_prim( TNLcontext *tnl, GLuint mode ) -{ - if (MESA_VERBOSE & DEBUG_VFMT) - _mesa_debug(NULL, "%s %d\n", __FUNCTION__, - tnl->initial_counter - tnl->counter); - - tnl->primlist[tnl->nrprims].start = tnl->initial_counter - tnl->counter; - tnl->primlist[tnl->nrprims].prim = mode; -} -static void note_last_prim( TNLcontext *tnl, GLuint flags ) -{ - if (MESA_VERBOSE & DEBUG_VFMT) - _mesa_debug(NULL, "%s %d\n", __FUNCTION__, - tnl->initial_counter - tnl->counter); + tmp->Attribs[attr].count = count; + tmp->Attribs[attr].data = (GLfloat (*)[4]) tnl->vtx.current[attr]; + tmp->Attribs[attr].start = tnl->vtx.current[attr]; + tmp->Attribs[attr].size = get_size( tnl->vtx.current[attr] ); + tmp->Attribs[attr].stride = 0; + VB->AttribPtr[attr] = &tmp->Attribs[attr]; + } + } - if (tnl->prim[0] != GL_POLYGON+1) { - tnl->primlist[tnl->nrprims].prim |= flags; - tnl->primlist[tnl->nrprims].end = tnl->initial_counter - tnl->counter; + + /* Copy and translate EdgeFlag to a contiguous array of GLbooleans + */ + if (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL) { + if (tnl->vtx.attrsz[_TNL_ATTRIB_EDGEFLAG]) { + VB->EdgeFlag = _tnl_translate_edgeflag( ctx, data, count, + tnl->vtx.vertex_size ); + data++; + } + else + VB->EdgeFlag = _tnl_import_current_edgeflag( ctx, count ); + } - if (++tnl->nrprims == TNL_MAX_PRIMS) - flush_prims( tnl ); + /* Legacy pointers -- remove one day. + */ + VB->ObjPtr = VB->AttribPtr[_TNL_ATTRIB_POS]; + VB->NormalPtr = VB->AttribPtr[_TNL_ATTRIB_NORMAL]; + VB->ColorPtr[0] = VB->AttribPtr[_TNL_ATTRIB_COLOR0]; + VB->ColorPtr[1] = 0; + VB->IndexPtr[0] = VB->AttribPtr[_TNL_ATTRIB_INDEX]; + VB->IndexPtr[1] = 0; + VB->SecondaryColorPtr[0] = VB->AttribPtr[_TNL_ATTRIB_COLOR1]; + VB->SecondaryColorPtr[1] = 0; + + for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { + VB->TexCoordPtr[i] = VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]; } } -static void copy_vertex( TNLcontext *tnl, GLuint n, GLfloat *dst ) -{ - GLuint i; - GLfloat *src = (GLfloat *)(tnl->dma.current.address + - tnl->dma.current.ptr + - (tnl->primlist[tnl->nrprims].start + n) * - tnl->vertex_size * 4); - if (MESA_VERBOSE & DEBUG_VFMT) - _mesa_debug(NULL, "copy_vertex %d\n", - tnl->primlist[tnl->nrprims].start + n); - for (i = 0 ; i < tnl->vertex_size; i++) { - dst[i] = src[i]; - } -} -static GLuint copy_wrapped_verts( TNLcontext *tnl, GLfloat (*tmp)[15] ) +/* + * NOTE: Need to have calculated primitives by this point -- do it on the fly. + * NOTE: Old 'parity' issue is gone. + */ +static GLuint _tnl_copy_vertices( GLcontext *ctx ) { + TNLcontext *tnl = TNL_CONTEXT( ctx ); + GLuint nr = tnl->vtx.prim[tnl->vtx.prim_count-1].count; GLuint ovf, i; - GLuint nr = (tnl->initial_counter - tnl->counter) - tnl->primlist[tnl->nrprims].start; + GLuint sz = tnl->vtx.vertex_size; + GLfloat *dst = tnl->vtx.copied.buffer; + GLfloat *src = (tnl->vtx.buffer + + tnl->vtx.prim[tnl->vtx.prim_count-1].start * + tnl->vtx.vertex_size); - if (MESA_VERBOSE & DEBUG_VFMT) - _mesa_debug(NULL, "%s %d verts\n", __FUNCTION__, nr); - switch( tnl->prim[0] ) + switch( ctx->Driver.CurrentExecPrimitive ) { case GL_POINTS: return 0; case GL_LINES: ovf = nr&1; for (i = 0 ; i < ovf ; i++) - copy_vertex( tnl, nr-ovf+i, tmp[i] ); + memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) ); return i; case GL_TRIANGLES: ovf = nr%3; for (i = 0 ; i < ovf ; i++) - copy_vertex( tnl, nr-ovf+i, tmp[i] ); + memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) ); return i; case GL_QUADS: ovf = nr&3; for (i = 0 ; i < ovf ; i++) - copy_vertex( tnl, nr-ovf+i, tmp[i] ); + memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) ); return i; case GL_LINE_STRIP: if (nr == 0) return 0; - copy_vertex( tnl, nr-1, tmp[0] ); - return 1; + else { + memcpy( dst, src+(nr-1)*sz, sz * sizeof(GLfloat) ); + return 1; + } case GL_LINE_LOOP: case GL_TRIANGLE_FAN: case GL_POLYGON: if (nr == 0) return 0; else if (nr == 1) { - copy_vertex( tnl, 0, tmp[0] ); + memcpy( dst, src+0, sz * sizeof(GLfloat) ); return 1; } else { - copy_vertex( tnl, 0, tmp[0] ); - copy_vertex( tnl, nr-1, tmp[1] ); + memcpy( dst, src+0, sz * sizeof(GLfloat) ); + memcpy( dst+sz, src+(nr-1)*sz, sz * sizeof(GLfloat) ); return 2; } case GL_TRIANGLE_STRIP: - ovf = MIN2( nr-1, 2 ); - for (i = 0 ; i < ovf ; i++) - copy_vertex( tnl, nr-ovf+i, tmp[i] ); - return i; case GL_QUAD_STRIP: - ovf = MIN2( nr-1, 2 ); - if (nr > 2) ovf += nr&1; + switch (nr) { + case 0: ovf = 0; break; + case 1: ovf = 1; break; + default: ovf = 2 + (nr&1); break; + } for (i = 0 ; i < ovf ; i++) - copy_vertex( tnl, nr-ovf+i, tmp[i] ); + memcpy( dst+i*sz, src+(nr-ovf+i)*sz, sz * sizeof(GLfloat) ); return i; + case GL_POLYGON+1: + return 0; default: assert(0); return 0; @@ -247,385 +255,45 @@ static GLuint copy_wrapped_verts( TNLcontext *tnl, GLfloat (*tmp)[15] ) -/* Extend for vertex-format changes on wrap: - */ -static void wrap_buffer( void ) -{ - TNLcontext *tnl = tnl->tnl; - GLfloat tmp[3][15]; - GLuint i, nrverts; - - if (MESA_VERBOSE & (DEBUG_VFMT|DEBUG_PRIMS)) - _mesa_debug(NULL, "%s %d\n", __FUNCTION__, - tnl->initial_counter - tnl->counter); - - /* Don't deal with parity. *** WONT WORK FOR COMPILE - */ - if ((((tnl->initial_counter - tnl->counter) - - tnl->primlist[tnl->nrprims].start) & 1)) { - tnl->counter++; - tnl->initial_counter++; - return; - } - - /* Copy vertices out of dma: - */ - nrverts = copy_dma_verts( tnl, tmp ); - - if (MESA_VERBOSE & DEBUG_VFMT) - _mesa_debug(NULL, "%d vertices to copy\n", nrverts); - - - /* Finish the prim at this point: - */ - note_last_prim( tnl, 0 ); - flush_prims( tnl ); - - /* Reset counter, dmaptr - */ - tnl->dmaptr = (int *)(tnl->dma.current.ptr + tnl->dma.current.address); - tnl->counter = (tnl->dma.current.end - tnl->dma.current.ptr) / - (tnl->vertex_size * 4); - tnl->counter--; - tnl->initial_counter = tnl->counter; - tnl->notify = wrap_buffer; - tnl->dma.flush = flush_prims; - start_prim( tnl, tnl->prim[0] ); - /* Reemit saved vertices - * *** POSSIBLY IN NEW FORMAT - * --> Can't always extend at end of vertex? - */ - for (i = 0 ; i < nrverts; i++) { - if (MESA_VERBOSE & DEBUG_VERTS) { - int j; - _mesa_debug(NULL, "re-emit vertex %d to %p\n", i, tnl->dmaptr); - if (MESA_VERBOSE & DEBUG_VERBOSE) - for (j = 0 ; j < tnl->vertex_size; j++) - _mesa_debug(NULL, "\t%08x/%f\n", *(int*)&tmp[i][j], tmp[i][j]); - } - - memcpy( tnl->dmaptr, tmp[i], tnl->vertex_size * 4 ); - tnl->dmaptr += tnl->vertex_size; - tnl->counter--; - } -} - - - -/* Always follow data, don't try to predict what's necessary. +/** + * Execute the buffer and save copied verts. */ -static GLboolean check_vtx_fmt( GLcontext *ctx ) +void _tnl_flush_vtx( GLcontext *ctx ) { TNLcontext *tnl = TNL_CONTEXT(ctx); - if (ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) - ctx->Driver.FlushVertices( ctx, FLUSH_UPDATE_CURRENT ); - - - TNL_NEWPRIM(tnl); - tnl->vertex_format = VERT_BIT_POS; - tnl->prim = &ctx->Driver.CurrentExecPrimitive; - - - /* Currently allow the full 4 components per attrib. Can use the - * mechanism from radeon driver color handling to reduce this (and - * also to store ubyte colors where these are incoming). This - * won't work for compile mode. - * - * Only adding components when they are first received eliminates - * the need for displaylist fixup, as there are no 'empty' slots - * at the start of buffers. - */ - for (i = 0 ; i < 16 ; i++) { - if (ind & (1<attribptr[i] = &tnl->vertex[tnl->vertex_size].f; - tnl->vertex_size += 4; - tnl->attribptr[i][0] = ctx->Current.Attrib[i][0]; - tnl->attribptr[i][1] = ctx->Current.Attrib[i][1]; - tnl->attribptr[i][2] = ctx->Current.Attrib[i][2]; - tnl->attribptr[i][3] = ctx->Current.Attrib[i][3]; - } - else - tnl->attribptr[i] = ctx->Current.Attrib[i]; - } - - /* Edgeflag, Index: - */ - for (i = 16 ; i < 18 ; i++) - ; - - /* Materials: - */ - for (i = 18 ; i < 28 ; i++) - ; - - /* Eval: - */ - for (i = 28 ; i < 29 ; i++) - ; - - - if (tnl->installed_vertex_format != tnl->vertex_format) { - if (MESA_VERBOSE & DEBUG_VFMT) - _mesa_debug(NULL, "reinstall on vertex_format change\n"); - _mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt ); - tnl->installed_vertex_format = tnl->vertex_format; - } - - return GL_TRUE; -} - - -void _tnl_InvalidateVtxfmt( GLcontext *ctx ) -{ - tnl->recheck = GL_TRUE; - tnl->fell_back = GL_FALSE; -} - - - - -static void _tnl_ValidateVtxfmt( GLcontext *ctx ) -{ - if (MESA_VERBOSE & DEBUG_VFMT) - _mesa_debug(NULL, "%s\n", __FUNCTION__); - - if (ctx->Driver.NeedFlush) - ctx->Driver.FlushVertices( ctx, ctx->Driver.NeedFlush ); - - tnl->recheck = GL_FALSE; - - if (check_vtx_fmt( ctx )) { - if (!tnl->installed) { - if (MESA_VERBOSE & DEBUG_VFMT) - _mesa_debug(NULL, "reinstall (new install)\n"); - - _mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt ); - ctx->Driver.FlushVertices = _tnl_FlushVertices; - tnl->installed = GL_TRUE; - } - else - _mesa_debug(NULL, "%s: already installed", __FUNCTION__); - } - else { - if (MESA_VERBOSE & DEBUG_VFMT) - _mesa_debug(NULL, "%s: failed\n", __FUNCTION__); - - if (tnl->installed) { - if (tnl->tnl->dma.flush) - tnl->tnl->dma.flush( tnl->tnl ); - _tnl_wakeup_exec( ctx ); - tnl->installed = GL_FALSE; - } - } -} - - - - - -/* Begin/End - */ -static void _tnl_Begin( GLenum mode ) -{ - GLcontext *ctx = tnl->context; - TNLcontext *tnl = tnl->tnl; - - if (MESA_VERBOSE & DEBUG_VFMT) - _mesa_debug(NULL, "%s\n", __FUNCTION__); - - if (mode > GL_POLYGON) { - _mesa_error( ctx, GL_INVALID_ENUM, "glBegin" ); - return; - } - - if (tnl->prim[0] != GL_POLYGON+1) { - _mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" ); - return; - } - - if (ctx->NewState) - _mesa_update_state( ctx ); - - if (tnl->recheck) - _tnl_ValidateVtxfmt( ctx ); - - if (tnl->dma.flush && tnl->counter < 12) { - if (MESA_VERBOSE & DEBUG_VFMT) - _mesa_debug(NULL, "%s: flush almost-empty buffers\n", __FUNCTION__); - flush_prims( tnl ); - } - - if (!tnl->dma.flush) { - if (tnl->dma.current.ptr + 12*tnl->vertex_size*4 > - tnl->dma.current.end) { - TNL_NEWPRIM( tnl ); - _tnl_RefillCurrentDmaRegion( tnl ); - } - - tnl->dmaptr = (int *)(tnl->dma.current.address + tnl->dma.current.ptr); - tnl->counter = (tnl->dma.current.end - tnl->dma.current.ptr) / - (tnl->vertex_size * 4); - tnl->counter--; - tnl->initial_counter = tnl->counter; - tnl->notify = wrap_buffer; - tnl->dma.flush = flush_prims; - tnl->context->Driver.NeedFlush |= FLUSH_STORED_VERTICES; - } - - - tnl->prim[0] = mode; - start_prim( tnl, mode | PRIM_BEGIN ); -} - - - + if (0) + _tnl_print_vtx( ctx ); + if (tnl->vtx.prim_count && + tnl->vtx.counter != tnl->vtx.initial_counter) { -static void _tnl_End( void ) -{ - TNLcontext *tnl = tnl->tnl; - GLcontext *ctx = tnl->context; - - if (MESA_VERBOSE & DEBUG_VFMT) - _mesa_debug(NULL, "%s\n", __FUNCTION__); - - if (tnl->prim[0] == GL_POLYGON+1) { - _mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" ); - return; - } - - note_last_prim( tnl, PRIM_END ); - tnl->prim[0] = GL_POLYGON+1; -} - + tnl->vtx.copied.nr = _tnl_copy_vertices( ctx ); -static void _tnl_FlushVertices( GLcontext *ctx, GLuint flags ) -{ - if (MESA_VERBOSE & DEBUG_VFMT) - _mesa_debug(NULL, "%s\n", __FUNCTION__); + if (ctx->NewState) + _mesa_update_state( ctx ); + + if (tnl->pipeline.build_state_changes) + _tnl_validate_pipeline( ctx ); - assert(tnl->installed); + _tnl_vb_bind_vtx( ctx ); - if (flags & FLUSH_UPDATE_CURRENT) { - _tnl_copy_to_current( ctx ); - if (MESA_VERBOSE & DEBUG_VFMT) - _mesa_debug(NULL, "reinstall on update_current\n"); - _mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt ); - ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT; + /* Invalidate all stored data before and after run: + */ + tnl->pipeline.run_input_changes |= tnl->pipeline.inputs; + tnl->Driver.RunPipeline( ctx ); + tnl->pipeline.run_input_changes |= tnl->pipeline.inputs; } - if (flags & FLUSH_STORED_VERTICES) { - TNLcontext *tnl = TNL_CONTEXT( ctx ); - assert (tnl->dma.flush == 0 || - tnl->dma.flush == flush_prims); - if (tnl->dma.flush == flush_prims) - flush_prims( TNL_CONTEXT( ctx ) ); - ctx->Driver.NeedFlush &= ~FLUSH_STORED_VERTICES; - } + tnl->vtx.prim_count = 0; + tnl->vtx.counter = tnl->vtx.initial_counter; + tnl->vtx.vbptr = tnl->vtx.buffer; } -/* At this point, don't expect very many versions of each function to - * be generated, so not concerned about freeing them? - */ - - -static void _tnl_InitVtxfmt( GLcontext *ctx ) -{ - GLvertexformat *vfmt = &(tnl->vtxfmt); - - MEMSET( vfmt, 0, sizeof(GLvertexformat) ); - - /* Hook in chooser functions for codegen, etc: - */ - _tnl_InitVtxfmtChoosers( vfmt ); - - /* Handled fully in supported states, but no codegen: - */ - vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */ - vfmt->Rectf = _mesa_noop_Rectf; /* generic helper */ - vfmt->Begin = _tnl_Begin; - vfmt->End = _tnl_End; - - tnl->context = ctx; - tnl->tnl = TNL_CONTEXT(ctx); - tnl->prim = &ctx->Driver.CurrentExecPrimitive; - tnl->primflags = 0; - - make_empty_list( &tnl->dfn_cache.Vertex2f ); - make_empty_list( &tnl->dfn_cache.Vertex2fv ); - make_empty_list( &tnl->dfn_cache.Vertex3f ); - make_empty_list( &tnl->dfn_cache.Vertex3fv ); - make_empty_list( &tnl->dfn_cache.Color4ub ); - make_empty_list( &tnl->dfn_cache.Color4ubv ); - make_empty_list( &tnl->dfn_cache.Color3ub ); - make_empty_list( &tnl->dfn_cache.Color3ubv ); - make_empty_list( &tnl->dfn_cache.Color4f ); - make_empty_list( &tnl->dfn_cache.Color4fv ); - make_empty_list( &tnl->dfn_cache.Color3f ); - make_empty_list( &tnl->dfn_cache.Color3fv ); - make_empty_list( &tnl->dfn_cache.SecondaryColor3fEXT ); - make_empty_list( &tnl->dfn_cache.SecondaryColor3fvEXT ); - make_empty_list( &tnl->dfn_cache.SecondaryColor3ubEXT ); - make_empty_list( &tnl->dfn_cache.SecondaryColor3ubvEXT ); - make_empty_list( &tnl->dfn_cache.Normal3f ); - make_empty_list( &tnl->dfn_cache.Normal3fv ); - make_empty_list( &tnl->dfn_cache.TexCoord2f ); - make_empty_list( &tnl->dfn_cache.TexCoord2fv ); - make_empty_list( &tnl->dfn_cache.TexCoord1f ); - make_empty_list( &tnl->dfn_cache.TexCoord1fv ); - make_empty_list( &tnl->dfn_cache.MultiTexCoord2fARB ); - make_empty_list( &tnl->dfn_cache.MultiTexCoord2fvARB ); - make_empty_list( &tnl->dfn_cache.MultiTexCoord1fARB ); - make_empty_list( &tnl->dfn_cache.MultiTexCoord1fvARB ); - - _tnl_InitCodegen( &tnl->codegen ); -} -static void free_funcs( struct dynfn *l ) -{ - struct dynfn *f, *tmp; - foreach_s (f, tmp, l) { - remove_from_list( f ); - ALIGN_FREE( f->code ); - FREE( f ); - } -} - - -static void _tnl_DestroyVtxfmt( GLcontext *ctx ) -{ - count_funcs(); - free_funcs( &tnl->dfn_cache.Vertex2f ); - free_funcs( &tnl->dfn_cache.Vertex2fv ); - free_funcs( &tnl->dfn_cache.Vertex3f ); - free_funcs( &tnl->dfn_cache.Vertex3fv ); - free_funcs( &tnl->dfn_cache.Color4ub ); - free_funcs( &tnl->dfn_cache.Color4ubv ); - free_funcs( &tnl->dfn_cache.Color3ub ); - free_funcs( &tnl->dfn_cache.Color3ubv ); - free_funcs( &tnl->dfn_cache.Color4f ); - free_funcs( &tnl->dfn_cache.Color4fv ); - free_funcs( &tnl->dfn_cache.Color3f ); - free_funcs( &tnl->dfn_cache.Color3fv ); - free_funcs( &tnl->dfn_cache.SecondaryColor3ubEXT ); - free_funcs( &tnl->dfn_cache.SecondaryColor3ubvEXT ); - free_funcs( &tnl->dfn_cache.SecondaryColor3fEXT ); - free_funcs( &tnl->dfn_cache.SecondaryColor3fvEXT ); - free_funcs( &tnl->dfn_cache.Normal3f ); - free_funcs( &tnl->dfn_cache.Normal3fv ); - free_funcs( &tnl->dfn_cache.TexCoord2f ); - free_funcs( &tnl->dfn_cache.TexCoord2fv ); - free_funcs( &tnl->dfn_cache.TexCoord1f ); - free_funcs( &tnl->dfn_cache.TexCoord1fv ); - free_funcs( &tnl->dfn_cache.MultiTexCoord2fARB ); - free_funcs( &tnl->dfn_cache.MultiTexCoord2fvARB ); - free_funcs( &tnl->dfn_cache.MultiTexCoord1fARB ); - free_funcs( &tnl->dfn_cache.MultiTexCoord1fvARB ); -} diff --git a/src/mesa/tnl/t_vtx_sse.c b/src/mesa/tnl/t_vtx_sse.c deleted file mode 100644 index 8998c901bcd..00000000000 --- a/src/mesa/tnl/t_vtx_sse.c +++ /dev/null @@ -1,91 +0,0 @@ -/* $XFree86$ */ -/************************************************************************** - -Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas. - -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 -on the rights to use, copy, modify, merge, publish, distribute, sub -license, 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 (including the next -paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL -TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS 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 - */ - -#include "imports.h" -#include "simple_list.h" -#include "t_vtx_api.h" - -#if defined(USE_SSE_ASM) - -/* Build specialized versions of the immediate calls on the fly for - * the current state. ???P4 SSE2 versions??? - */ - - -static struct dynfn *makeSSENormal3fv( struct _vb *vb, int key ) -{ - /* Requires P4 (sse2?) - */ - static unsigned char temp[] = { - 0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ - 0xba, 0x78, 0x56, 0x34, 0x12, /* mov $0x12345678,%edx */ - 0xf3, 0x0f, 0x7e, 0x00, /* movq (%eax),%xmm0 */ - 0x66, 0x0f, 0x6e, 0x48, 0x08, /* movd 0x8(%eax),%xmm1 */ - 0x66, 0x0f, 0xd6, 0x42, 0x0c, /* movq %xmm0,0xc(%edx) */ - 0x66, 0x0f, 0x7e, 0x4a, 0x14, /* movd %xmm1,0x14(%edx) */ - 0xc3, /* ret */ - }; - - - struct dynfn *dfn = MALLOC_STRUCT( dynfn ); - insert_at_head( &vb->dfn_cache.Normal3fv, dfn ); - dfn->key = key; - - dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); - memcpy (dfn->code, temp, sizeof(temp)); - FIXUP(dfn->code, 5, 0x0, (int)vb->normalptr); - return dfn; -} - -void _tnl_InitSSECodegen( struct dfn_generators *gen ) -{ - /* Need to: - * - check kernel sse support - * - check p4/sse2 - */ - (void) makeSSENormal3fv; -} - - -#else - -void _tnl_InitSSECodegen( struct dfn_generators *gen ) -{ - (void) gen; -} - -#endif - - - - diff --git a/src/mesa/tnl/t_vtx_x86.c b/src/mesa/tnl/t_vtx_x86.c deleted file mode 100644 index 3211662dae6..00000000000 --- a/src/mesa/tnl/t_vtx_x86.c +++ /dev/null @@ -1,704 +0,0 @@ -/* $XFree86$ */ -/************************************************************************** - -Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas. - -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 -on the rights to use, copy, modify, merge, publish, distribute, sub -license, 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 (including the next -paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL -TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS 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 - */ - -#include "imports.h" -#include "simple_list.h" -#include "tnl_vtxfmt.h" - -#if defined(USE_X86_ASM) - - -struct dynfn *tnl_makeX86Vertex2f( TNLcontext *tnl, int key ) -{ - struct dynfn *dfn = MALLOC_STRUCT( dynfn ); - - if (RADEON_DEBUG & DEBUG_CODEGEN) - _mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key ); - - switch (tnl->vertex_size) { - default: { - /* Repz convenient as it's possible to emit code for any size - * vertex with little tweaking. Might as well read vertsize - * though, and have only one of these. - */ - static char temp[] = { - 0x57, /* push %edi */ - 0x56, /* push %esi */ - 0xbe, 0, 0, 0, 0, /* mov $VERTEX+2,%esi */ - 0x8b, 0x3d, 0, 0, 0, 0, /* mov DMAPTR,%edi */ - 0x8b, 0x44, 0x24, 0x0c, /* mov 0x0c(%esp,1),%eax */ - 0x8b, 0x54, 0x24, 0x10, /* mov 0x10(%esp,1),%edx */ - 0x89, 0x07, /* mov %eax,(%edi) */ - 0x89, 0x57, 0x04, /* mov %edx,0x4(%edi) */ - 0x83, 0xc7, 0x08, /* add $0x8,%edi */ - 0xb9, 0, 0, 0, 0, /* mov $VERTSIZE-2,%ecx */ - 0xf3, 0xa5, /* repz movsl %ds:(%esi),%es:(%edi)*/ - 0xa1, 0, 0, 0, 0, /* mov COUNTER,%eax */ - 0x89, 0x3d, 0, 0, 0, 0, /* mov %edi,DMAPTR */ - 0x48, /* dec %eax */ - 0xa3, 0, 0, 0, 0, /* mov %eax,COUNTER */ - 0x5e, /* pop %esi */ - 0x5f, /* pop %edi */ - 0x74, 0x01, /* je +1 */ - 0xc3, /* ret */ - 0xff, 0x25, 0, 0, 0, 0 /* jmp NOTIFY */ - }; - - dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); - memcpy (dfn->code, temp, sizeof(temp)); - FIXUP(dfn->code, 3, 0x0, (int)&tnl->vertex[2]); - FIXUP(dfn->code, 9, 0x0, (int)&tnl->dmaptr); - FIXUP(dfn->code, 37, 0x0, tnl->vertex_size-2); - FIXUP(dfn->code, 44, 0x0, (int)&tnl->counter); - FIXUP(dfn->code, 50, 0x0, (int)&tnl->dmaptr); - FIXUP(dfn->code, 56, 0x0, (int)&tnl->counter); - FIXUP(dfn->code, 67, 0x0, (int)&tnl->notify); - break; - } - } - - insert_at_head( &tnl->dfn_cache.Vertex3f, dfn ); - dfn->key = key; - return dfn; -} - -/* Build specialized versions of the immediate calls on the fly for - * the current state. Generic x86 versions. - */ - -struct dynfn *tnl_makeX86Vertex3f( TNLcontext *tnl, int key ) -{ - struct dynfn *dfn = MALLOC_STRUCT( dynfn ); - - if (RADEON_DEBUG & DEBUG_CODEGEN) - _mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key ); - - switch (tnl->vertex_size) { - case 4: { - static char temp[] = { - 0x8b, 0x0d, 0,0,0,0, /* mov DMAPTR,%ecx */ - 0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ - 0x8b, 0x54, 0x24, 0x08, /* mov 0x8(%esp,1),%edx */ - 0x89, 0x01, /* mov %eax,(%ecx) */ - 0x89, 0x51, 0x04, /* mov %edx,0x4(%ecx) */ - 0x8b, 0x44, 0x24, 0x0c, /* mov 0xc(%esp,1),%eax */ - 0x8b, 0x15, 0,0,0,0, /* mov VERTEX[3],%edx */ - 0x89, 0x41, 0x08, /* mov %eax,0x8(%ecx) */ - 0x89, 0x51, 0x0c, /* mov %edx,0xc(%ecx) */ - 0xa1, 0, 0, 0, 0, /* mov COUNTER,%eax */ - 0x83, 0xc1, 0x10, /* add $0x10,%ecx */ - 0x48, /* dec %eax */ - 0x89, 0x0d, 0,0,0,0, /* mov %ecx,DMAPTR */ - 0xa3, 0, 0, 0, 0, /* mov %eax,COUNTER */ - 0x74, 0x01, /* je +1 */ - 0xc3, /* ret */ - 0xff, 0x25, 0,0,0,0 /* jmp *NOTIFY */ - }; - - dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); - memcpy (dfn->code, temp, sizeof(temp)); - FIXUP(dfn->code, 2, 0x0, (int)&tnl->dmaptr); - FIXUP(dfn->code, 25, 0x0, (int)&tnl->vertex[3]); - FIXUP(dfn->code, 36, 0x0, (int)&tnl->counter); - FIXUP(dfn->code, 46, 0x0, (int)&tnl->dmaptr); - FIXUP(dfn->code, 51, 0x0, (int)&tnl->counter); - FIXUP(dfn->code, 60, 0x0, (int)&tnl->notify); - break; - } - case 6: { - static char temp[] = { - 0x57, /* push %edi */ - 0x8b, 0x3d, 0, 0, 0, 0, /* mov DMAPTR,%edi */ - 0x8b, 0x44, 0x24, 0x8, /* mov 0x8(%esp,1),%eax */ - 0x8b, 0x54, 0x24, 0xc, /* mov 0xc(%esp,1),%edx */ - 0x8b, 0x4c, 0x24, 0x10, /* mov 0x10(%esp,1),%ecx */ - 0x89, 0x07, /* mov %eax,(%edi) */ - 0x89, 0x57, 0x04, /* mov %edx,0x4(%edi) */ - 0x89, 0x4f, 0x08, /* mov %ecx,0x8(%edi) */ - 0xa1, 0, 0, 0, 0, /* mov VERTEX[3],%eax */ - 0x8b, 0x15, 0, 0, 0, 0, /* mov VERTEX[4],%edx */ - 0x8b, 0x0d, 0, 0, 0, 0, /* mov VERTEX[5],%ecx */ - 0x89, 0x47, 0x0c, /* mov %eax,0xc(%edi) */ - 0x89, 0x57, 0x10, /* mov %edx,0x10(%edi) */ - 0x89, 0x4f, 0x14, /* mov %ecx,0x14(%edi) */ - 0x83, 0xc7, 0x18, /* add $0x18,%edi */ - 0xa1, 0, 0, 0, 0, /* mov COUNTER,%eax */ - 0x89, 0x3d, 0, 0, 0, 0, /* mov %edi,DMAPTR */ - 0x48, /* dec %eax */ - 0x5f, /* pop %edi */ - 0xa3, 0, 0, 0, 0, /* mov %eax,COUNTER */ - 0x74, 0x01, /* je +1 */ - 0xc3, /* ret */ - 0xff, 0x25, 0,0,0,0, /* jmp *NOTIFY */ - }; - - dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); - memcpy (dfn->code, temp, sizeof(temp)); - FIXUP(dfn->code, 3, 0x0, (int)&tnl->dmaptr); - FIXUP(dfn->code, 28, 0x0, (int)&tnl->vertex[3]); - FIXUP(dfn->code, 34, 0x0, (int)&tnl->vertex[4]); - FIXUP(dfn->code, 40, 0x0, (int)&tnl->vertex[5]); - FIXUP(dfn->code, 57, 0x0, (int)&tnl->counter); - FIXUP(dfn->code, 63, 0x0, (int)&tnl->dmaptr); - FIXUP(dfn->code, 70, 0x0, (int)&tnl->counter); - FIXUP(dfn->code, 79, 0x0, (int)&tnl->notify); - break; - } - default: { - /* Repz convenient as it's possible to emit code for any size - * vertex with little tweaking. Might as well read vertsize - * though, and have only one of these. - */ - static char temp[] = { - 0x57, /* push %edi */ - 0x56, /* push %esi */ - 0xbe, 0, 0, 0, 0, /* mov $VERTEX+3,%esi */ - 0x8b, 0x3d, 0, 0, 0, 0, /* mov DMAPTR,%edi */ - 0x8b, 0x44, 0x24, 0x0c, /* mov 0x0c(%esp,1),%eax */ - 0x8b, 0x54, 0x24, 0x10, /* mov 0x10(%esp,1),%edx */ - 0x8b, 0x4c, 0x24, 0x14, /* mov 0x14(%esp,1),%ecx */ - 0x89, 0x07, /* mov %eax,(%edi) */ - 0x89, 0x57, 0x04, /* mov %edx,0x4(%edi) */ - 0x89, 0x4f, 0x08, /* mov %ecx,0x8(%edi) */ - 0x83, 0xc7, 0x0c, /* add $0xc,%edi */ - 0xb9, 0, 0, 0, 0, /* mov $VERTSIZE-3,%ecx */ - 0xf3, 0xa5, /* repz movsl %ds:(%esi),%es:(%edi)*/ - 0xa1, 0, 0, 0, 0, /* mov COUNTER,%eax */ - 0x89, 0x3d, 0, 0, 0, 0, /* mov %edi,DMAPTR */ - 0x48, /* dec %eax */ - 0xa3, 0, 0, 0, 0, /* mov %eax,COUNTER */ - 0x5e, /* pop %esi */ - 0x5f, /* pop %edi */ - 0x74, 0x01, /* je +1 */ - 0xc3, /* ret */ - 0xff, 0x25, 0, 0, 0, 0 /* jmp NOTIFY */ - }; - - dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); - memcpy (dfn->code, temp, sizeof(temp)); - FIXUP(dfn->code, 3, 0x0, (int)&tnl->vertex[3]); - FIXUP(dfn->code, 9, 0x0, (int)&tnl->dmaptr); - FIXUP(dfn->code, 37, 0x0, tnl->vertex_size-3); - FIXUP(dfn->code, 44, 0x0, (int)&tnl->counter); - FIXUP(dfn->code, 50, 0x0, (int)&tnl->dmaptr); - FIXUP(dfn->code, 56, 0x0, (int)&tnl->counter); - FIXUP(dfn->code, 67, 0x0, (int)&tnl->notify); - break; - } - } - - insert_at_head( &tnl->dfn_cache.Vertex3f, dfn ); - dfn->key = key; - return dfn; -} - - - -struct dynfn *tnl_makeX86Vertex3fv( TNLcontext *tnl, int key ) -{ - struct dynfn *dfn = MALLOC_STRUCT( dynfn ); - - if (TNL_DEBUG & DEBUG_CODEGEN) - _mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key ); - - switch (tnl->vertex_size) { - case 6: { - static char temp[] = { - 0xa1, 0x00, 0x00, 0, 0, /* mov 0x0,%eax */ - 0x8b, 0x4c, 0x24, 0x04, /* mov 0x4(%esp,1),%ecx */ - 0x8b, 0x11, /* mov (%ecx),%edx */ - 0x89, 0x10, /* mov %edx,(%eax) */ - 0x8b, 0x51, 0x04, /* mov 0x4(%ecx),%edx */ - 0x8b, 0x49, 0x08, /* mov 0x8(%ecx),%ecx */ - 0x89, 0x50, 0x04, /* mov %edx,0x4(%eax) */ - 0x89, 0x48, 0x08, /* mov %ecx,0x8(%eax) */ - 0x8b, 0x15, 0x1c, 0, 0, 0, /* mov 0x1c,%edx */ - 0x8b, 0x0d, 0x20, 0, 0, 0, /* mov 0x20,%ecx */ - 0x89, 0x50, 0x0c, /* mov %edx,0xc(%eax) */ - 0x89, 0x48, 0x10, /* mov %ecx,0x10(%eax) */ - 0x8b, 0x15, 0x24, 0, 0, 0, /* mov 0x24,%edx */ - 0x89, 0x50, 0x14, /* mov %edx,0x14(%eax) */ - 0x83, 0xc0, 0x18, /* add $0x18,%eax */ - 0xa3, 0x00, 0x00, 0, 0, /* mov %eax,0x0 */ - 0xa1, 0x04, 0x00, 0, 0, /* mov 0x4,%eax */ - 0x48, /* dec %eax */ - 0xa3, 0x04, 0x00, 0, 0, /* mov %eax,0x4 */ - 0x74, 0x01, /* je 2a4 <.f11> */ - 0xc3, /* ret */ - 0xff, 0x25, 0x08, 0, 0, 0, /* jmp *0x8 */ - }; - - dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); - memcpy (dfn->code, temp, sizeof(temp)); - FIXUP(dfn->code, 1, 0x00000000, (int)&tnl->dmaptr); - FIXUP(dfn->code, 27, 0x0000001c, (int)&tnl->vertex[3]); - FIXUP(dfn->code, 33, 0x00000020, (int)&tnl->vertex[4]); - FIXUP(dfn->code, 45, 0x00000024, (int)&tnl->vertex[5]); - FIXUP(dfn->code, 56, 0x00000000, (int)&tnl->dmaptr); - FIXUP(dfn->code, 61, 0x00000004, (int)&tnl->counter); - FIXUP(dfn->code, 67, 0x00000004, (int)&tnl->counter); - FIXUP(dfn->code, 76, 0x00000008, (int)&tnl->notify); - break; - } - - - case 8: { - static char temp[] = { - 0xa1, 0x00, 0x00, 0, 0, /* mov 0x0,%eax */ - 0x8b, 0x4c, 0x24, 0x04, /* mov 0x4(%esp,1),%ecx */ - 0x8b, 0x11, /* mov (%ecx),%edx */ - 0x89, 0x10, /* mov %edx,(%eax) */ - 0x8b, 0x51, 0x04, /* mov 0x4(%ecx),%edx */ - 0x8b, 0x49, 0x08, /* mov 0x8(%ecx),%ecx */ - 0x89, 0x50, 0x04, /* mov %edx,0x4(%eax) */ - 0x89, 0x48, 0x08, /* mov %ecx,0x8(%eax) */ - 0x8b, 0x15, 0x1c, 0, 0, 0, /* mov 0x1c,%edx */ - 0x8b, 0x0d, 0x20, 0, 0, 0, /* mov 0x20,%ecx */ - 0x89, 0x50, 0x0c, /* mov %edx,0xc(%eax) */ - 0x89, 0x48, 0x10, /* mov %ecx,0x10(%eax) */ - 0x8b, 0x15, 0x1c, 0, 0, 0, /* mov 0x1c,%edx */ - 0x8b, 0x0d, 0x20, 0, 0, 0, /* mov 0x20,%ecx */ - 0x89, 0x50, 0x14, /* mov %edx,0x14(%eax) */ - 0x89, 0x48, 0x18, /* mov %ecx,0x18(%eax) */ - 0x8b, 0x15, 0x24, 0, 0, 0, /* mov 0x24,%edx */ - 0x89, 0x50, 0x1c, /* mov %edx,0x1c(%eax) */ - 0x83, 0xc0, 0x20, /* add $0x20,%eax */ - 0xa3, 0x00, 0x00, 0, 0, /* mov %eax,0x0 */ - 0xa1, 0x04, 0x00, 0, 0, /* mov 0x4,%eax */ - 0x48, /* dec %eax */ - 0xa3, 0x04, 0x00, 0, 0, /* mov %eax,0x4 */ - 0x74, 0x01, /* je 2a4 <.f11> */ - 0xc3, /* ret */ - 0xff, 0x25, 0x08, 0, 0, 0, /* jmp *0x8 */ - }; - - dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); - memcpy (dfn->code, temp, sizeof(temp)); - FIXUP(dfn->code, 1, 0x00000000, (int)&tnl->dmaptr); - FIXUP(dfn->code, 27, 0x0000001c, (int)&tnl->vertex[3]); - FIXUP(dfn->code, 33, 0x00000020, (int)&tnl->vertex[4]); - FIXUP(dfn->code, 45, 0x0000001c, (int)&tnl->vertex[5]); - FIXUP(dfn->code, 51, 0x00000020, (int)&tnl->vertex[6]); - FIXUP(dfn->code, 63, 0x00000024, (int)&tnl->vertex[7]); - FIXUP(dfn->code, 74, 0x00000000, (int)&tnl->dmaptr); - FIXUP(dfn->code, 79, 0x00000004, (int)&tnl->counter); - FIXUP(dfn->code, 85, 0x00000004, (int)&tnl->counter); - FIXUP(dfn->code, 94, 0x00000008, (int)&tnl->notify); - break; - } - - - - default: { - /* Repz convenient as it's possible to emit code for any size - * vertex with little tweaking. Might as well read vertsize - * though, and have only one of these. - */ - static char temp[] = { - 0x8b, 0x54, 0x24, 0x04, /* mov 0x4(%esp,1),%edx */ - 0x57, /* push %edi */ - 0x56, /* push %esi */ - 0x8b, 0x3d, 1,1,1,1, /* mov DMAPTR,%edi */ - 0x8b, 0x02, /* mov (%edx),%eax */ - 0x8b, 0x4a, 0x04, /* mov 0x4(%edx),%ecx */ - 0x8b, 0x72, 0x08, /* mov 0x8(%edx),%esi */ - 0x89, 0x07, /* mov %eax,(%edi) */ - 0x89, 0x4f, 0x04, /* mov %ecx,0x4(%edi) */ - 0x89, 0x77, 0x08, /* mov %esi,0x8(%edi) */ - 0x83, 0xc7, 0x0c, /* add $0xc,%edi */ - 0xb9, 0x06, 0x00, 0x00, 0x00, /* mov $VERTSIZE-3,%ecx */ - 0xbe, 0x58, 0x00, 0x00, 0x00, /* mov $VERTEX[3],%esi */ - 0xf3, 0xa5, /* repz movsl %ds:(%esi),%es:(%edi)*/ - 0x89, 0x3d, 1, 1, 1, 1, /* mov %edi,DMAPTR */ - 0xa1, 2, 2, 2, 2, /* mov COUNTER,%eax */ - 0x5e, /* pop %esi */ - 0x5f, /* pop %edi */ - 0x48, /* dec %eax */ - 0xa3, 2, 2, 2, 2, /* mov %eax,COUNTER */ - 0x74, 0x01, /* je +1 */ - 0xc3, /* ret */ - 0xff, 0x25, 0, 0, 0, 0 /* jmp NOTIFY */ - }; - - dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); - memcpy (dfn->code, temp, sizeof(temp)); - FIXUP(dfn->code, 8, 0x01010101, (int)&tnl->dmaptr); - FIXUP(dfn->code, 32, 0x00000006, tnl->vertex_size-3); - FIXUP(dfn->code, 37, 0x00000058, (int)&tnl->vertex[3]); - FIXUP(dfn->code, 45, 0x01010101, (int)&tnl->dmaptr); - FIXUP(dfn->code, 50, 0x02020202, (int)&tnl->counter); - FIXUP(dfn->code, 58, 0x02020202, (int)&tnl->counter); - FIXUP(dfn->code, 67, 0x0, (int)&tnl->notify); - break; - } - } - - insert_at_head( &tnl->dfn_cache.Vertex3fv, dfn ); - dfn->key = key; - return dfn; -} - - -struct dynfn *tnl_makeX86Attr4fv( TNLcontext *tnl, int key ) -{ - static char temp[] = { - 0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ - 0xba, 0, 0, 0, 0, /* mov $DEST,%edx */ - 0x8b, 0x08, /* mov (%eax),%ecx */ - 0x89, 0x0a, /* mov %ecx,(%edx) */ - 0x8b, 0x48, 0x04, /* mov 0x4(%eax),%ecx */ - 0x89, 0x4a, 0x04, /* mov %ecx,0x4(%edx) */ - 0x8b, 0x48, 0x08, /* mov 0x8(%eax),%ecx */ - 0x89, 0x4a, 0x08, /* mov %ecx,0x8(%edx) */ - 0x8b, 0x48, 0x0a, /* mov 0xa(%eax),%ecx */ - 0x89, 0x4a, 0x0a, /* mov %ecx,0xa(%edx) */ - 0xc3, /* ret */ - }; - - struct dynfn *dfn = MALLOC_STRUCT( dynfn ); - - if (TNL_DEBUG & DEBUG_CODEGEN) - _mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key ); - - insert_at_head( &tnl->dfn_cache.Normal3fv, dfn ); - dfn->key = key; - dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); - memcpy (dfn->code, temp, sizeof(temp)); - FIXUP(dfn->code, 5, 0x0, (int)tnl->normalptr); - return dfn; -} - -struct dynfn *tnl_makeX86Attr4f( TNLcontext *tnl, int key ) -{ - static char temp[] = { - 0xba, 0x78, 0x56, 0x34, 0x12, /* mov $DEST,%edx */ - 0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ - 0x89, 0x02, /* mov %eax,(%edx) */ - 0x8b, 0x44, 0x24, 0x08, /* mov 0x8(%esp,1),%eax */ - 0x89, 0x42, 0x04, /* mov %eax,0x4(%edx) */ - 0x8b, 0x44, 0x24, 0x0c, /* mov 0xc(%esp,1),%eax */ - 0x89, 0x42, 0x08, /* mov %eax,0x8(%edx) */ - 0x8b, 0x44, 0x24, 0x10, /* mov 0x10(%esp,1),%eax */ - 0x89, 0x42, 0x0a, /* mov %eax,0xa(%edx) */ - 0xc3, /* ret */ - }; - - struct dynfn *dfn = MALLOC_STRUCT( dynfn ); - - if (TNL_DEBUG & DEBUG_CODEGEN) - _mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key ); - - insert_at_head( &tnl->dfn_cache.Normal3f, dfn ); - dfn->key = key; - dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); - memcpy (dfn->code, temp, sizeof(temp)); - FIXUP(dfn->code, 1, 0x12345678, (int)tnl->normalptr); - return dfn; -} - - -struct dynfn *tnl_makeX86Attr3fv( TNLcontext *tnl, int key ) -{ - static char temp[] = { - 0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ - 0xba, 0, 0, 0, 0, /* mov $DEST,%edx */ - 0x8b, 0x08, /* mov (%eax),%ecx */ - 0x89, 0x0a, /* mov %ecx,(%edx) */ - 0x8b, 0x48, 0x04, /* mov 0x4(%eax),%ecx */ - 0x89, 0x4a, 0x04, /* mov %ecx,0x4(%edx) */ - 0x8b, 0x48, 0x08, /* mov 0x8(%eax),%ecx */ - 0x89, 0x4a, 0x08, /* mov %ecx,0x8(%edx) */ - 0xc3, /* ret */ - }; - - struct dynfn *dfn = MALLOC_STRUCT( dynfn ); - - if (TNL_DEBUG & DEBUG_CODEGEN) - _mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key ); - - insert_at_head( &tnl->dfn_cache.Normal3fv, dfn ); - dfn->key = key; - dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); - memcpy (dfn->code, temp, sizeof(temp)); - FIXUP(dfn->code, 5, 0x0, (int)tnl->normalptr); - return dfn; -} - -struct dynfn *tnl_makeX86Attr3f( TNLcontext *tnl, int key ) -{ - static char temp[] = { - 0xba, 0x78, 0x56, 0x34, 0x12, /* mov $DEST,%edx */ - 0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ - 0x89, 0x02, /* mov %eax,(%edx) */ - 0x8b, 0x44, 0x24, 0x08, /* mov 0x8(%esp,1),%eax */ - 0x89, 0x42, 0x04, /* mov %eax,0x4(%edx) */ - 0x8b, 0x44, 0x24, 0x0c, /* mov 0xc(%esp,1),%eax */ - 0x89, 0x42, 0x08, /* mov %eax,0x8(%edx) */ - 0xc3, /* ret */ - }; - - struct dynfn *dfn = MALLOC_STRUCT( dynfn ); - - if (TNL_DEBUG & DEBUG_CODEGEN) - _mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key ); - - insert_at_head( &tnl->dfn_cache.Normal3f, dfn ); - dfn->key = key; - dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); - memcpy (dfn->code, temp, sizeof(temp)); - FIXUP(dfn->code, 1, 0x12345678, (int)tnl->normalptr); - return dfn; -} - -struct dynfn *tnl_makeX86Attr4ubv( TNLcontext *tnl, int key ) -{ - struct dynfn *dfn = MALLOC_STRUCT( dynfn ); - insert_at_head( &tnl->dfn_cache.Color4ubv, dfn ); - dfn->key = key; - - if (TNL_DEBUG & DEBUG_CODEGEN) - _mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key ); - - if (key & TNL_CP_VC_FRMT_PKCOLOR) { - static char temp[] = { - 0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ - 0xba, 0x78, 0x56, 0x34, 0x12, /* mov $DEST,%edx */ - 0x8b, 0x00, /* mov (%eax),%eax */ - 0x89, 0x02, /* mov %eax,(%edx) */ - 0xc3, /* ret */ - }; - - dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); - memcpy (dfn->code, temp, sizeof(temp)); - FIXUP(dfn->code, 5, 0x12345678, (int)tnl->ubytecolorptr); - return dfn; - } - else { - static char temp[] = { - 0x53, /* push %ebx */ - 0xba, 0x00, 0x00, 0x00, 0x00, /* mov $0x0,%edx */ - 0x31, 0xc0, /* xor %eax,%eax */ - 0x31, 0xc9, /* xor %ecx,%ecx */ - 0x8b, 0x5c, 0x24, 0x08, /* mov 0x8(%esp,1), %ebx */ - 0x8b, 0x1b, /* mov (%ebx), %ebx */ - 0x88, 0xd8, /* mov %bl, %al */ - 0x88, 0xf9, /* mov %bh, %cl */ - 0x8b, 0x04, 0x82, /* mov (%edx,%eax,4),%eax */ - 0x8b, 0x0c, 0x8a, /* mov (%edx,%ecx,4),%ecx */ - 0xa3, 0xaf, 0xbe, 0xad, 0xde, /* mov %eax,0xdeadbeaf */ - 0x89, 0x0d, 0xaf, 0xbe, 0xad, 0xde, /* mov %ecx,0xdeadbeaf */ - 0x31, 0xc0, /* xor %eax,%eax */ - 0x31, 0xc9, /* xor %ecx,%ecx */ - 0xc1, 0xeb, 0x10, /* shr $0x10, %ebx */ - 0x88, 0xd8, /* mov %bl, %al */ - 0x88, 0xf9, /* mov %bh, %cl */ - 0x8b, 0x04, 0x82, /* mov (%edx,%eax,4),%eax */ - 0x8b, 0x0c, 0x8a, /* mov (%edx,%ecx,4),%ecx */ - 0xa3, 0xaf, 0xbe, 0xad, 0xde, /* mov %eax,0xdeadbeaf */ - 0x89, 0x0d, 0xaf, 0xbe, 0xad, 0xde, /* mov %ecx,0xdeadbeaf */ - 0x5b, /* pop %ebx */ - 0xc3, /* ret */ - }; - - dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); - memcpy (dfn->code, temp, sizeof(temp)); - FIXUP(dfn->code, 2, 0x00000000, (int)_mesa_ubyte_to_float_color_tab); - FIXUP(dfn->code, 27, 0xdeadbeaf, (int)tnl->floatcolorptr); - FIXUP(dfn->code, 33, 0xdeadbeaf, (int)tnl->floatcolorptr+4); - FIXUP(dfn->code, 55, 0xdeadbeaf, (int)tnl->floatcolorptr+8); - FIXUP(dfn->code, 61, 0xdeadbeaf, (int)tnl->floatcolorptr+12); - return dfn; - } -} - -struct dynfn *tnl_makeX86Attr4ub( TNLcontext *tnl, int key ) -{ - if (TNL_DEBUG & DEBUG_CODEGEN) - _mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key ); - - if (key & TNL_CP_VC_FRMT_PKCOLOR) { - /* XXX push/pop */ - static char temp[] = { - 0x53, /* push %ebx */ - 0x8b, 0x44, 0x24, 0x08, /* mov 0x8(%esp,1),%eax */ - 0x8b, 0x54, 0x24, 0x0c, /* mov 0xc(%esp,1),%edx */ - 0x8b, 0x4c, 0x24, 0x10, /* mov 0x10(%esp,1),%ecx */ - 0x8b, 0x5c, 0x24, 0x14, /* mov 0x14(%esp,1),%ebx */ - 0xa2, 0, 0, 0, 0, /* mov %al,DEST */ - 0x88, 0x15, 0, 0, 0, 0, /* mov %dl,DEST+1 */ - 0x88, 0x0d, 0, 0, 0, 0, /* mov %cl,DEST+2 */ - 0x88, 0x1d, 0, 0, 0, 0, /* mov %bl,DEST+3 */ - 0x5b, /* pop %ebx */ - 0xc3, /* ret */ - }; - - struct dynfn *dfn = MALLOC_STRUCT( dynfn ); - insert_at_head( &tnl->dfn_cache.Color4ub, dfn ); - dfn->key = key; - - dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); - memcpy (dfn->code, temp, sizeof(temp)); - FIXUP(dfn->code, 18, 0x0, (int)tnl->ubytecolorptr); - FIXUP(dfn->code, 24, 0x0, (int)tnl->ubytecolorptr+1); - FIXUP(dfn->code, 30, 0x0, (int)tnl->ubytecolorptr+2); - FIXUP(dfn->code, 36, 0x0, (int)tnl->ubytecolorptr+3); - return dfn; - } - else - return 0; -} - - - -struct dynfn *tnl_makeX86Attr2fv( TNLcontext *tnl, int key ) -{ - static char temp[] = { - 0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ - 0xba, 0x78, 0x56, 0x34, 0x12, /* mov $DEST,%edx */ - 0x8b, 0x08, /* mov (%eax),%ecx */ - 0x8b, 0x40, 0x04, /* mov 0x4(%eax),%eax */ - 0x89, 0x0a, /* mov %ecx,(%edx) */ - 0x89, 0x42, 0x04, /* mov %eax,0x4(%edx) */ - 0xc3, /* ret */ - }; - - struct dynfn *dfn = MALLOC_STRUCT( dynfn ); - - if (TNL_DEBUG & DEBUG_CODEGEN) - _mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key ); - - insert_at_head( &tnl->dfn_cache.TexCoord2fv, dfn ); - dfn->key = key; - dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); - memcpy (dfn->code, temp, sizeof(temp)); - FIXUP(dfn->code, 5, 0x12345678, (int)tnl->texcoordptr[0]); - return dfn; -} - -struct dynfn *tnl_makeX86Attr2f( TNLcontext *tnl, int key ) -{ - static char temp[] = { - 0xba, 0x78, 0x56, 0x34, 0x12, /* mov $DEST,%edx */ - 0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ - 0x8b, 0x4c, 0x24, 0x08, /* mov 0x8(%esp,1),%ecx */ - 0x89, 0x02, /* mov %eax,(%edx) */ - 0x89, 0x4a, 0x04, /* mov %ecx,0x4(%edx) */ - 0xc3, /* ret */ - }; - - struct dynfn *dfn = MALLOC_STRUCT( dynfn ); - - if (TNL_DEBUG & DEBUG_CODEGEN) - _mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key ); - - insert_at_head( &tnl->dfn_cache.TexCoord2f, dfn ); - dfn->key = key; - dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); - memcpy (dfn->code, temp, sizeof(temp)); - FIXUP(dfn->code, 1, 0x12345678, (int)tnl->texcoordptr[0]); - return dfn; -} - - -struct dynfn *tnl_makeX86Attr1fv( TNLcontext *tnl, int key ) -{ - static char temp[] = { - 0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ - 0xba, 0x78, 0x56, 0x34, 0x12, /* mov $DEST,%edx */ - 0x8b, 0x08, /* mov (%eax),%ecx */ - 0x89, 0x0a, /* mov %ecx,(%edx) */ - 0xc3, /* ret */ - }; - - struct dynfn *dfn = MALLOC_STRUCT( dynfn ); - - if (TNL_DEBUG & DEBUG_CODEGEN) - _mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key ); - - insert_at_head( &tnl->dfn_cache.TexCoord2fv, dfn ); - dfn->key = key; - dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); - memcpy (dfn->code, temp, sizeof(temp)); - FIXUP(dfn->code, 5, 0x12345678, (int)tnl->texcoordptr[0]); - return dfn; -} - -struct dynfn *tnl_makeX86Attr1f( TNLcontext *tnl, int key ) -{ - static char temp[] = { - 0xba, 0x78, 0x56, 0x34, 0x12, /* mov $DEST,%edx */ - 0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ - 0x89, 0x02, /* mov %eax,(%edx) */ - 0xc3, /* ret */ - }; - - struct dynfn *dfn = MALLOC_STRUCT( dynfn ); - - if (TNL_DEBUG & DEBUG_CODEGEN) - _mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key ); - - insert_at_head( &tnl->dfn_cache.TexCoord2f, dfn ); - dfn->key = key; - dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); - memcpy (dfn->code, temp, sizeof(temp)); - FIXUP(dfn->code, 1, 0x12345678, (int)tnl->texcoordptr[0]); - return dfn; -} - - - -void _tnl_InitX86Codegen( struct dfn_generators *gen ) -{ - gen->Attr1f = tnl_makeX86Attr1f; - gen->Attr1fv = tnl_makeX86Attr1fv; - gen->Attr2f = tnl_makeX86Attr2f; - gen->Attr2fv = tnl_makeX86Attr2fv; - gen->Attr3f = tnl_makeX86Attr3f; - gen->Attr3fv = tnl_makeX86Attr3fv; - gen->Attr4f = tnl_makeX86Attr4f; - gen->Attr4fv = tnl_makeX86Attr4fv; - gen->Attr4ub = tnl_makeX86Attr4ub; - gen->Attr4ubv = tnl_makeX86Attr4ubv; - gen->Vertex3f = tnl_makeX86Vertex3f; - gen->Vertex3fv = tnl_makeX86Vertex3fv; -} - - -#else - -void _tnl_InitX86Codegen( struct dfn_generators *gen ) -{ - (void) gen; -} - -#endif -- cgit v1.2.3