diff options
Diffstat (limited to 'src/mesa/tnl/t_imm_exec.c')
-rw-r--r-- | src/mesa/tnl/t_imm_exec.c | 507 |
1 files changed, 507 insertions, 0 deletions
diff --git a/src/mesa/tnl/t_imm_exec.c b/src/mesa/tnl/t_imm_exec.c new file mode 100644 index 0000000000..97f23d86e6 --- /dev/null +++ b/src/mesa/tnl/t_imm_exec.c @@ -0,0 +1,507 @@ +/* $Id: t_imm_exec.c,v 1.1 2000/12/26 05:09:32 keithw Exp $ */ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2000 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 <keithw@valinux.com> + */ + + +#include "glheader.h" +#include "context.h" +#include "enums.h" +#include "dlist.h" +#include "macros.h" +#include "mem.h" +#include "mmath.h" +#include "light.h" +#include "state.h" +#include "texture.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" + + + +/* Called to initialize new buffers, and to recycle old ones. + */ +void _tnl_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)); + + IM->CopyStart = IM->Start = IM->Count = start; + IM->Primitive[IM->Start] = (ctx->Driver.CurrentExecPrimitive | PRIM_LAST); + IM->LastPrimitive = IM->Start; + IM->BeginState = beginstate; + IM->SavedBeginState = savedbeginstate; + IM->TexSize = 0; + + IM->ArrayEltFlags = ~ctx->Array._Enabled; + IM->ArrayEltIncr = ctx->Array.Vertex.Enabled ? 1 : 0; + IM->ArrayEltFlush = !ctx->Array.LockCount; +} + + + +static void copy_to_current( GLcontext *ctx, struct immediate *IM, + GLuint flag ) +{ + GLuint count = IM->LastData; + + if (MESA_VERBOSE&VERBOSE_IMMEDIATE) + _tnl_print_vert_flags("copy to current", flag); + + if (flag & VERT_NORM) + COPY_3FV( ctx->Current.Normal, IM->Normal[count]); + + if (flag & VERT_INDEX) + ctx->Current.Index = IM->Index[count]; + + if (flag & VERT_EDGE) + ctx->Current.EdgeFlag = IM->EdgeFlag[count]; + + if (flag & VERT_RGBA) + COPY_4UBV(ctx->Current.Color, IM->Color[count]); + + if (flag & VERT_SPEC_RGB) + COPY_4UBV(ctx->Current.SecondaryColor, IM->SecondaryColor[count]); + + if (flag & VERT_FOG_COORD) + ctx->Current.FogCoord = IM->FogCoord[count]; + + if (flag & VERT_TEX_ANY) { + GLuint i; + for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) { + if (flag & VERT_TEX(i)) { + COPY_4FV( ctx->Current.Texcoord[0], IM->TexCoord[0][count]); + } + } + } +} + + + +void _tnl_compute_orflag( struct immediate *IM ) +{ + GLuint count = IM->Count; + GLuint orflag = 0; + GLuint andflag = ~0U; + GLuint i; + + IM->LastData = count-1; + + + /* Compute the flags for the whole buffer. + */ + for (i = IM->CopyStart ; i < count ; i++) { + andflag &= IM->Flag[i]; + orflag |= IM->Flag[i]; + } + + /* It is possible there will be data in the buffer arising from + * calls like 'glNormal', 'glMaterial' that occur after the final + * glVertex, glEval, etc. Additionally, a buffer can consist of + * only a single glMaterial call, in which case IM->Start == + * IM->Count, but the buffer is definitely not empty. + */ + if (IM->Flag[i] & VERT_DATA) { + IM->LastData++; + orflag |= IM->Flag[i]; + } + + IM->Flag[IM->LastData+1] |= VERT_END_VB; + IM->CopyAndFlag = IM->AndFlag = andflag; + IM->CopyOrFlag = IM->OrFlag = orflag; +} + + + + + +/* 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 */ + GLuint start = IM->CopyStart; + 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 = 0; + 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 = 0; + VB->NormalLengthPtr = 0; + VB->FogCoordPtr = 0; + VB->EdgeFlagPtr = 0; + VB->IndexPtr[0] = 0; + VB->IndexPtr[1] = 0; + VB->ColorPtr[0] = 0; + VB->ColorPtr[1] = 0; + VB->SecondaryColorPtr[0] = 0; + VB->SecondaryColorPtr[1] = 0; + VB->Elts = 0; + VB->MaterialMask = 0; + VB->Material = 0; + +/* _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_OBJ) { + tmp->Obj.data = IM->Obj + start; + tmp->Obj.start = (GLfloat *)(IM->Obj + start); + tmp->Obj.count = count; + VB->ObjPtr = &tmp->Obj; + if ((IM->CopyOrFlag & VERT_OBJ_234) == VERT_OBJ_234) + tmp->Obj.size = 4; + else if ((IM->CopyOrFlag & VERT_OBJ_234) == VERT_OBJ_23) + tmp->Obj.size = 3; + else + tmp->Obj.size = 2; + } + + if (inputs & VERT_NORM) { + tmp->Normal.data = IM->Normal + start; + tmp->Normal.start = (GLfloat *)(IM->Normal + start); + tmp->Normal.count = count; + VB->NormalPtr = &tmp->Normal; + if (IM->NormalLengths) + VB->NormalLengthPtr = IM->NormalLengths + start; + } + + if (inputs & VERT_INDEX) { + tmp->Index.count = count; + tmp->Index.data = IM->Index + start; + tmp->Index.start = IM->Index + start; + VB->IndexPtr[0] = &tmp->Index; + } + + if (inputs & VERT_FOG_COORD) { + tmp->FogCoord.data = IM->FogCoord + start; + tmp->FogCoord.start = IM->FogCoord + start; + tmp->FogCoord.count = count; + VB->FogCoordPtr = &tmp->FogCoord; + } + + if (inputs & VERT_SPEC_RGB) { + tmp->SecondaryColor.data = IM->SecondaryColor + start; + tmp->SecondaryColor.start = (GLubyte *)(IM->SecondaryColor + start); + tmp->SecondaryColor.count = count; + VB->SecondaryColorPtr[0] = &tmp->SecondaryColor; + } + + if (inputs & VERT_EDGE) { + tmp->EdgeFlag.data = IM->EdgeFlag + start; + tmp->EdgeFlag.start = IM->EdgeFlag + start; + tmp->EdgeFlag.count = count; + VB->EdgeFlagPtr = &tmp->EdgeFlag; + } + + if (inputs & VERT_RGBA) { + tmp->Color.data = IM->Color + start; + tmp->Color.start = (GLubyte *)(IM->Color + start); + tmp->Color.count = count; + VB->ColorPtr[0] = &tmp->Color; + } + + if (inputs & VERT_TEX_ANY) { + GLuint i; + for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { + VB->TexCoordPtr[i] = 0; + if (inputs & VERT_TEX(i)) { + tmp->TexCoord[i].count = count; + tmp->TexCoord[i].data = IM->TexCoord[i] + start; + tmp->TexCoord[i].start = (GLfloat *)(IM->TexCoord[i] + start); + tmp->TexCoord[i].size = 2; + if (IM->TexSize & i) { + tmp->TexCoord[i].size = 3; + if (IM->TexSize & (i<<16)) + tmp->TexCoord[i].size = 4; + } + VB->TexCoordPtr[i] = &tmp->TexCoord[i]; + } + } + } + + if ((inputs & VERT_MATERIAL) && IM->Material) { + VB->MaterialMask = IM->MaterialMask + start; + VB->Material = IM->Material + start; + } +} + + + + +/* Called by exec_cassette and execute_compiled_cassette. + */ +void _tnl_run_cassette( GLcontext *ctx, struct immediate *IM ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + + _tnl_vb_bind_immediate( ctx, IM ); + + if (IM->CopyOrFlag & VERT_EVAL_ANY) + _tnl_eval_vb( ctx, + IM->Obj + IM->CopyStart, + IM->CopyOrFlag, + IM->CopyAndFlag ); + + + /* Invalidate all stored data before and after run: + */ + tnl->pipeline.run_input_changes |= tnl->pipeline.inputs; + _tnl_run_pipeline( ctx ); + tnl->pipeline.run_input_changes |= tnl->pipeline.inputs; + + copy_to_current( ctx, IM, IM->OrFlag ); +} + + + + +/* Called for pure, locked VERT_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 ); + + 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_run_pipeline( ctx ); + + /* Still need to update current values: (TODO - copy from VB) + * TODO: delay this until FlushVertices + */ + if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) { + _tnl_translate_array_elts( ctx, IM, IM->LastData, IM->LastData ); + copy_to_current( ctx, IM, ctx->Array._Enabled ); + } +} + +/* Called for cassettes where CopyStart == Count -- no need to run the + * pipeline. + */ +static void exec_empty_cassette( GLcontext *ctx, struct immediate *IM ) +{ + GLuint start = IM->CopyStart; + + if (IM->OrFlag & VERT_ELT) + _tnl_translate_array_elts( ctx, IM, start, start ); + + _tnl_fixup_input( ctx, IM ); /* shouldn't be needed? (demos/fire) */ + copy_to_current( ctx, IM, IM->OrFlag ); + + if (IM->OrFlag & VERT_MATERIAL) + gl_update_material( ctx, IM->Material[start], IM->MaterialMask[start] ); + + if (IM->OrFlag & VERT_RGBA) + if (ctx->Light.ColorMaterialEnabled) + gl_update_color_material( ctx, ctx->Current.Color ); +} + + +/* Called for regular vertex cassettes. + */ +static void exec_vert_cassette( GLcontext *ctx, struct immediate *IM ) +{ + if (IM->OrFlag & VERT_ELT) { + GLuint andflag = ~0; + GLuint i; + GLuint start = IM->FlushElt ? IM->LastPrimitive : IM->CopyStart; + _tnl_translate_array_elts( ctx, IM, start, IM->Count ); + + /* Need to recompute andflag. + */ + if (IM->CopyAndFlag & VERT_ELT) + IM->CopyAndFlag |= ctx->Array._Enabled; + else { + for (i = IM->CopyStart ; i < IM->Count ; i++) + andflag &= IM->Flag[i]; + IM->CopyAndFlag = andflag; + } + } + + _tnl_fixup_input( ctx, IM ); +/* _tnl_print_cassette( IM ); */ + _tnl_run_cassette( ctx, IM ); +} + + + +/* Called for all cassettes when not compiling or playing a display + * list. + */ +void _tnl_execute_cassette( GLcontext *ctx, struct immediate *IM ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + + ASSERT(tnl->ExecCopySource == IM); + + _tnl_compute_orflag( IM ); + + /* Mark the last primitive: + */ + IM->PrimitiveLength[IM->LastPrimitive] = IM->Count - IM->LastPrimitive; + ASSERT(IM->Primitive[IM->LastPrimitive] & PRIM_LAST); + + + if (tnl->pipeline.build_state_changes) + _tnl_validate_pipeline( ctx ); + + _tnl_get_exec_copy_verts( ctx, IM ); + + if (IM->CopyStart == IM->Count) { + exec_empty_cassette( ctx, IM ); + } + else if ((IM->OrFlag & VERT_DATA) == VERT_ELT && + ctx->Array.LockCount && + ctx->Array.Vertex.Enabled) { + exec_elt_cassette( ctx, IM ); + } + else { + exec_vert_cassette( ctx, IM ); + } + + _tnl_reset_input( ctx, + IMM_MAX_COPIED_VERTS, + IM->BeginState & (VERT_BEGIN_0|VERT_BEGIN_1), + IM->SavedBeginState ); + + /* Copy vertices and primitive information to immediate before it + * can be overwritten. + */ + _tnl_copy_immediate_vertices( ctx, IM ); + +/* if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) */ +/* ctx->Driver.NeedFlush &= ~FLUSH_STORED_VERTICES; */ +} + + + + +/* Setup vector pointers that will be used to bind immediates to VB's. + */ +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 = TNL_CURRENT_IM(ctx); + TNL_CURRENT_IM(ctx)->ref_count++; + TNL_CURRENT_IM(ctx)->CopyStart = IMM_MAX_COPIED_VERTS; + + gl_vector4f_init( &tmp->Obj, 0, 0 ); + gl_vector3f_init( &tmp->Normal, 0, 0 ); + gl_vector4ub_init( &tmp->Color, 0, 0 ); + gl_vector4ub_init( &tmp->SecondaryColor, 0, 0 ); + gl_vector1f_init( &tmp->FogCoord, 0, 0 ); + gl_vector1ui_init( &tmp->Index, 0, 0 ); + gl_vector1ub_init( &tmp->EdgeFlag, 0, 0 ); + + for (i = 0; i < ctx->Const.MaxTextureUnits; i++) + gl_vector4f_init( &tmp->TexCoord[i], 0, 0); + + /* Install the first immediate. Intially outside begin/end. + */ + _tnl_reset_input( ctx, IMM_MAX_COPIED_VERTS, 0, 0 ); + tnl->ReplayHardBeginEnd = 0; + + _tnl_imm_vtxfmt_init( ctx ); +} + + +void _tnl_imm_destroy( GLcontext *ctx ) +{ + if (TNL_CURRENT_IM(ctx)) + _tnl_free_immediate( TNL_CURRENT_IM(ctx) ); + +} |