diff options
Diffstat (limited to 'mesalib/src/mesa/tnl')
27 files changed, 9228 insertions, 9221 deletions
diff --git a/mesalib/src/mesa/tnl/NOTES b/mesalib/src/mesa/tnl/NOTES new file mode 100644 index 000000000..9a35e948b --- /dev/null +++ b/mesalib/src/mesa/tnl/NOTES @@ -0,0 +1,102 @@ +INTRODUCTION
+
+A generic, configurable software implementation of GL transformation &
+lighting.
+
+This module provides an implementation of the routines required by the
+'vtxfmt' mechanism of core mesa for tnl functionality in all
+combinations of compile and execute modes.
+
+Most current drivers use the tnl module exclusively to provide this
+functionality, though there is an experimental alternate
+implementation provided by the tnl_dd/t_dd_imm_* files which can
+handle a small subset of GL states in execute mode only.
+
+
+STATE
+
+To create and destroy the module:
+
+ GLboolean _tnl_CreateContext( struct gl_context *ctx );
+ void _tnl_DestroyContext( struct gl_context *ctx );
+
+The module is not active by default, and must be installed by calling
+_tnl_Wakeup(). This function installs internal tnl functions into all
+the vtxfmt dispatch hooks, thus taking over the task of transformation
+and lighting entirely:
+
+ void _tnl_wakeup_exec( struct gl_context *ctx );
+ void _tnl_wakeup_save_exec( struct gl_context *ctx );
+
+
+This module tracks state changes internally and maintains derived
+values based on the current state. For this to work, the driver
+ensure the following funciton is called whenever the state changes and
+the swsetup module is 'awake':
+
+ void _tnl_InvalidateState( struct gl_context *ctx, GLuint new_state );
+
+There is no explicit call to put the tnl module to sleep. Simply
+install other function pointers into all the vtxfmt dispatch slots,
+and (optionally) cease calling _tnl_InvalidateState().
+
+CUSTOMIZATION
+
+The module provides customizability through several mechanisms. The
+most important is by allowing drivers to specify the pipeline through
+which vertex data is passed, including its eventual transfer to
+rasterization hardware (or software).
+
+The default pipeline is specified in t_pipeline.c, and is usually a
+starting point for driver pipelines. Some drivers will remove a stage
+where hardware provides support for the implemented operation (for
+instance fog where per-pixel hardware fog is available, as in the dri
+tdfx driver), or add stages to shortcircuit latter operations (for
+example taking advantage of hardware support for strips and other
+higher-level primitives (for example the radeon driver).
+
+In addition, the following functions provide further tweaks:
+
+extern void
+_tnl_need_projected_coords( struct gl_context *ctx, GLboolean flag );
+
+ - Direct the default vertex transformation stage to
+ produce/not produce projected clip coordinates.
+
+extern void
+_tnl_need_dlist_loopback( struct gl_context *ctx, GLboolean flag );
+
+ - Direct the display list component of the tnl module to
+ replay display lists as 'glVertex' type calls, rather than
+ passing the display list data directly into the tnl pipeline
+ mechanism.
+
+ This allows display lists to be replayed by the tnl module
+ even when the module is not strictly active.
+
+
+extern void
+_tnl_need_dlist_norm_lengths( struct gl_context *ctx, GLboolean flag );
+
+ - Direct the display list component to enable/disable caching
+ 1/length values for display list normals. Doing so is
+ ususally helpful when lighting is performed in software, but
+ wasteful otherwise.
+
+
+DRIVER INTERFACE
+
+The module itself offers a minimal driver interface:
+
+ void (*RunPipeline)( struct gl_context *ctx );
+
+Normally this is set to _tnl_RunPipeline(), however the driver can use
+this hook to wrap checks or other code around this call.
+
+In addition, the driver interface for the default render pipeline
+stage is housed in the tnl context struct (this could be cleaner).
+
+
+RENDER DRIVER INTERFACE
+
+See t_context.h for the definition and explanation of this.
\ No newline at end of file diff --git a/mesalib/src/mesa/tnl/t_context.c b/mesalib/src/mesa/tnl/t_context.c index f27c8ad9d..f27f2d090 100644 --- a/mesalib/src/mesa/tnl/t_context.c +++ b/mesalib/src/mesa/tnl/t_context.c @@ -1,223 +1,223 @@ -/* - * Mesa 3-D graphics library - * Version: 7.2 - * - * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Keith Whitwell <keith@tungstengraphics.com> - */ - - -#include "main/glheader.h" -#include "main/imports.h" -#include "main/context.h" -#include "main/macros.h" -#include "main/mtypes.h" -#include "main/light.h" -#include "math/m_translate.h" -#include "math/m_xform.h" - -#include "tnl.h" -#include "t_context.h" -#include "t_pipeline.h" - -#include "vbo/vbo.h" - -GLboolean -_tnl_CreateContext( GLcontext *ctx ) -{ - TNLcontext *tnl; - - /* Create the TNLcontext structure - */ - ctx->swtnl_context = tnl = (TNLcontext *) CALLOC( sizeof(TNLcontext) ); - - if (!tnl) { - return GL_FALSE; - } - - /* Initialize the VB. - */ - tnl->vb.Size = ctx->Const.MaxArrayLockSize + MAX_CLIPPED_VERTICES; - - - /* Initialize tnl state. - */ - if (ctx->VertexProgram._MaintainTnlProgram) { - _tnl_install_pipeline( ctx, _tnl_vp_pipeline ); - } else { - _tnl_install_pipeline( ctx, _tnl_default_pipeline ); - } - - tnl->NeedNdcCoords = GL_TRUE; - tnl->AllowVertexFog = GL_TRUE; - tnl->AllowPixelFog = GL_TRUE; - - /* Set a few default values in the driver struct. - */ - tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts; - tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts; - tnl->Driver.NotifyMaterialChange = _mesa_validate_all_lighting_tables; - - tnl->nr_blocks = 0; - - /* plug in the VBO drawing function */ - vbo_set_draw_func(ctx, _tnl_vbo_draw_prims); - - _math_init_transformation(); - _math_init_translate(); - - return GL_TRUE; -} - - -void -_tnl_DestroyContext( GLcontext *ctx ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - - _tnl_destroy_pipeline( ctx ); - - FREE(tnl); - ctx->swtnl_context = NULL; -} - - -void -_tnl_InvalidateState( GLcontext *ctx, GLuint new_state ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - const struct gl_vertex_program *vp = ctx->VertexProgram._Current; - const struct gl_fragment_program *fp = ctx->FragmentProgram._Current; - GLuint i; - - if (new_state & (_NEW_HINT | _NEW_PROGRAM)) { - ASSERT(tnl->AllowVertexFog || tnl->AllowPixelFog); - tnl->_DoVertexFog = ((tnl->AllowVertexFog && (ctx->Hint.Fog != GL_NICEST)) - || !tnl->AllowPixelFog) && !fp; - } - - tnl->pipeline.new_state |= new_state; - - /* Calculate tnl->render_inputs. This bitmask indicates which vertex - * attributes need to be emitted to the rasterizer. - */ - RENDERINPUTS_ZERO( tnl->render_inputs_bitset ); - RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_POS ); - - if (!fp || (fp->Base.InputsRead & FRAG_BIT_COL0)) { - RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_COLOR0 ); - } - - if (NEED_SECONDARY_COLOR(ctx)) - RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_COLOR1 ); - - for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { - if (ctx->Texture._EnabledCoordUnits & (1 << i) || - (fp && fp->Base.InputsRead & FRAG_BIT_TEX(i))) { - RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_TEX(i) ); - } - } - - if (ctx->Fog.Enabled) { - /* fixed-function fog */ - RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_FOG ); - } - else if (fp) { - if (fp->FogOption != GL_NONE || (fp->Base.InputsRead & FRAG_BIT_FOGC)) { - /* fragment program needs fog coord */ - RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_FOG ); - } - } - - if (ctx->Polygon.FrontMode != GL_FILL || - ctx->Polygon.BackMode != GL_FILL) - RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_EDGEFLAG ); - - if (ctx->RenderMode == GL_FEEDBACK) - RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_TEX0 ); - - if (ctx->Point._Attenuated || - (ctx->VertexProgram._Enabled && ctx->VertexProgram.PointSizeEnabled)) - RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_POINTSIZE ); - - /* check for varying vars which are written by the vertex program */ - if (vp) { - GLuint i; - for (i = 0; i < MAX_VARYING; i++) { - if (vp->Base.OutputsWritten & BITFIELD64_BIT(VERT_RESULT_VAR0 + i)) { - RENDERINPUTS_SET(tnl->render_inputs_bitset, - _TNL_ATTRIB_GENERIC(i)); - } - } - } -} - - -void -_tnl_wakeup( GLcontext *ctx ) -{ - /* Assume we haven't been getting state updates either: - */ - _tnl_InvalidateState( ctx, ~0 ); - -#if 0 - if (ctx->Light.ColorMaterialEnabled) { - _mesa_update_color_material( ctx, - ctx->Current.Attrib[VERT_ATTRIB_COLOR0] ); - } -#endif -} - - - - -/** - * Drivers call this function to tell the TCL module whether or not - * it wants Normalized Device Coords (NDC) computed. I.e. whether - * we should "Divide-by-W". Software renders will want that. - */ -void -_tnl_need_projected_coords( GLcontext *ctx, GLboolean mode ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - tnl->NeedNdcCoords = mode; -} - -void -_tnl_allow_vertex_fog( GLcontext *ctx, GLboolean value ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - tnl->AllowVertexFog = value; - tnl->_DoVertexFog = ((tnl->AllowVertexFog && (ctx->Hint.Fog != GL_NICEST)) - || !tnl->AllowPixelFog) && !ctx->FragmentProgram._Current; - -} - -void -_tnl_allow_pixel_fog( GLcontext *ctx, GLboolean value ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - tnl->AllowPixelFog = value; - tnl->_DoVertexFog = ((tnl->AllowVertexFog && (ctx->Hint.Fog != GL_NICEST)) - || !tnl->AllowPixelFog) && !ctx->FragmentProgram._Current; -} - +/*
+ * Mesa 3-D graphics library
+ * Version: 7.2
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "main/glheader.h"
+#include "main/imports.h"
+#include "main/context.h"
+#include "main/macros.h"
+#include "main/mtypes.h"
+#include "main/light.h"
+#include "math/m_translate.h"
+#include "math/m_xform.h"
+
+#include "tnl.h"
+#include "t_context.h"
+#include "t_pipeline.h"
+
+#include "vbo/vbo.h"
+
+GLboolean
+_tnl_CreateContext( struct gl_context *ctx )
+{
+ TNLcontext *tnl;
+
+ /* Create the TNLcontext structure
+ */
+ ctx->swtnl_context = tnl = (TNLcontext *) CALLOC( sizeof(TNLcontext) );
+
+ if (!tnl) {
+ return GL_FALSE;
+ }
+
+ /* Initialize the VB.
+ */
+ tnl->vb.Size = ctx->Const.MaxArrayLockSize + MAX_CLIPPED_VERTICES;
+
+
+ /* Initialize tnl state.
+ */
+ if (ctx->VertexProgram._MaintainTnlProgram) {
+ _tnl_install_pipeline( ctx, _tnl_vp_pipeline );
+ } else {
+ _tnl_install_pipeline( ctx, _tnl_default_pipeline );
+ }
+
+ tnl->NeedNdcCoords = GL_TRUE;
+ tnl->AllowVertexFog = GL_TRUE;
+ tnl->AllowPixelFog = GL_TRUE;
+
+ /* Set a few default values in the driver struct.
+ */
+ tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts;
+ tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts;
+ tnl->Driver.NotifyMaterialChange = _mesa_validate_all_lighting_tables;
+
+ tnl->nr_blocks = 0;
+
+ /* plug in the VBO drawing function */
+ vbo_set_draw_func(ctx, _tnl_vbo_draw_prims);
+
+ _math_init_transformation();
+ _math_init_translate();
+
+ return GL_TRUE;
+}
+
+
+void
+_tnl_DestroyContext( struct gl_context *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ _tnl_destroy_pipeline( ctx );
+
+ FREE(tnl);
+ ctx->swtnl_context = NULL;
+}
+
+
+void
+_tnl_InvalidateState( struct gl_context *ctx, GLuint new_state )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ const struct gl_vertex_program *vp = ctx->VertexProgram._Current;
+ const struct gl_fragment_program *fp = ctx->FragmentProgram._Current;
+ GLuint i;
+
+ if (new_state & (_NEW_HINT | _NEW_PROGRAM)) {
+ ASSERT(tnl->AllowVertexFog || tnl->AllowPixelFog);
+ tnl->_DoVertexFog = ((tnl->AllowVertexFog && (ctx->Hint.Fog != GL_NICEST))
+ || !tnl->AllowPixelFog) && !fp;
+ }
+
+ tnl->pipeline.new_state |= new_state;
+
+ /* Calculate tnl->render_inputs. This bitmask indicates which vertex
+ * attributes need to be emitted to the rasterizer.
+ */
+ RENDERINPUTS_ZERO( tnl->render_inputs_bitset );
+ RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_POS );
+
+ if (!fp || (fp->Base.InputsRead & FRAG_BIT_COL0)) {
+ RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_COLOR0 );
+ }
+
+ if (NEED_SECONDARY_COLOR(ctx))
+ RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_COLOR1 );
+
+ for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
+ if (ctx->Texture._EnabledCoordUnits & (1 << i) ||
+ (fp && fp->Base.InputsRead & FRAG_BIT_TEX(i))) {
+ RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_TEX(i) );
+ }
+ }
+
+ if (ctx->Fog.Enabled) {
+ /* fixed-function fog */
+ RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_FOG );
+ }
+ else if (fp) {
+ if (fp->FogOption != GL_NONE || (fp->Base.InputsRead & FRAG_BIT_FOGC)) {
+ /* fragment program needs fog coord */
+ RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_FOG );
+ }
+ }
+
+ if (ctx->Polygon.FrontMode != GL_FILL ||
+ ctx->Polygon.BackMode != GL_FILL)
+ RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_EDGEFLAG );
+
+ if (ctx->RenderMode == GL_FEEDBACK)
+ RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_TEX0 );
+
+ if (ctx->Point._Attenuated ||
+ (ctx->VertexProgram._Enabled && ctx->VertexProgram.PointSizeEnabled))
+ RENDERINPUTS_SET( tnl->render_inputs_bitset, _TNL_ATTRIB_POINTSIZE );
+
+ /* check for varying vars which are written by the vertex program */
+ if (vp) {
+ GLuint i;
+ for (i = 0; i < MAX_VARYING; i++) {
+ if (vp->Base.OutputsWritten & BITFIELD64_BIT(VERT_RESULT_VAR0 + i)) {
+ RENDERINPUTS_SET(tnl->render_inputs_bitset,
+ _TNL_ATTRIB_GENERIC(i));
+ }
+ }
+ }
+}
+
+
+void
+_tnl_wakeup( struct gl_context *ctx )
+{
+ /* Assume we haven't been getting state updates either:
+ */
+ _tnl_InvalidateState( ctx, ~0 );
+
+#if 0
+ if (ctx->Light.ColorMaterialEnabled) {
+ _mesa_update_color_material( ctx,
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR0] );
+ }
+#endif
+}
+
+
+
+
+/**
+ * Drivers call this function to tell the TCL module whether or not
+ * it wants Normalized Device Coords (NDC) computed. I.e. whether
+ * we should "Divide-by-W". Software renders will want that.
+ */
+void
+_tnl_need_projected_coords( struct gl_context *ctx, GLboolean mode )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl->NeedNdcCoords = mode;
+}
+
+void
+_tnl_allow_vertex_fog( struct gl_context *ctx, GLboolean value )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl->AllowVertexFog = value;
+ tnl->_DoVertexFog = ((tnl->AllowVertexFog && (ctx->Hint.Fog != GL_NICEST))
+ || !tnl->AllowPixelFog) && !ctx->FragmentProgram._Current;
+
+}
+
+void
+_tnl_allow_pixel_fog( struct gl_context *ctx, GLboolean value )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl->AllowPixelFog = value;
+ tnl->_DoVertexFog = ((tnl->AllowVertexFog && (ctx->Hint.Fog != GL_NICEST))
+ || !tnl->AllowPixelFog) && !ctx->FragmentProgram._Current;
+}
+
diff --git a/mesalib/src/mesa/tnl/t_context.h b/mesalib/src/mesa/tnl/t_context.h index 258906f79..ecc4e2aa4 100644 --- a/mesalib/src/mesa/tnl/t_context.h +++ b/mesalib/src/mesa/tnl/t_context.h @@ -1,545 +1,545 @@ -/* - * mesa 3-D graphics library - * Version: 6.5 - * - * Copyright (C) 1999-2006 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 t_context.h - * \brief TnL module datatypes and definitions. - * \author Keith Whitwell - */ - - -/** - * \mainpage The TNL-module - * - * TNL stands for "transform and lighting", i.e. this module implements - * a pipeline that receives as input a buffer of vertices and does all - * necessary transformations (rotations, clipping, vertex shader etc.) - * and passes then the output to the rasterizer. - * - * The tnl_pipeline contains the array of all stages, which should be - * applied. Each stage is a black-box, which is described by an - * 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. - * - */ - - -#ifndef _T_CONTEXT_H -#define _T_CONTEXT_H - -#include "main/glheader.h" -#include "main/bitset.h" -#include "main/mtypes.h" - -#include "math/m_vector.h" - -#include "vbo/vbo.h" - -#define MAX_PIPELINE_STAGES 30 - -/* - * Note: The first attributes match the VERT_ATTRIB_* definitions - * in mtypes.h. However, the tnl module has additional attributes - * for materials, color indexes, edge flags, etc. - */ -/* Although it's nice to use these as bit indexes in a DWORD flag, we - * could manage without if necessary. Another limit currently is the - * number of bits allocated for these numbers in places like vertex - * program instruction formats and register layouts. - */ -/* The bit space exhaustion is a fact now, done by _TNL_ATTRIB_ATTRIBUTE* for - * GLSL vertex shader which cannot be aliased with conventional vertex attribs. - * Compacting _TNL_ATTRIB_MAT_* attribs would not work, they would not give - * as many free bits (11 plus already 1 free bit) as _TNL_ATTRIB_ATTRIBUTE* - * attribs want (16). - */ -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_COLOR_INDEX = 6, - _TNL_ATTRIB_EDGEFLAG = 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_GENERIC0 = 16, /* doesn't really exist! */ - _TNL_ATTRIB_GENERIC1 = 17, - _TNL_ATTRIB_GENERIC2 = 18, - _TNL_ATTRIB_GENERIC3 = 19, - _TNL_ATTRIB_GENERIC4 = 20, - _TNL_ATTRIB_GENERIC5 = 21, - _TNL_ATTRIB_GENERIC6 = 22, - _TNL_ATTRIB_GENERIC7 = 23, - _TNL_ATTRIB_GENERIC8 = 24, - _TNL_ATTRIB_GENERIC9 = 25, - _TNL_ATTRIB_GENERIC10 = 26, - _TNL_ATTRIB_GENERIC11 = 27, - _TNL_ATTRIB_GENERIC12 = 28, - _TNL_ATTRIB_GENERIC13 = 29, - _TNL_ATTRIB_GENERIC14 = 30, - _TNL_ATTRIB_GENERIC15 = 31, - - /* These alias with the generics, but they are not active - * concurrently, so it's not a problem. The TNL module - * doesn't have to do anything about this as this is how they - * are passed into the _draw_prims callback. - * - * When we generate fixed-function replacement programs (in - * t_vp_build.c currently), they refer to the appropriate - * generic attribute in order to pick up per-vertex material - * data. - */ - _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, - - /* This is really a VERT_RESULT, not an attrib. Need to fix - * tnl to understand the difference. - */ - _TNL_ATTRIB_POINTSIZE = 16, - - _TNL_ATTRIB_MAX = 32 -} ; - -#define _TNL_ATTRIB_TEX(u) (_TNL_ATTRIB_TEX0 + (u)) -#define _TNL_ATTRIB_GENERIC(n) (_TNL_ATTRIB_GENERIC0 + (n)) - -/* special index used for handing invalid glVertexAttribute() indices */ -#define _TNL_ATTRIB_ERROR (_TNL_ATTRIB_GENERIC15 + 1) - -/** - * Handy attribute ranges: - */ -#define _TNL_FIRST_PROG _TNL_ATTRIB_WEIGHT -#define _TNL_LAST_PROG _TNL_ATTRIB_TEX7 - -#define _TNL_FIRST_TEX _TNL_ATTRIB_TEX0 -#define _TNL_LAST_TEX _TNL_ATTRIB_TEX7 - -#define _TNL_FIRST_GENERIC _TNL_ATTRIB_GENERIC0 -#define _TNL_LAST_GENERIC _TNL_ATTRIB_GENERIC15 - -#define _TNL_FIRST_MAT _TNL_ATTRIB_MAT_FRONT_AMBIENT /* GENERIC0 */ -#define _TNL_LAST_MAT _TNL_ATTRIB_MAT_BACK_INDEXES /* GENERIC11 */ - -/* Number of available generic attributes */ -#define _TNL_NUM_GENERIC 16 - -/* Number of attributes used for evaluators */ -#define _TNL_NUM_EVAL 16 - - -#define PRIM_BEGIN 0x10 -#define PRIM_END 0x20 -#define PRIM_MODE_MASK 0x0f - -static INLINE GLuint _tnl_translate_prim( const struct _mesa_prim *prim ) -{ - GLuint flag; - flag = prim->mode; - if (prim->begin) flag |= PRIM_BEGIN; - if (prim->end) flag |= PRIM_END; - return flag; -} - - - - -/** - * Contains the current state of a running pipeline. - */ -struct vertex_buffer -{ - GLuint Size; /**< Max vertices per vertex buffer, constant */ - - /* Constant over the pipeline. - */ - GLuint Count; /**< Number of vertices currently in buffer */ - - /* Pointers to current data. Most of the data is in AttribPtr -- all of - * it that is one of VERT_ATTRIB_X. For things only produced by TNL, - * such as backface color or eye-space coordinates, they are stored - * here. - */ - GLuint *Elts; - GLvector4f *EyePtr; /* _TNL_BIT_POS */ - GLvector4f *ClipPtr; /* _TNL_BIT_POS */ - GLvector4f *NdcPtr; /* _TNL_BIT_POS */ - GLubyte ClipOrMask; /* _TNL_BIT_POS */ - GLubyte ClipAndMask; /* _TNL_BIT_POS */ - GLubyte *ClipMask; /* _TNL_BIT_POS */ - GLfloat *NormalLengthPtr; /* _TNL_BIT_NORMAL */ - GLboolean *EdgeFlag; /* _TNL_BIT_EDGEFLAG */ - GLvector4f *BackfaceIndexPtr; - GLvector4f *BackfaceColorPtr; - GLvector4f *BackfaceSecondaryColorPtr; - - const struct _mesa_prim *Primitive; - GLuint PrimitiveCount; - - /* Inputs to the vertex program stage */ - GLvector4f *AttribPtr[_TNL_ATTRIB_MAX]; /* GL_NV_vertex_program */ -}; - - -/** - * Describes an individual operation on the pipeline. - */ -struct tnl_pipeline_stage -{ - const char *name; - - /* Private data for the pipeline stage: - */ - void *privatePtr; - - /* Allocate private data - */ - GLboolean (*create)( GLcontext *ctx, struct tnl_pipeline_stage * ); - - /* Free private data. - */ - void (*destroy)( struct tnl_pipeline_stage * ); - - /* Called on any statechange or input array size change or - * input array change to/from zero stride. - */ - void (*validate)( 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 - * non-zero, recompute all affected outputs of the stage, otherwise - * execute any 'sideeffects' of the stage. - * - * Return value: GL_TRUE - keep going - * GL_FALSE - finished pipeline - */ - 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 tnl_pipeline { - - GLuint last_attrib_stride[_TNL_ATTRIB_MAX]; - GLuint last_attrib_size[_TNL_ATTRIB_MAX]; - GLuint input_changes; - GLuint new_state; - - struct tnl_pipeline_stage stages[MAX_PIPELINE_STAGES+1]; - GLuint nr_stages; -}; - -struct tnl_clipspace; -struct tnl_clipspace_attr; - -typedef void (*tnl_extract_func)( const struct tnl_clipspace_attr *a, - GLfloat *out, - const GLubyte *v ); - -typedef void (*tnl_insert_func)( const struct tnl_clipspace_attr *a, - GLubyte *v, - const GLfloat *in ); - -typedef void (*tnl_emit_func)( GLcontext *ctx, - GLuint count, - GLubyte *dest ); - - -/** - * Describes how to convert/move a vertex attribute from a vertex array - * to a vertex structure. - */ -struct tnl_clipspace_attr -{ - GLuint attrib; /* which vertex attrib (0=position, etc) */ - GLuint format; - GLuint vertoffset; /* position of the attrib in the vertex struct */ - GLuint vertattrsize; /* size of the attribute in bytes */ - GLubyte *inputptr; - GLuint inputstride; - GLuint inputsize; - const tnl_insert_func *insert; - tnl_insert_func emit; - tnl_extract_func extract; - const GLfloat *vp; /* NDC->Viewport mapping matrix */ -}; - - - - -typedef void (*tnl_points_func)( GLcontext *ctx, GLuint first, GLuint last ); -typedef void (*tnl_line_func)( GLcontext *ctx, GLuint v1, GLuint v2 ); -typedef void (*tnl_triangle_func)( GLcontext *ctx, - GLuint v1, GLuint v2, GLuint v3 ); -typedef void (*tnl_quad_func)( GLcontext *ctx, GLuint v1, GLuint v2, - GLuint v3, GLuint v4 ); -typedef void (*tnl_render_func)( GLcontext *ctx, GLuint start, GLuint count, - GLuint flags ); -typedef void (*tnl_interp_func)( GLcontext *ctx, - GLfloat t, GLuint dst, GLuint out, GLuint in, - GLboolean force_boundary ); -typedef void (*tnl_copy_pv_func)( GLcontext *ctx, GLuint dst, GLuint src ); -typedef void (*tnl_setup_func)( GLcontext *ctx, - GLuint start, GLuint end, - GLuint new_inputs); - - -struct tnl_attr_type { - GLuint format; - GLuint size; - GLuint stride; - GLuint offset; -}; - -struct tnl_clipspace_fastpath { - GLuint vertex_size; - GLuint attr_count; - GLboolean match_strides; - - struct tnl_attr_type *attr; - - tnl_emit_func func; - struct tnl_clipspace_fastpath *next; -}; - -/** - * Used to describe conversion of vertex arrays to vertex structures. - * I.e. Structure of arrays to arrays of structs. - */ -struct tnl_clipspace -{ - GLboolean need_extras; - - GLuint new_inputs; - - GLubyte *vertex_buf; - GLuint vertex_size; - GLuint max_vertex_size; - - struct tnl_clipspace_attr attr[_TNL_ATTRIB_MAX]; - GLuint attr_count; - - tnl_emit_func emit; - tnl_interp_func interp; - tnl_copy_pv_func copy_pv; - - /* Parameters and constants for codegen: - */ - GLboolean need_viewport; - GLfloat vp_scale[4]; - GLfloat vp_xlate[4]; - GLfloat chan_scale[4]; - GLfloat identity[4]; - - struct tnl_clipspace_fastpath *fastpath; - - void (*codegen_emit)( GLcontext *ctx ); -}; - - -struct tnl_device_driver -{ - /*** - *** TNL Pipeline - ***/ - - void (*RunPipeline)(GLcontext *ctx); - /* Replaces PipelineStart/PipelineFinish -- intended to allow - * drivers to wrap _tnl_run_pipeline() with code to validate state - * and grab/release hardware locks. - */ - - void (*NotifyMaterialChange)(GLcontext *ctx); - /* Alert tnl-aware drivers of changes to material. - */ - - /*** - *** Rendering -- These functions called only from t_vb_render.c - ***/ - struct - { - void (*Start)(GLcontext *ctx); - void (*Finish)(GLcontext *ctx); - /* Called before and after all rendering operations, including DrawPixels, - * ReadPixels, Bitmap, span functions, and CopyTexImage, etc commands. - * These are a suitable place for grabbing/releasing hardware locks. - */ - - void (*PrimitiveNotify)(GLcontext *ctx, GLenum mode); - /* Called between RenderStart() and RenderFinish() to indicate the - * type of primitive we're about to draw. Mode will be one of the - * modes accepted by glBegin(). - */ - - tnl_interp_func Interp; - /* The interp function is called by the clipping routines when we need - * to generate an interpolated vertex. All pertinant vertex ancilliary - * data should be computed by interpolating between the 'in' and 'out' - * vertices. - */ - - tnl_copy_pv_func CopyPV; - /* The copy function is used to make a copy of a vertex. All pertinant - * vertex attributes should be copied. - */ - - void (*ClippedPolygon)( GLcontext *ctx, const GLuint *elts, GLuint n ); - /* Render a polygon with <n> vertices whose indexes are in the <elts> - * array. - */ - - void (*ClippedLine)( GLcontext *ctx, GLuint v0, GLuint v1 ); - /* Render a line between the two vertices given by indexes v0 and v1. */ - - tnl_points_func Points; /* must now respect vb->elts */ - tnl_line_func Line; - tnl_triangle_func Triangle; - tnl_quad_func Quad; - /* These functions are called in order to render points, lines, - * triangles and quads. These are only called via the T&L module. - */ - - tnl_render_func *PrimTabVerts; - tnl_render_func *PrimTabElts; - /* Render whole unclipped primitives (points, lines, linestrips, - * lineloops, etc). The tables are indexed by the GL enum of the - * primitive to be rendered. RenderTabVerts is used for non-indexed - * arrays of vertices. RenderTabElts is used for indexed arrays of - * vertices. - */ - - void (*ResetLineStipple)( GLcontext *ctx ); - /* Reset the hardware's line stipple counter. - */ - - tnl_setup_func BuildVertices; - /* This function is called whenever new vertices are required for - * rendering. The vertices in question are those n such that start - * <= n < end. The new_inputs parameter indicates those fields of - * the vertex which need to be updated, if only a partial repair of - * the vertex is required. - * - * This function is called only from _tnl_render_stage in tnl/t_render.c. - */ - - - GLboolean (*Multipass)( GLcontext *ctx, GLuint passno ); - /* Driver may request additional render passes by returning GL_TRUE - * when this function is called. This function will be called - * after the first pass, and passes will be made until the function - * returns GL_FALSE. If no function is registered, only one pass - * is made. - * - * This function will be first invoked with passno == 1. - */ - } Render; -}; - - -#define DECLARE_RENDERINPUTS(name) BITSET64_DECLARE(name, _TNL_ATTRIB_MAX) -#define RENDERINPUTS_COPY BITSET64_COPY -#define RENDERINPUTS_EQUAL BITSET64_EQUAL -#define RENDERINPUTS_ZERO BITSET64_ZERO -#define RENDERINPUTS_ONES BITSET64_ONES -#define RENDERINPUTS_TEST BITSET64_TEST -#define RENDERINPUTS_SET BITSET64_SET -#define RENDERINPUTS_CLEAR BITSET64_CLEAR -#define RENDERINPUTS_TEST_RANGE BITSET64_TEST_RANGE -#define RENDERINPUTS_SET_RANGE BITSET64_SET_RANGE -#define RENDERINPUTS_CLEAR_RANGE BITSET64_CLEAR_RANGE - - -/** - * Context state for T&L context. - */ -typedef struct -{ - /* Driver interface. - */ - struct tnl_device_driver Driver; - - /* Pipeline - */ - struct tnl_pipeline pipeline; - struct vertex_buffer vb; - - /* Clipspace/ndc/window vertex managment: - */ - struct tnl_clipspace clipspace; - - /* Probably need a better configuration mechanism: - */ - GLboolean NeedNdcCoords; - GLboolean AllowVertexFog; - GLboolean AllowPixelFog; - GLboolean _DoVertexFog; /* eval fog function at each vertex? */ - - DECLARE_RENDERINPUTS(render_inputs_bitset); - - GLvector4f tmp_inputs[VERT_ATTRIB_MAX]; - - /* Temp storage for t_draw.c: - */ - GLubyte *block[VERT_ATTRIB_MAX]; - GLuint nr_blocks; - -} TNLcontext; - - - -#define TNL_CONTEXT(ctx) ((TNLcontext *)((ctx)->swtnl_context)) - - -#define TYPE_IDX(t) ((t) & 0xf) -#define MAX_TYPES TYPE_IDX(GL_DOUBLE)+1 /* 0xa + 1 */ - - -extern void -tnl_clip_prepare(GLcontext *ctx); - - -#endif +/*
+ * mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 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 t_context.h
+ * \brief TnL module datatypes and definitions.
+ * \author Keith Whitwell
+ */
+
+
+/**
+ * \mainpage The TNL-module
+ *
+ * TNL stands for "transform and lighting", i.e. this module implements
+ * a pipeline that receives as input a buffer of vertices and does all
+ * necessary transformations (rotations, clipping, vertex shader etc.)
+ * and passes then the output to the rasterizer.
+ *
+ * The tnl_pipeline contains the array of all stages, which should be
+ * applied. Each stage is a black-box, which is described by an
+ * 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.
+ *
+ */
+
+
+#ifndef _T_CONTEXT_H
+#define _T_CONTEXT_H
+
+#include "main/glheader.h"
+#include "main/bitset.h"
+#include "main/mtypes.h"
+
+#include "math/m_vector.h"
+
+#include "vbo/vbo.h"
+
+#define MAX_PIPELINE_STAGES 30
+
+/*
+ * Note: The first attributes match the VERT_ATTRIB_* definitions
+ * in mtypes.h. However, the tnl module has additional attributes
+ * for materials, color indexes, edge flags, etc.
+ */
+/* Although it's nice to use these as bit indexes in a DWORD flag, we
+ * could manage without if necessary. Another limit currently is the
+ * number of bits allocated for these numbers in places like vertex
+ * program instruction formats and register layouts.
+ */
+/* The bit space exhaustion is a fact now, done by _TNL_ATTRIB_ATTRIBUTE* for
+ * GLSL vertex shader which cannot be aliased with conventional vertex attribs.
+ * Compacting _TNL_ATTRIB_MAT_* attribs would not work, they would not give
+ * as many free bits (11 plus already 1 free bit) as _TNL_ATTRIB_ATTRIBUTE*
+ * attribs want (16).
+ */
+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_COLOR_INDEX = 6,
+ _TNL_ATTRIB_EDGEFLAG = 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_GENERIC0 = 16, /* doesn't really exist! */
+ _TNL_ATTRIB_GENERIC1 = 17,
+ _TNL_ATTRIB_GENERIC2 = 18,
+ _TNL_ATTRIB_GENERIC3 = 19,
+ _TNL_ATTRIB_GENERIC4 = 20,
+ _TNL_ATTRIB_GENERIC5 = 21,
+ _TNL_ATTRIB_GENERIC6 = 22,
+ _TNL_ATTRIB_GENERIC7 = 23,
+ _TNL_ATTRIB_GENERIC8 = 24,
+ _TNL_ATTRIB_GENERIC9 = 25,
+ _TNL_ATTRIB_GENERIC10 = 26,
+ _TNL_ATTRIB_GENERIC11 = 27,
+ _TNL_ATTRIB_GENERIC12 = 28,
+ _TNL_ATTRIB_GENERIC13 = 29,
+ _TNL_ATTRIB_GENERIC14 = 30,
+ _TNL_ATTRIB_GENERIC15 = 31,
+
+ /* These alias with the generics, but they are not active
+ * concurrently, so it's not a problem. The TNL module
+ * doesn't have to do anything about this as this is how they
+ * are passed into the _draw_prims callback.
+ *
+ * When we generate fixed-function replacement programs (in
+ * t_vp_build.c currently), they refer to the appropriate
+ * generic attribute in order to pick up per-vertex material
+ * data.
+ */
+ _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,
+
+ /* This is really a VERT_RESULT, not an attrib. Need to fix
+ * tnl to understand the difference.
+ */
+ _TNL_ATTRIB_POINTSIZE = 16,
+
+ _TNL_ATTRIB_MAX = 32
+} ;
+
+#define _TNL_ATTRIB_TEX(u) (_TNL_ATTRIB_TEX0 + (u))
+#define _TNL_ATTRIB_GENERIC(n) (_TNL_ATTRIB_GENERIC0 + (n))
+
+/* special index used for handing invalid glVertexAttribute() indices */
+#define _TNL_ATTRIB_ERROR (_TNL_ATTRIB_GENERIC15 + 1)
+
+/**
+ * Handy attribute ranges:
+ */
+#define _TNL_FIRST_PROG _TNL_ATTRIB_WEIGHT
+#define _TNL_LAST_PROG _TNL_ATTRIB_TEX7
+
+#define _TNL_FIRST_TEX _TNL_ATTRIB_TEX0
+#define _TNL_LAST_TEX _TNL_ATTRIB_TEX7
+
+#define _TNL_FIRST_GENERIC _TNL_ATTRIB_GENERIC0
+#define _TNL_LAST_GENERIC _TNL_ATTRIB_GENERIC15
+
+#define _TNL_FIRST_MAT _TNL_ATTRIB_MAT_FRONT_AMBIENT /* GENERIC0 */
+#define _TNL_LAST_MAT _TNL_ATTRIB_MAT_BACK_INDEXES /* GENERIC11 */
+
+/* Number of available generic attributes */
+#define _TNL_NUM_GENERIC 16
+
+/* Number of attributes used for evaluators */
+#define _TNL_NUM_EVAL 16
+
+
+#define PRIM_BEGIN 0x10
+#define PRIM_END 0x20
+#define PRIM_MODE_MASK 0x0f
+
+static INLINE GLuint _tnl_translate_prim( const struct _mesa_prim *prim )
+{
+ GLuint flag;
+ flag = prim->mode;
+ if (prim->begin) flag |= PRIM_BEGIN;
+ if (prim->end) flag |= PRIM_END;
+ return flag;
+}
+
+
+
+
+/**
+ * Contains the current state of a running pipeline.
+ */
+struct vertex_buffer
+{
+ GLuint Size; /**< Max vertices per vertex buffer, constant */
+
+ /* Constant over the pipeline.
+ */
+ GLuint Count; /**< Number of vertices currently in buffer */
+
+ /* Pointers to current data. Most of the data is in AttribPtr -- all of
+ * it that is one of VERT_ATTRIB_X. For things only produced by TNL,
+ * such as backface color or eye-space coordinates, they are stored
+ * here.
+ */
+ GLuint *Elts;
+ GLvector4f *EyePtr; /* _TNL_BIT_POS */
+ GLvector4f *ClipPtr; /* _TNL_BIT_POS */
+ GLvector4f *NdcPtr; /* _TNL_BIT_POS */
+ GLubyte ClipOrMask; /* _TNL_BIT_POS */
+ GLubyte ClipAndMask; /* _TNL_BIT_POS */
+ GLubyte *ClipMask; /* _TNL_BIT_POS */
+ GLfloat *NormalLengthPtr; /* _TNL_BIT_NORMAL */
+ GLboolean *EdgeFlag; /* _TNL_BIT_EDGEFLAG */
+ GLvector4f *BackfaceIndexPtr;
+ GLvector4f *BackfaceColorPtr;
+ GLvector4f *BackfaceSecondaryColorPtr;
+
+ const struct _mesa_prim *Primitive;
+ GLuint PrimitiveCount;
+
+ /* Inputs to the vertex program stage */
+ GLvector4f *AttribPtr[_TNL_ATTRIB_MAX]; /* GL_NV_vertex_program */
+};
+
+
+/**
+ * Describes an individual operation on the pipeline.
+ */
+struct tnl_pipeline_stage
+{
+ const char *name;
+
+ /* Private data for the pipeline stage:
+ */
+ void *privatePtr;
+
+ /* Allocate private data
+ */
+ GLboolean (*create)( struct gl_context *ctx, struct tnl_pipeline_stage * );
+
+ /* Free private data.
+ */
+ void (*destroy)( struct tnl_pipeline_stage * );
+
+ /* Called on any statechange or input array size change or
+ * input array change to/from zero stride.
+ */
+ void (*validate)( struct gl_context *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
+ * non-zero, recompute all affected outputs of the stage, otherwise
+ * execute any 'sideeffects' of the stage.
+ *
+ * Return value: GL_TRUE - keep going
+ * GL_FALSE - finished pipeline
+ */
+ GLboolean (*run)( struct gl_context *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 tnl_pipeline {
+
+ GLuint last_attrib_stride[_TNL_ATTRIB_MAX];
+ GLuint last_attrib_size[_TNL_ATTRIB_MAX];
+ GLuint input_changes;
+ GLuint new_state;
+
+ struct tnl_pipeline_stage stages[MAX_PIPELINE_STAGES+1];
+ GLuint nr_stages;
+};
+
+struct tnl_clipspace;
+struct tnl_clipspace_attr;
+
+typedef void (*tnl_extract_func)( const struct tnl_clipspace_attr *a,
+ GLfloat *out,
+ const GLubyte *v );
+
+typedef void (*tnl_insert_func)( const struct tnl_clipspace_attr *a,
+ GLubyte *v,
+ const GLfloat *in );
+
+typedef void (*tnl_emit_func)( struct gl_context *ctx,
+ GLuint count,
+ GLubyte *dest );
+
+
+/**
+ * Describes how to convert/move a vertex attribute from a vertex array
+ * to a vertex structure.
+ */
+struct tnl_clipspace_attr
+{
+ GLuint attrib; /* which vertex attrib (0=position, etc) */
+ GLuint format;
+ GLuint vertoffset; /* position of the attrib in the vertex struct */
+ GLuint vertattrsize; /* size of the attribute in bytes */
+ GLubyte *inputptr;
+ GLuint inputstride;
+ GLuint inputsize;
+ const tnl_insert_func *insert;
+ tnl_insert_func emit;
+ tnl_extract_func extract;
+ const GLfloat *vp; /* NDC->Viewport mapping matrix */
+};
+
+
+
+
+typedef void (*tnl_points_func)( struct gl_context *ctx, GLuint first, GLuint last );
+typedef void (*tnl_line_func)( struct gl_context *ctx, GLuint v1, GLuint v2 );
+typedef void (*tnl_triangle_func)( struct gl_context *ctx,
+ GLuint v1, GLuint v2, GLuint v3 );
+typedef void (*tnl_quad_func)( struct gl_context *ctx, GLuint v1, GLuint v2,
+ GLuint v3, GLuint v4 );
+typedef void (*tnl_render_func)( struct gl_context *ctx, GLuint start, GLuint count,
+ GLuint flags );
+typedef void (*tnl_interp_func)( struct gl_context *ctx,
+ GLfloat t, GLuint dst, GLuint out, GLuint in,
+ GLboolean force_boundary );
+typedef void (*tnl_copy_pv_func)( struct gl_context *ctx, GLuint dst, GLuint src );
+typedef void (*tnl_setup_func)( struct gl_context *ctx,
+ GLuint start, GLuint end,
+ GLuint new_inputs);
+
+
+struct tnl_attr_type {
+ GLuint format;
+ GLuint size;
+ GLuint stride;
+ GLuint offset;
+};
+
+struct tnl_clipspace_fastpath {
+ GLuint vertex_size;
+ GLuint attr_count;
+ GLboolean match_strides;
+
+ struct tnl_attr_type *attr;
+
+ tnl_emit_func func;
+ struct tnl_clipspace_fastpath *next;
+};
+
+/**
+ * Used to describe conversion of vertex arrays to vertex structures.
+ * I.e. Structure of arrays to arrays of structs.
+ */
+struct tnl_clipspace
+{
+ GLboolean need_extras;
+
+ GLuint new_inputs;
+
+ GLubyte *vertex_buf;
+ GLuint vertex_size;
+ GLuint max_vertex_size;
+
+ struct tnl_clipspace_attr attr[_TNL_ATTRIB_MAX];
+ GLuint attr_count;
+
+ tnl_emit_func emit;
+ tnl_interp_func interp;
+ tnl_copy_pv_func copy_pv;
+
+ /* Parameters and constants for codegen:
+ */
+ GLboolean need_viewport;
+ GLfloat vp_scale[4];
+ GLfloat vp_xlate[4];
+ GLfloat chan_scale[4];
+ GLfloat identity[4];
+
+ struct tnl_clipspace_fastpath *fastpath;
+
+ void (*codegen_emit)( struct gl_context *ctx );
+};
+
+
+struct tnl_device_driver
+{
+ /***
+ *** TNL Pipeline
+ ***/
+
+ void (*RunPipeline)(struct gl_context *ctx);
+ /* Replaces PipelineStart/PipelineFinish -- intended to allow
+ * drivers to wrap _tnl_run_pipeline() with code to validate state
+ * and grab/release hardware locks.
+ */
+
+ void (*NotifyMaterialChange)(struct gl_context *ctx);
+ /* Alert tnl-aware drivers of changes to material.
+ */
+
+ /***
+ *** Rendering -- These functions called only from t_vb_render.c
+ ***/
+ struct
+ {
+ void (*Start)(struct gl_context *ctx);
+ void (*Finish)(struct gl_context *ctx);
+ /* Called before and after all rendering operations, including DrawPixels,
+ * ReadPixels, Bitmap, span functions, and CopyTexImage, etc commands.
+ * These are a suitable place for grabbing/releasing hardware locks.
+ */
+
+ void (*PrimitiveNotify)(struct gl_context *ctx, GLenum mode);
+ /* Called between RenderStart() and RenderFinish() to indicate the
+ * type of primitive we're about to draw. Mode will be one of the
+ * modes accepted by glBegin().
+ */
+
+ tnl_interp_func Interp;
+ /* The interp function is called by the clipping routines when we need
+ * to generate an interpolated vertex. All pertinant vertex ancilliary
+ * data should be computed by interpolating between the 'in' and 'out'
+ * vertices.
+ */
+
+ tnl_copy_pv_func CopyPV;
+ /* The copy function is used to make a copy of a vertex. All pertinant
+ * vertex attributes should be copied.
+ */
+
+ void (*ClippedPolygon)( struct gl_context *ctx, const GLuint *elts, GLuint n );
+ /* Render a polygon with <n> vertices whose indexes are in the <elts>
+ * array.
+ */
+
+ void (*ClippedLine)( struct gl_context *ctx, GLuint v0, GLuint v1 );
+ /* Render a line between the two vertices given by indexes v0 and v1. */
+
+ tnl_points_func Points; /* must now respect vb->elts */
+ tnl_line_func Line;
+ tnl_triangle_func Triangle;
+ tnl_quad_func Quad;
+ /* These functions are called in order to render points, lines,
+ * triangles and quads. These are only called via the T&L module.
+ */
+
+ tnl_render_func *PrimTabVerts;
+ tnl_render_func *PrimTabElts;
+ /* Render whole unclipped primitives (points, lines, linestrips,
+ * lineloops, etc). The tables are indexed by the GL enum of the
+ * primitive to be rendered. RenderTabVerts is used for non-indexed
+ * arrays of vertices. RenderTabElts is used for indexed arrays of
+ * vertices.
+ */
+
+ void (*ResetLineStipple)( struct gl_context *ctx );
+ /* Reset the hardware's line stipple counter.
+ */
+
+ tnl_setup_func BuildVertices;
+ /* This function is called whenever new vertices are required for
+ * rendering. The vertices in question are those n such that start
+ * <= n < end. The new_inputs parameter indicates those fields of
+ * the vertex which need to be updated, if only a partial repair of
+ * the vertex is required.
+ *
+ * This function is called only from _tnl_render_stage in tnl/t_render.c.
+ */
+
+
+ GLboolean (*Multipass)( struct gl_context *ctx, GLuint passno );
+ /* Driver may request additional render passes by returning GL_TRUE
+ * when this function is called. This function will be called
+ * after the first pass, and passes will be made until the function
+ * returns GL_FALSE. If no function is registered, only one pass
+ * is made.
+ *
+ * This function will be first invoked with passno == 1.
+ */
+ } Render;
+};
+
+
+#define DECLARE_RENDERINPUTS(name) BITSET64_DECLARE(name, _TNL_ATTRIB_MAX)
+#define RENDERINPUTS_COPY BITSET64_COPY
+#define RENDERINPUTS_EQUAL BITSET64_EQUAL
+#define RENDERINPUTS_ZERO BITSET64_ZERO
+#define RENDERINPUTS_ONES BITSET64_ONES
+#define RENDERINPUTS_TEST BITSET64_TEST
+#define RENDERINPUTS_SET BITSET64_SET
+#define RENDERINPUTS_CLEAR BITSET64_CLEAR
+#define RENDERINPUTS_TEST_RANGE BITSET64_TEST_RANGE
+#define RENDERINPUTS_SET_RANGE BITSET64_SET_RANGE
+#define RENDERINPUTS_CLEAR_RANGE BITSET64_CLEAR_RANGE
+
+
+/**
+ * Context state for T&L context.
+ */
+typedef struct
+{
+ /* Driver interface.
+ */
+ struct tnl_device_driver Driver;
+
+ /* Pipeline
+ */
+ struct tnl_pipeline pipeline;
+ struct vertex_buffer vb;
+
+ /* Clipspace/ndc/window vertex managment:
+ */
+ struct tnl_clipspace clipspace;
+
+ /* Probably need a better configuration mechanism:
+ */
+ GLboolean NeedNdcCoords;
+ GLboolean AllowVertexFog;
+ GLboolean AllowPixelFog;
+ GLboolean _DoVertexFog; /* eval fog function at each vertex? */
+
+ DECLARE_RENDERINPUTS(render_inputs_bitset);
+
+ GLvector4f tmp_inputs[VERT_ATTRIB_MAX];
+
+ /* Temp storage for t_draw.c:
+ */
+ GLubyte *block[VERT_ATTRIB_MAX];
+ GLuint nr_blocks;
+
+} TNLcontext;
+
+
+
+#define TNL_CONTEXT(ctx) ((TNLcontext *)((ctx)->swtnl_context))
+
+
+#define TYPE_IDX(t) ((t) & 0xf)
+#define MAX_TYPES TYPE_IDX(GL_DOUBLE)+1 /* 0xa + 1 */
+
+
+extern void
+tnl_clip_prepare(struct gl_context *ctx);
+
+
+#endif
diff --git a/mesalib/src/mesa/tnl/t_draw.c b/mesalib/src/mesa/tnl/t_draw.c index fdde29425..6f152ad53 100644 --- a/mesalib/src/mesa/tnl/t_draw.c +++ b/mesalib/src/mesa/tnl/t_draw.c @@ -1,487 +1,487 @@ -/* - * Mesa 3-D graphics library - * Version: 7.1 - * - * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Keith Whitwell <keith@tungstengraphics.com> - */ - -#include "main/glheader.h" -#include "main/condrender.h" -#include "main/context.h" -#include "main/imports.h" -#include "main/mtypes.h" -#include "main/macros.h" -#include "main/enums.h" - -#include "t_context.h" -#include "tnl.h" - - - -static GLubyte *get_space(GLcontext *ctx, GLuint bytes) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - GLubyte *space = malloc(bytes); - - tnl->block[tnl->nr_blocks++] = space; - return space; -} - - -static void free_space(GLcontext *ctx) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - GLuint i; - for (i = 0; i < tnl->nr_blocks; i++) - free(tnl->block[i]); - tnl->nr_blocks = 0; -} - - -/* Convert the incoming array to GLfloats. Understands the - * array->Normalized flag and selects the correct conversion method. - */ -#define CONVERT( TYPE, MACRO ) do { \ - GLuint i, j; \ - if (input->Normalized) { \ - for (i = 0; i < count; i++) { \ - const TYPE *in = (TYPE *)ptr; \ - for (j = 0; j < sz; j++) { \ - *fptr++ = MACRO(*in); \ - in++; \ - } \ - ptr += input->StrideB; \ - } \ - } else { \ - for (i = 0; i < count; i++) { \ - const TYPE *in = (TYPE *)ptr; \ - for (j = 0; j < sz; j++) { \ - *fptr++ = (GLfloat)(*in); \ - in++; \ - } \ - ptr += input->StrideB; \ - } \ - } \ -} while (0) - - -/** - * Convert array of BGRA/GLubyte[4] values to RGBA/float[4] - * \param ptr input/ubyte array - * \param fptr output/float array - */ -static void -convert_bgra_to_float(const struct gl_client_array *input, - const GLubyte *ptr, GLfloat *fptr, - GLuint count ) -{ - GLuint i; - assert(input->Normalized); - assert(input->Size == 4); - for (i = 0; i < count; i++) { - const GLubyte *in = (GLubyte *) ptr; /* in is in BGRA order */ - *fptr++ = UBYTE_TO_FLOAT(in[2]); /* red */ - *fptr++ = UBYTE_TO_FLOAT(in[1]); /* green */ - *fptr++ = UBYTE_TO_FLOAT(in[0]); /* blue */ - *fptr++ = UBYTE_TO_FLOAT(in[3]); /* alpha */ - ptr += input->StrideB; - } -} - -static void -convert_half_to_float(const struct gl_client_array *input, - const GLubyte *ptr, GLfloat *fptr, - GLuint count, GLuint sz) -{ - GLuint i, j; - - for (i = 0; i < count; i++) { - GLhalfARB *in = (GLhalfARB *)ptr; - - for (j = 0; j < sz; j++) { - *fptr++ = _mesa_half_to_float(in[j]); - } - ptr += input->StrideB; - } -} - -/* Adjust pointer to point at first requested element, convert to - * floating point, populate VB->AttribPtr[]. - */ -static void _tnl_import_array( GLcontext *ctx, - GLuint attrib, - GLuint count, - const struct gl_client_array *input, - const GLubyte *ptr ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - GLuint stride = input->StrideB; - - if (input->Type != GL_FLOAT) { - const GLuint sz = input->Size; - GLubyte *buf = get_space(ctx, count * sz * sizeof(GLfloat)); - GLfloat *fptr = (GLfloat *)buf; - - switch (input->Type) { - case GL_BYTE: - CONVERT(GLbyte, BYTE_TO_FLOAT); - break; - case GL_UNSIGNED_BYTE: - if (input->Format == GL_BGRA) { - /* See GL_EXT_vertex_array_bgra */ - convert_bgra_to_float(input, ptr, fptr, count); - } - else { - CONVERT(GLubyte, UBYTE_TO_FLOAT); - } - break; - case GL_SHORT: - CONVERT(GLshort, SHORT_TO_FLOAT); - break; - case GL_UNSIGNED_SHORT: - CONVERT(GLushort, USHORT_TO_FLOAT); - break; - case GL_INT: - CONVERT(GLint, INT_TO_FLOAT); - break; - case GL_UNSIGNED_INT: - CONVERT(GLuint, UINT_TO_FLOAT); - break; - case GL_DOUBLE: - CONVERT(GLdouble, (GLfloat)); - break; - case GL_HALF_FLOAT: - convert_half_to_float(input, ptr, fptr, count, sz); - break; - default: - assert(0); - break; - } - - ptr = buf; - stride = sz * sizeof(GLfloat); - } - - VB->AttribPtr[attrib] = &tnl->tmp_inputs[attrib]; - VB->AttribPtr[attrib]->data = (GLfloat (*)[4])ptr; - VB->AttribPtr[attrib]->start = (GLfloat *)ptr; - VB->AttribPtr[attrib]->count = count; - VB->AttribPtr[attrib]->stride = stride; - VB->AttribPtr[attrib]->size = input->Size; - - /* This should die, but so should the whole GLvector4f concept: - */ - VB->AttribPtr[attrib]->flags = (((1<<input->Size)-1) | - VEC_NOT_WRITEABLE | - (stride == 4*sizeof(GLfloat) ? 0 : VEC_BAD_STRIDE)); - - VB->AttribPtr[attrib]->storage = NULL; -} - -#define CLIPVERTS ((6 + MAX_CLIP_PLANES) * 2) - - -static GLboolean *_tnl_import_edgeflag( GLcontext *ctx, - const GLvector4f *input, - GLuint count) -{ - const GLubyte *ptr = (const GLubyte *)input->data; - const GLuint stride = input->stride; - GLboolean *space = (GLboolean *)get_space(ctx, count + CLIPVERTS); - GLboolean *bptr = space; - GLuint i; - - for (i = 0; i < count; i++) { - *bptr++ = ((GLfloat *)ptr)[0] == 1.0; - ptr += stride; - } - - return space; -} - - -static void bind_inputs( GLcontext *ctx, - const struct gl_client_array *inputs[], - GLint count, - struct gl_buffer_object **bo, - GLuint *nr_bo ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - GLuint i; - - /* Map all the VBOs - */ - for (i = 0; i < VERT_ATTRIB_MAX; i++) { - const void *ptr; - - if (inputs[i]->BufferObj->Name) { - if (!inputs[i]->BufferObj->Pointer) { - bo[*nr_bo] = inputs[i]->BufferObj; - (*nr_bo)++; - ctx->Driver.MapBuffer(ctx, - GL_ARRAY_BUFFER, - GL_READ_ONLY_ARB, - inputs[i]->BufferObj); - - assert(inputs[i]->BufferObj->Pointer); - } - - ptr = ADD_POINTERS(inputs[i]->BufferObj->Pointer, - inputs[i]->Ptr); - } - else - ptr = inputs[i]->Ptr; - - /* Just make sure the array is floating point, otherwise convert to - * temporary storage. - * - * XXX: remove the GLvector4f type at some stage and just use - * client arrays. - */ - _tnl_import_array(ctx, i, count, inputs[i], ptr); - } - - /* We process only the vertices between min & max index: - */ - VB->Count = count; - - /* These should perhaps be part of _TNL_ATTRIB_* */ - VB->BackfaceColorPtr = NULL; - VB->BackfaceIndexPtr = NULL; - VB->BackfaceSecondaryColorPtr = NULL; - - /* Clipping and drawing code still requires this to be a packed - * array of ubytes which can be written into. TODO: Fix and - * remove. - */ - if (ctx->Polygon.FrontMode != GL_FILL || - ctx->Polygon.BackMode != GL_FILL) - { - VB->EdgeFlag = _tnl_import_edgeflag( ctx, - VB->AttribPtr[_TNL_ATTRIB_EDGEFLAG], - VB->Count ); - } - else { - /* the data previously pointed to by EdgeFlag may have been freed */ - VB->EdgeFlag = NULL; - } -} - - -/* Translate indices to GLuints and store in VB->Elts. - */ -static void bind_indices( GLcontext *ctx, - const struct _mesa_index_buffer *ib, - struct gl_buffer_object **bo, - GLuint *nr_bo) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - GLuint i; - void *ptr; - - if (!ib) { - VB->Elts = NULL; - return; - } - - if (ib->obj->Name && !ib->obj->Pointer) { - bo[*nr_bo] = ib->obj; - (*nr_bo)++; - ctx->Driver.MapBuffer(ctx, - GL_ELEMENT_ARRAY_BUFFER, - GL_READ_ONLY_ARB, - ib->obj); - - assert(ib->obj->Pointer); - } - - ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr); - - if (ib->type == GL_UNSIGNED_INT && VB->Primitive[0].basevertex == 0) { - VB->Elts = (GLuint *) ptr; - } - else { - GLuint *elts = (GLuint *)get_space(ctx, ib->count * sizeof(GLuint)); - VB->Elts = elts; - - if (ib->type == GL_UNSIGNED_INT) { - const GLuint *in = (GLuint *)ptr; - for (i = 0; i < ib->count; i++) - *elts++ = (GLuint)(*in++) + VB->Primitive[0].basevertex; - } - else if (ib->type == GL_UNSIGNED_SHORT) { - const GLushort *in = (GLushort *)ptr; - for (i = 0; i < ib->count; i++) - *elts++ = (GLuint)(*in++) + VB->Primitive[0].basevertex; - } - else { - const GLubyte *in = (GLubyte *)ptr; - for (i = 0; i < ib->count; i++) - *elts++ = (GLuint)(*in++) + VB->Primitive[0].basevertex; - } - } -} - -static void bind_prims( GLcontext *ctx, - const struct _mesa_prim *prim, - GLuint nr_prims ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - - VB->Primitive = prim; - VB->PrimitiveCount = nr_prims; -} - -static void unmap_vbos( GLcontext *ctx, - struct gl_buffer_object **bo, - GLuint nr_bo ) -{ - GLuint i; - for (i = 0; i < nr_bo; i++) { - ctx->Driver.UnmapBuffer(ctx, - 0, /* target -- I don't see why this would be needed */ - bo[i]); - } -} - - -void _tnl_vbo_draw_prims(GLcontext *ctx, - const struct gl_client_array *arrays[], - const struct _mesa_prim *prim, - GLuint nr_prims, - const struct _mesa_index_buffer *ib, - GLboolean index_bounds_valid, - GLuint min_index, - GLuint max_index) -{ - if (!index_bounds_valid) - vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index); - - _tnl_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index); -} - -/* This is the main entrypoint into the slimmed-down software tnl - * module. In a regular swtnl driver, this can be plugged straight - * into the vbo->Driver.DrawPrims() callback. - */ -void _tnl_draw_prims( GLcontext *ctx, - const struct gl_client_array *arrays[], - const struct _mesa_prim *prim, - GLuint nr_prims, - const struct _mesa_index_buffer *ib, - GLuint min_index, - GLuint max_index) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - const GLuint TEST_SPLIT = 0; - const GLint max = TEST_SPLIT ? 8 : tnl->vb.Size - MAX_CLIPPED_VERTICES; - GLint max_basevertex = prim->basevertex; - GLuint i; - - /* Mesa core state should have been validated already */ - assert(ctx->NewState == 0x0); - - if (!_mesa_check_conditional_render(ctx)) - return; /* don't draw */ - - for (i = 1; i < nr_prims; i++) - max_basevertex = MAX2(max_basevertex, prim[i].basevertex); - - if (0) - { - printf("%s %d..%d\n", __FUNCTION__, min_index, max_index); - for (i = 0; i < nr_prims; i++) - printf("prim %d: %s start %d count %d\n", i, - _mesa_lookup_enum_by_nr(prim[i].mode), - prim[i].start, - prim[i].count); - } - - if (min_index) { - /* We always translate away calls with min_index != 0. - */ - vbo_rebase_prims( ctx, arrays, prim, nr_prims, ib, - min_index, max_index, - _tnl_vbo_draw_prims ); - return; - } - else if ((GLint)max_index + max_basevertex > max) { - /* The software TNL pipeline has a fixed amount of storage for - * vertices and it is necessary to split incoming drawing commands - * if they exceed that limit. - */ - struct split_limits limits; - limits.max_verts = max; - limits.max_vb_size = ~0; - limits.max_indices = ~0; - - /* This will split the buffers one way or another and - * recursively call back into this function. - */ - vbo_split_prims( ctx, arrays, prim, nr_prims, ib, - 0, max_index + prim->basevertex, - _tnl_vbo_draw_prims, - &limits ); - } - else { - /* May need to map a vertex buffer object for every attribute plus - * one for the index buffer. - */ - struct gl_buffer_object *bo[VERT_ATTRIB_MAX + 1]; - GLuint nr_bo = 0; - - for (i = 0; i < nr_prims;) { - GLuint this_nr_prims; - - /* Our SW TNL pipeline doesn't handle basevertex yet, so bind_indices - * will rebase the elements to the basevertex, and we'll only - * emit strings of prims with the same basevertex in one draw call. - */ - for (this_nr_prims = 1; i + this_nr_prims < nr_prims; - this_nr_prims++) { - if (prim[i].basevertex != prim[i + this_nr_prims].basevertex) - break; - } - - /* Binding inputs may imply mapping some vertex buffer objects. - * They will need to be unmapped below. - */ - bind_prims(ctx, &prim[i], this_nr_prims); - bind_inputs(ctx, arrays, max_index + prim[i].basevertex + 1, - bo, &nr_bo); - bind_indices(ctx, ib, bo, &nr_bo); - - TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx); - - unmap_vbos(ctx, bo, nr_bo); - free_space(ctx); - - i += this_nr_prims; - } - } -} - +/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "main/glheader.h"
+#include "main/condrender.h"
+#include "main/context.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "main/macros.h"
+#include "main/enums.h"
+
+#include "t_context.h"
+#include "tnl.h"
+
+
+
+static GLubyte *get_space(struct gl_context *ctx, GLuint bytes)
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLubyte *space = malloc(bytes);
+
+ tnl->block[tnl->nr_blocks++] = space;
+ return space;
+}
+
+
+static void free_space(struct gl_context *ctx)
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLuint i;
+ for (i = 0; i < tnl->nr_blocks; i++)
+ free(tnl->block[i]);
+ tnl->nr_blocks = 0;
+}
+
+
+/* Convert the incoming array to GLfloats. Understands the
+ * array->Normalized flag and selects the correct conversion method.
+ */
+#define CONVERT( TYPE, MACRO ) do { \
+ GLuint i, j; \
+ if (input->Normalized) { \
+ for (i = 0; i < count; i++) { \
+ const TYPE *in = (TYPE *)ptr; \
+ for (j = 0; j < sz; j++) { \
+ *fptr++ = MACRO(*in); \
+ in++; \
+ } \
+ ptr += input->StrideB; \
+ } \
+ } else { \
+ for (i = 0; i < count; i++) { \
+ const TYPE *in = (TYPE *)ptr; \
+ for (j = 0; j < sz; j++) { \
+ *fptr++ = (GLfloat)(*in); \
+ in++; \
+ } \
+ ptr += input->StrideB; \
+ } \
+ } \
+} while (0)
+
+
+/**
+ * Convert array of BGRA/GLubyte[4] values to RGBA/float[4]
+ * \param ptr input/ubyte array
+ * \param fptr output/float array
+ */
+static void
+convert_bgra_to_float(const struct gl_client_array *input,
+ const GLubyte *ptr, GLfloat *fptr,
+ GLuint count )
+{
+ GLuint i;
+ assert(input->Normalized);
+ assert(input->Size == 4);
+ for (i = 0; i < count; i++) {
+ const GLubyte *in = (GLubyte *) ptr; /* in is in BGRA order */
+ *fptr++ = UBYTE_TO_FLOAT(in[2]); /* red */
+ *fptr++ = UBYTE_TO_FLOAT(in[1]); /* green */
+ *fptr++ = UBYTE_TO_FLOAT(in[0]); /* blue */
+ *fptr++ = UBYTE_TO_FLOAT(in[3]); /* alpha */
+ ptr += input->StrideB;
+ }
+}
+
+static void
+convert_half_to_float(const struct gl_client_array *input,
+ const GLubyte *ptr, GLfloat *fptr,
+ GLuint count, GLuint sz)
+{
+ GLuint i, j;
+
+ for (i = 0; i < count; i++) {
+ GLhalfARB *in = (GLhalfARB *)ptr;
+
+ for (j = 0; j < sz; j++) {
+ *fptr++ = _mesa_half_to_float(in[j]);
+ }
+ ptr += input->StrideB;
+ }
+}
+
+/* Adjust pointer to point at first requested element, convert to
+ * floating point, populate VB->AttribPtr[].
+ */
+static void _tnl_import_array( struct gl_context *ctx,
+ GLuint attrib,
+ GLuint count,
+ const struct gl_client_array *input,
+ const GLubyte *ptr )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint stride = input->StrideB;
+
+ if (input->Type != GL_FLOAT) {
+ const GLuint sz = input->Size;
+ GLubyte *buf = get_space(ctx, count * sz * sizeof(GLfloat));
+ GLfloat *fptr = (GLfloat *)buf;
+
+ switch (input->Type) {
+ case GL_BYTE:
+ CONVERT(GLbyte, BYTE_TO_FLOAT);
+ break;
+ case GL_UNSIGNED_BYTE:
+ if (input->Format == GL_BGRA) {
+ /* See GL_EXT_vertex_array_bgra */
+ convert_bgra_to_float(input, ptr, fptr, count);
+ }
+ else {
+ CONVERT(GLubyte, UBYTE_TO_FLOAT);
+ }
+ break;
+ case GL_SHORT:
+ CONVERT(GLshort, SHORT_TO_FLOAT);
+ break;
+ case GL_UNSIGNED_SHORT:
+ CONVERT(GLushort, USHORT_TO_FLOAT);
+ break;
+ case GL_INT:
+ CONVERT(GLint, INT_TO_FLOAT);
+ break;
+ case GL_UNSIGNED_INT:
+ CONVERT(GLuint, UINT_TO_FLOAT);
+ break;
+ case GL_DOUBLE:
+ CONVERT(GLdouble, (GLfloat));
+ break;
+ case GL_HALF_FLOAT:
+ convert_half_to_float(input, ptr, fptr, count, sz);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ ptr = buf;
+ stride = sz * sizeof(GLfloat);
+ }
+
+ VB->AttribPtr[attrib] = &tnl->tmp_inputs[attrib];
+ VB->AttribPtr[attrib]->data = (GLfloat (*)[4])ptr;
+ VB->AttribPtr[attrib]->start = (GLfloat *)ptr;
+ VB->AttribPtr[attrib]->count = count;
+ VB->AttribPtr[attrib]->stride = stride;
+ VB->AttribPtr[attrib]->size = input->Size;
+
+ /* This should die, but so should the whole GLvector4f concept:
+ */
+ VB->AttribPtr[attrib]->flags = (((1<<input->Size)-1) |
+ VEC_NOT_WRITEABLE |
+ (stride == 4*sizeof(GLfloat) ? 0 : VEC_BAD_STRIDE));
+
+ VB->AttribPtr[attrib]->storage = NULL;
+}
+
+#define CLIPVERTS ((6 + MAX_CLIP_PLANES) * 2)
+
+
+static GLboolean *_tnl_import_edgeflag( struct gl_context *ctx,
+ const GLvector4f *input,
+ GLuint count)
+{
+ const GLubyte *ptr = (const GLubyte *)input->data;
+ const GLuint stride = input->stride;
+ GLboolean *space = (GLboolean *)get_space(ctx, count + CLIPVERTS);
+ GLboolean *bptr = space;
+ GLuint i;
+
+ for (i = 0; i < count; i++) {
+ *bptr++ = ((GLfloat *)ptr)[0] == 1.0;
+ ptr += stride;
+ }
+
+ return space;
+}
+
+
+static void bind_inputs( struct gl_context *ctx,
+ const struct gl_client_array *inputs[],
+ GLint count,
+ struct gl_buffer_object **bo,
+ GLuint *nr_bo )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint i;
+
+ /* Map all the VBOs
+ */
+ for (i = 0; i < VERT_ATTRIB_MAX; i++) {
+ const void *ptr;
+
+ if (inputs[i]->BufferObj->Name) {
+ if (!inputs[i]->BufferObj->Pointer) {
+ bo[*nr_bo] = inputs[i]->BufferObj;
+ (*nr_bo)++;
+ ctx->Driver.MapBuffer(ctx,
+ GL_ARRAY_BUFFER,
+ GL_READ_ONLY_ARB,
+ inputs[i]->BufferObj);
+
+ assert(inputs[i]->BufferObj->Pointer);
+ }
+
+ ptr = ADD_POINTERS(inputs[i]->BufferObj->Pointer,
+ inputs[i]->Ptr);
+ }
+ else
+ ptr = inputs[i]->Ptr;
+
+ /* Just make sure the array is floating point, otherwise convert to
+ * temporary storage.
+ *
+ * XXX: remove the GLvector4f type at some stage and just use
+ * client arrays.
+ */
+ _tnl_import_array(ctx, i, count, inputs[i], ptr);
+ }
+
+ /* We process only the vertices between min & max index:
+ */
+ VB->Count = count;
+
+ /* These should perhaps be part of _TNL_ATTRIB_* */
+ VB->BackfaceColorPtr = NULL;
+ VB->BackfaceIndexPtr = NULL;
+ VB->BackfaceSecondaryColorPtr = NULL;
+
+ /* Clipping and drawing code still requires this to be a packed
+ * array of ubytes which can be written into. TODO: Fix and
+ * remove.
+ */
+ if (ctx->Polygon.FrontMode != GL_FILL ||
+ ctx->Polygon.BackMode != GL_FILL)
+ {
+ VB->EdgeFlag = _tnl_import_edgeflag( ctx,
+ VB->AttribPtr[_TNL_ATTRIB_EDGEFLAG],
+ VB->Count );
+ }
+ else {
+ /* the data previously pointed to by EdgeFlag may have been freed */
+ VB->EdgeFlag = NULL;
+ }
+}
+
+
+/* Translate indices to GLuints and store in VB->Elts.
+ */
+static void bind_indices( struct gl_context *ctx,
+ const struct _mesa_index_buffer *ib,
+ struct gl_buffer_object **bo,
+ GLuint *nr_bo)
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint i;
+ void *ptr;
+
+ if (!ib) {
+ VB->Elts = NULL;
+ return;
+ }
+
+ if (ib->obj->Name && !ib->obj->Pointer) {
+ bo[*nr_bo] = ib->obj;
+ (*nr_bo)++;
+ ctx->Driver.MapBuffer(ctx,
+ GL_ELEMENT_ARRAY_BUFFER,
+ GL_READ_ONLY_ARB,
+ ib->obj);
+
+ assert(ib->obj->Pointer);
+ }
+
+ ptr = ADD_POINTERS(ib->obj->Pointer, ib->ptr);
+
+ if (ib->type == GL_UNSIGNED_INT && VB->Primitive[0].basevertex == 0) {
+ VB->Elts = (GLuint *) ptr;
+ }
+ else {
+ GLuint *elts = (GLuint *)get_space(ctx, ib->count * sizeof(GLuint));
+ VB->Elts = elts;
+
+ if (ib->type == GL_UNSIGNED_INT) {
+ const GLuint *in = (GLuint *)ptr;
+ for (i = 0; i < ib->count; i++)
+ *elts++ = (GLuint)(*in++) + VB->Primitive[0].basevertex;
+ }
+ else if (ib->type == GL_UNSIGNED_SHORT) {
+ const GLushort *in = (GLushort *)ptr;
+ for (i = 0; i < ib->count; i++)
+ *elts++ = (GLuint)(*in++) + VB->Primitive[0].basevertex;
+ }
+ else {
+ const GLubyte *in = (GLubyte *)ptr;
+ for (i = 0; i < ib->count; i++)
+ *elts++ = (GLuint)(*in++) + VB->Primitive[0].basevertex;
+ }
+ }
+}
+
+static void bind_prims( struct gl_context *ctx,
+ const struct _mesa_prim *prim,
+ GLuint nr_prims )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+
+ VB->Primitive = prim;
+ VB->PrimitiveCount = nr_prims;
+}
+
+static void unmap_vbos( struct gl_context *ctx,
+ struct gl_buffer_object **bo,
+ GLuint nr_bo )
+{
+ GLuint i;
+ for (i = 0; i < nr_bo; i++) {
+ ctx->Driver.UnmapBuffer(ctx,
+ 0, /* target -- I don't see why this would be needed */
+ bo[i]);
+ }
+}
+
+
+void _tnl_vbo_draw_prims(struct gl_context *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLboolean index_bounds_valid,
+ GLuint min_index,
+ GLuint max_index)
+{
+ if (!index_bounds_valid)
+ vbo_get_minmax_index(ctx, prim, ib, &min_index, &max_index);
+
+ _tnl_draw_prims(ctx, arrays, prim, nr_prims, ib, min_index, max_index);
+}
+
+/* This is the main entrypoint into the slimmed-down software tnl
+ * module. In a regular swtnl driver, this can be plugged straight
+ * into the vbo->Driver.DrawPrims() callback.
+ */
+void _tnl_draw_prims( struct gl_context *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index)
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ const GLuint TEST_SPLIT = 0;
+ const GLint max = TEST_SPLIT ? 8 : tnl->vb.Size - MAX_CLIPPED_VERTICES;
+ GLint max_basevertex = prim->basevertex;
+ GLuint i;
+
+ /* Mesa core state should have been validated already */
+ assert(ctx->NewState == 0x0);
+
+ if (!_mesa_check_conditional_render(ctx))
+ return; /* don't draw */
+
+ for (i = 1; i < nr_prims; i++)
+ max_basevertex = MAX2(max_basevertex, prim[i].basevertex);
+
+ if (0)
+ {
+ printf("%s %d..%d\n", __FUNCTION__, min_index, max_index);
+ for (i = 0; i < nr_prims; i++)
+ printf("prim %d: %s start %d count %d\n", i,
+ _mesa_lookup_enum_by_nr(prim[i].mode),
+ prim[i].start,
+ prim[i].count);
+ }
+
+ if (min_index) {
+ /* We always translate away calls with min_index != 0.
+ */
+ vbo_rebase_prims( ctx, arrays, prim, nr_prims, ib,
+ min_index, max_index,
+ _tnl_vbo_draw_prims );
+ return;
+ }
+ else if ((GLint)max_index + max_basevertex > max) {
+ /* The software TNL pipeline has a fixed amount of storage for
+ * vertices and it is necessary to split incoming drawing commands
+ * if they exceed that limit.
+ */
+ struct split_limits limits;
+ limits.max_verts = max;
+ limits.max_vb_size = ~0;
+ limits.max_indices = ~0;
+
+ /* This will split the buffers one way or another and
+ * recursively call back into this function.
+ */
+ vbo_split_prims( ctx, arrays, prim, nr_prims, ib,
+ 0, max_index + prim->basevertex,
+ _tnl_vbo_draw_prims,
+ &limits );
+ }
+ else {
+ /* May need to map a vertex buffer object for every attribute plus
+ * one for the index buffer.
+ */
+ struct gl_buffer_object *bo[VERT_ATTRIB_MAX + 1];
+ GLuint nr_bo = 0;
+
+ for (i = 0; i < nr_prims;) {
+ GLuint this_nr_prims;
+
+ /* Our SW TNL pipeline doesn't handle basevertex yet, so bind_indices
+ * will rebase the elements to the basevertex, and we'll only
+ * emit strings of prims with the same basevertex in one draw call.
+ */
+ for (this_nr_prims = 1; i + this_nr_prims < nr_prims;
+ this_nr_prims++) {
+ if (prim[i].basevertex != prim[i + this_nr_prims].basevertex)
+ break;
+ }
+
+ /* Binding inputs may imply mapping some vertex buffer objects.
+ * They will need to be unmapped below.
+ */
+ bind_prims(ctx, &prim[i], this_nr_prims);
+ bind_inputs(ctx, arrays, max_index + prim[i].basevertex + 1,
+ bo, &nr_bo);
+ bind_indices(ctx, ib, bo, &nr_bo);
+
+ TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx);
+
+ unmap_vbos(ctx, bo, nr_bo);
+ free_space(ctx);
+
+ i += this_nr_prims;
+ }
+ }
+}
+
diff --git a/mesalib/src/mesa/tnl/t_pipeline.c b/mesalib/src/mesa/tnl/t_pipeline.c index 36fcd074c..27d7ecff7 100644 --- a/mesalib/src/mesa/tnl/t_pipeline.c +++ b/mesalib/src/mesa/tnl/t_pipeline.c @@ -1,210 +1,210 @@ -/* - * Mesa 3-D graphics library - * Version: 6.5.3 - * - * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Keith Whitwell <keith@tungstengraphics.com> - */ - -#include "main/glheader.h" -#include "main/context.h" -#include "main/imports.h" -#include "main/mtypes.h" - -#include "t_context.h" -#include "t_pipeline.h" -#include "t_vp_build.h" -#include "t_vertex.h" - -void _tnl_install_pipeline( GLcontext *ctx, - const struct tnl_pipeline_stage **stages ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - GLuint i; - - tnl->pipeline.new_state = ~0; - - /* Create a writeable copy of each stage. - */ - for (i = 0 ; i < MAX_PIPELINE_STAGES && stages[i] ; i++) { - struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i]; - memcpy(s, stages[i], sizeof(*s)); - if (s->create) - s->create(ctx, s); - } - - tnl->pipeline.nr_stages = i; -} - -void _tnl_destroy_pipeline( GLcontext *ctx ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - GLuint i; - - for (i = 0 ; i < tnl->pipeline.nr_stages ; i++) { - struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i]; - if (s->destroy) - s->destroy(s); - } - - tnl->pipeline.nr_stages = 0; -} - - - -static GLuint check_input_changes( GLcontext *ctx ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - GLuint i; - - for (i = 0; i <= _TNL_LAST_MAT; i++) { - if (tnl->vb.AttribPtr[i]->size != tnl->pipeline.last_attrib_size[i] || - tnl->vb.AttribPtr[i]->stride != tnl->pipeline.last_attrib_stride[i]) { - tnl->pipeline.last_attrib_size[i] = tnl->vb.AttribPtr[i]->size; - tnl->pipeline.last_attrib_stride[i] = tnl->vb.AttribPtr[i]->stride; - tnl->pipeline.input_changes |= 1<<i; - } - } - - return tnl->pipeline.input_changes; -} - - -static GLuint check_output_changes( GLcontext *ctx ) -{ -#if 0 - TNLcontext *tnl = TNL_CONTEXT(ctx); - - for (i = 0; i < VERT_RESULT_MAX; i++) { - if (tnl->vb.ResultPtr[i]->size != tnl->last_result_size[i] || - tnl->vb.ResultPtr[i]->stride != tnl->last_result_stride[i]) { - tnl->last_result_size[i] = tnl->vb.ResultPtr[i]->size; - tnl->last_result_stride[i] = tnl->vb.ResultPtr[i]->stride; - tnl->pipeline.output_changes |= 1<<i; - } - } - - if (tnl->pipeline.output_changes) - tnl->Driver.NotifyOutputChanges( ctx, tnl->pipeline.output_changes ); - - return tnl->pipeline.output_changes; -#else - return ~0; -#endif -} - - -void _tnl_run_pipeline( GLcontext *ctx ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - unsigned short __tmp; - GLuint i; - - if (!tnl->vb.Count) - return; - - /* Check for changed input sizes or change in stride to/from zero - * (ie const or non-const). - */ - if (check_input_changes( ctx ) || tnl->pipeline.new_state) { - if (ctx->VertexProgram._MaintainTnlProgram) - _tnl_UpdateFixedFunctionProgram( ctx ); - - for (i = 0; i < tnl->pipeline.nr_stages ; i++) { - struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i]; - if (s->validate) - s->validate( ctx, s ); - } - - tnl->pipeline.new_state = 0; - tnl->pipeline.input_changes = 0; - - /* Pipeline can only change its output in response to either a - * statechange or an input size/stride change. No other changes - * are allowed. - */ - if (check_output_changes( ctx )) - _tnl_notify_pipeline_output_change( ctx ); - } - - START_FAST_MATH(__tmp); - - for (i = 0; i < tnl->pipeline.nr_stages ; i++) { - struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i]; - if (!s->run( ctx, s )) - break; - } - - END_FAST_MATH(__tmp); -} - - - -/* The default pipeline. This is useful for software rasterizers, and - * simple hardware rasterizers. For customization, I don't recommend - * tampering with the internals of these stages in the way that - * drivers did in Mesa 3.4. These stages are basically black boxes, - * and should be left intact. - * - * To customize the pipeline, consider: - * - * - removing redundant stages (making sure that the software rasterizer - * can cope with this on fallback paths). An example is fog - * coordinate generation, which is not required in the FX driver. - * - * - replacing general-purpose machine-independent stages with - * general-purpose machine-specific stages. There is no example of - * this to date, though it must be borne in mind that all subsequent - * stages that reference the output of the new stage must cope with - * any machine-specific data introduced. This may not be easy - * unless there are no such stages (ie the new stage is the last in - * the pipe). - * - * - inserting optimized (but specialized) stages ahead of the - * general-purpose fallback implementation. For example, the old - * 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 * - * pipeline by returning GL_FALSE from run(), or do nothing). - * - * Some work can be done to lift some of the restrictions in the final - * case, if it becomes necessary to do so. - */ -const struct tnl_pipeline_stage *_tnl_default_pipeline[] = { - &_tnl_vertex_transform_stage, - &_tnl_normal_transform_stage, - &_tnl_lighting_stage, - &_tnl_texgen_stage, - &_tnl_texture_transform_stage, - &_tnl_point_attenuation_stage, - &_tnl_vertex_program_stage, - &_tnl_fog_coordinate_stage, - &_tnl_render_stage, - NULL -}; - -const struct tnl_pipeline_stage *_tnl_vp_pipeline[] = { - &_tnl_vertex_program_stage, - &_tnl_render_stage, - NULL -}; +/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+
+#include "t_context.h"
+#include "t_pipeline.h"
+#include "t_vp_build.h"
+#include "t_vertex.h"
+
+void _tnl_install_pipeline( struct gl_context *ctx,
+ const struct tnl_pipeline_stage **stages )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLuint i;
+
+ tnl->pipeline.new_state = ~0;
+
+ /* Create a writeable copy of each stage.
+ */
+ for (i = 0 ; i < MAX_PIPELINE_STAGES && stages[i] ; i++) {
+ struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i];
+ memcpy(s, stages[i], sizeof(*s));
+ if (s->create)
+ s->create(ctx, s);
+ }
+
+ tnl->pipeline.nr_stages = i;
+}
+
+void _tnl_destroy_pipeline( struct gl_context *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLuint i;
+
+ for (i = 0 ; i < tnl->pipeline.nr_stages ; i++) {
+ struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i];
+ if (s->destroy)
+ s->destroy(s);
+ }
+
+ tnl->pipeline.nr_stages = 0;
+}
+
+
+
+static GLuint check_input_changes( struct gl_context *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ GLuint i;
+
+ for (i = 0; i <= _TNL_LAST_MAT; i++) {
+ if (tnl->vb.AttribPtr[i]->size != tnl->pipeline.last_attrib_size[i] ||
+ tnl->vb.AttribPtr[i]->stride != tnl->pipeline.last_attrib_stride[i]) {
+ tnl->pipeline.last_attrib_size[i] = tnl->vb.AttribPtr[i]->size;
+ tnl->pipeline.last_attrib_stride[i] = tnl->vb.AttribPtr[i]->stride;
+ tnl->pipeline.input_changes |= 1<<i;
+ }
+ }
+
+ return tnl->pipeline.input_changes;
+}
+
+
+static GLuint check_output_changes( struct gl_context *ctx )
+{
+#if 0
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+
+ for (i = 0; i < VERT_RESULT_MAX; i++) {
+ if (tnl->vb.ResultPtr[i]->size != tnl->last_result_size[i] ||
+ tnl->vb.ResultPtr[i]->stride != tnl->last_result_stride[i]) {
+ tnl->last_result_size[i] = tnl->vb.ResultPtr[i]->size;
+ tnl->last_result_stride[i] = tnl->vb.ResultPtr[i]->stride;
+ tnl->pipeline.output_changes |= 1<<i;
+ }
+ }
+
+ if (tnl->pipeline.output_changes)
+ tnl->Driver.NotifyOutputChanges( ctx, tnl->pipeline.output_changes );
+
+ return tnl->pipeline.output_changes;
+#else
+ return ~0;
+#endif
+}
+
+
+void _tnl_run_pipeline( struct gl_context *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ unsigned short __tmp;
+ GLuint i;
+
+ if (!tnl->vb.Count)
+ return;
+
+ /* Check for changed input sizes or change in stride to/from zero
+ * (ie const or non-const).
+ */
+ if (check_input_changes( ctx ) || tnl->pipeline.new_state) {
+ if (ctx->VertexProgram._MaintainTnlProgram)
+ _tnl_UpdateFixedFunctionProgram( ctx );
+
+ for (i = 0; i < tnl->pipeline.nr_stages ; i++) {
+ struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i];
+ if (s->validate)
+ s->validate( ctx, s );
+ }
+
+ tnl->pipeline.new_state = 0;
+ tnl->pipeline.input_changes = 0;
+
+ /* Pipeline can only change its output in response to either a
+ * statechange or an input size/stride change. No other changes
+ * are allowed.
+ */
+ if (check_output_changes( ctx ))
+ _tnl_notify_pipeline_output_change( ctx );
+ }
+
+ START_FAST_MATH(__tmp);
+
+ for (i = 0; i < tnl->pipeline.nr_stages ; i++) {
+ struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i];
+ if (!s->run( ctx, s ))
+ break;
+ }
+
+ END_FAST_MATH(__tmp);
+}
+
+
+
+/* The default pipeline. This is useful for software rasterizers, and
+ * simple hardware rasterizers. For customization, I don't recommend
+ * tampering with the internals of these stages in the way that
+ * drivers did in Mesa 3.4. These stages are basically black boxes,
+ * and should be left intact.
+ *
+ * To customize the pipeline, consider:
+ *
+ * - removing redundant stages (making sure that the software rasterizer
+ * can cope with this on fallback paths). An example is fog
+ * coordinate generation, which is not required in the FX driver.
+ *
+ * - replacing general-purpose machine-independent stages with
+ * general-purpose machine-specific stages. There is no example of
+ * this to date, though it must be borne in mind that all subsequent
+ * stages that reference the output of the new stage must cope with
+ * any machine-specific data introduced. This may not be easy
+ * unless there are no such stages (ie the new stage is the last in
+ * the pipe).
+ *
+ * - inserting optimized (but specialized) stages ahead of the
+ * general-purpose fallback implementation. For example, the old
+ * 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 *
+ * pipeline by returning GL_FALSE from run(), or do nothing).
+ *
+ * Some work can be done to lift some of the restrictions in the final
+ * case, if it becomes necessary to do so.
+ */
+const struct tnl_pipeline_stage *_tnl_default_pipeline[] = {
+ &_tnl_vertex_transform_stage,
+ &_tnl_normal_transform_stage,
+ &_tnl_lighting_stage,
+ &_tnl_texgen_stage,
+ &_tnl_texture_transform_stage,
+ &_tnl_point_attenuation_stage,
+ &_tnl_vertex_program_stage,
+ &_tnl_fog_coordinate_stage,
+ &_tnl_render_stage,
+ NULL
+};
+
+const struct tnl_pipeline_stage *_tnl_vp_pipeline[] = {
+ &_tnl_vertex_program_stage,
+ &_tnl_render_stage,
+ NULL
+};
diff --git a/mesalib/src/mesa/tnl/t_pipeline.h b/mesalib/src/mesa/tnl/t_pipeline.h index d110010f0..579207889 100644 --- a/mesalib/src/mesa/tnl/t_pipeline.h +++ b/mesalib/src/mesa/tnl/t_pipeline.h @@ -1,74 +1,73 @@ -/* - * Mesa 3-D graphics library - * Version: 6.5.3 - * - * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Keith Whitwell <keith@tungstengraphics.com> - */ - - - -#ifndef _T_PIPELINE_H_ -#define _T_PIPELINE_H_ - -#include "main/mtypes.h" -#include "t_context.h" - -extern void _tnl_run_pipeline( GLcontext *ctx ); - -extern void _tnl_destroy_pipeline( GLcontext *ctx ); - -extern void _tnl_install_pipeline( GLcontext *ctx, - const struct tnl_pipeline_stage **stages ); - - -/* These are implemented in the t_vb_*.c files: - */ -extern const struct tnl_pipeline_stage _tnl_vertex_transform_stage; -extern const struct tnl_pipeline_stage _tnl_vertex_cull_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 tnl_pipeline_stage *_tnl_default_pipeline[]; -extern const struct tnl_pipeline_stage *_tnl_vp_pipeline[]; - - -/* Convenience routines provided by t_vb_render.c: - */ -extern tnl_render_func _tnl_render_tab_elts[]; -extern tnl_render_func _tnl_render_tab_verts[]; - -extern void _tnl_RenderClippedPolygon( GLcontext *ctx, - const GLuint *elts, GLuint n ); - -extern void _tnl_RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj ); - - -#endif +/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.3
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+
+#ifndef _T_PIPELINE_H_
+#define _T_PIPELINE_H_
+
+#include "main/mtypes.h"
+#include "t_context.h"
+
+extern void _tnl_run_pipeline( struct gl_context *ctx );
+
+extern void _tnl_destroy_pipeline( struct gl_context *ctx );
+
+extern void _tnl_install_pipeline( struct gl_context *ctx,
+ const struct tnl_pipeline_stage **stages );
+
+
+/* These are implemented in the t_vb_*.c files:
+ */
+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 tnl_pipeline_stage *_tnl_default_pipeline[];
+extern const struct tnl_pipeline_stage *_tnl_vp_pipeline[];
+
+
+/* Convenience routines provided by t_vb_render.c:
+ */
+extern tnl_render_func _tnl_render_tab_elts[];
+extern tnl_render_func _tnl_render_tab_verts[];
+
+extern void _tnl_RenderClippedPolygon( struct gl_context *ctx,
+ const GLuint *elts, GLuint n );
+
+extern void _tnl_RenderClippedLine( struct gl_context *ctx, GLuint ii, GLuint jj );
+
+
+#endif
diff --git a/mesalib/src/mesa/tnl/t_rasterpos.c b/mesalib/src/mesa/tnl/t_rasterpos.c index d82d5b507..78aa8880f 100644 --- a/mesalib/src/mesa/tnl/t_rasterpos.c +++ b/mesalib/src/mesa/tnl/t_rasterpos.c @@ -1,486 +1,486 @@ -/* - * Mesa 3-D graphics library - * Version: 7.1 - * - * Copyright (C) 1999-2007 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 "main/glheader.h" -#include "main/colormac.h" -#include "main/feedback.h" -#include "main/light.h" -#include "main/macros.h" -#include "main/simple_list.h" -#include "main/mtypes.h" - -#include "math/m_matrix.h" -#include "tnl/tnl.h" - - - -/** - * Clip a point against the view volume. - * - * \param v vertex vector describing the point to clip. - * - * \return zero if outside view volume, or one if inside. - */ -static GLuint -viewclip_point_xy( const GLfloat v[] ) -{ - if ( v[0] > v[3] || v[0] < -v[3] - || v[1] > v[3] || v[1] < -v[3] ) { - return 0; - } - else { - return 1; - } -} - - -/** - * Clip a point against the far/near Z clipping planes. - * - * \param v vertex vector describing the point to clip. - * - * \return zero if outside view volume, or one if inside. - */ -static GLuint -viewclip_point_z( const GLfloat v[] ) -{ - if (v[2] > v[3] || v[2] < -v[3] ) { - return 0; - } - else { - return 1; - } -} - - -/** - * Clip a point against the user clipping planes. - * - * \param ctx GL context. - * \param v vertex vector describing the point to clip. - * - * \return zero if the point was clipped, or one otherwise. - */ -static GLuint -userclip_point( GLcontext *ctx, const GLfloat v[] ) -{ - GLuint p; - - for (p = 0; p < ctx->Const.MaxClipPlanes; p++) { - if (ctx->Transform.ClipPlanesEnabled & (1 << p)) { - GLfloat dot = v[0] * ctx->Transform._ClipUserPlane[p][0] - + v[1] * ctx->Transform._ClipUserPlane[p][1] - + v[2] * ctx->Transform._ClipUserPlane[p][2] - + v[3] * ctx->Transform._ClipUserPlane[p][3]; - if (dot < 0.0F) { - return 0; - } - } - } - - return 1; -} - - -/** - * Compute lighting for the raster position. Both RGB and CI modes computed. - * \param ctx the context - * \param vertex vertex location - * \param normal normal vector - * \param Rcolor returned color - * \param Rspec returned specular color (if separate specular enabled) - * \param Rindex returned color index - */ -static void -shade_rastpos(GLcontext *ctx, - const GLfloat vertex[4], - const GLfloat normal[3], - GLfloat Rcolor[4], - GLfloat Rspec[4]) -{ - /*const*/ GLfloat (*base)[3] = ctx->Light._BaseColor; - const struct gl_light *light; - GLfloat diffuseColor[4], specularColor[4]; /* for RGB mode only */ - GLfloat diffuseCI = 0.0, specularCI = 0.0; /* for CI mode only */ - - _mesa_validate_all_lighting_tables( ctx ); - - COPY_3V(diffuseColor, base[0]); - diffuseColor[3] = CLAMP( - ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3], 0.0F, 1.0F ); - ASSIGN_4V(specularColor, 0.0, 0.0, 0.0, 1.0); - - foreach (light, &ctx->Light.EnabledList) { - GLfloat attenuation = 1.0; - GLfloat VP[3]; /* vector from vertex to light pos */ - GLfloat n_dot_VP; - GLfloat diffuseContrib[3], specularContrib[3]; - - if (!(light->_Flags & LIGHT_POSITIONAL)) { - /* light at infinity */ - COPY_3V(VP, light->_VP_inf_norm); - attenuation = light->_VP_inf_spot_attenuation; - } - else { - /* local/positional light */ - GLfloat d; - - /* VP = vector from vertex pos to light[i].pos */ - SUB_3V(VP, light->_Position, vertex); - /* d = length(VP) */ - d = (GLfloat) LEN_3FV( VP ); - if (d > 1.0e-6) { - /* normalize VP */ - GLfloat invd = 1.0F / d; - SELF_SCALE_SCALAR_3V(VP, invd); - } - - /* atti */ - attenuation = 1.0F / (light->ConstantAttenuation + d * - (light->LinearAttenuation + d * - light->QuadraticAttenuation)); - - if (light->_Flags & LIGHT_SPOT) { - GLfloat PV_dot_dir = - DOT3(VP, light->_NormSpotDirection); - - if (PV_dot_dir<light->_CosCutoff) { - continue; - } - else { - double x = PV_dot_dir * (EXP_TABLE_SIZE-1); - int k = (int) x; - GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0] - + (x-k)*light->_SpotExpTable[k][1]); - attenuation *= spot; - } - } - } - - if (attenuation < 1e-3) - continue; - - n_dot_VP = DOT3( normal, VP ); - - if (n_dot_VP < 0.0F) { - ACC_SCALE_SCALAR_3V(diffuseColor, attenuation, light->_MatAmbient[0]); - continue; - } - - /* Ambient + diffuse */ - COPY_3V(diffuseContrib, light->_MatAmbient[0]); - ACC_SCALE_SCALAR_3V(diffuseContrib, n_dot_VP, light->_MatDiffuse[0]); - diffuseCI += n_dot_VP * light->_dli * attenuation; - - /* Specular */ - { - const GLfloat *h; - GLfloat n_dot_h; - - ASSIGN_3V(specularContrib, 0.0, 0.0, 0.0); - - if (ctx->Light.Model.LocalViewer) { - GLfloat v[3]; - COPY_3V(v, vertex); - NORMALIZE_3FV(v); - SUB_3V(VP, VP, v); - NORMALIZE_3FV(VP); - h = VP; - } - else if (light->_Flags & LIGHT_POSITIONAL) { - ACC_3V(VP, ctx->_EyeZDir); - NORMALIZE_3FV(VP); - h = VP; - } - else { - h = light->_h_inf_norm; - } - - n_dot_h = DOT3(normal, h); - - if (n_dot_h > 0.0F) { - GLfloat spec_coef; - GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec_coef ); - - if (spec_coef > 1.0e-10) { - if (ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) { - ACC_SCALE_SCALAR_3V( specularContrib, spec_coef, - light->_MatSpecular[0]); - } - else { - ACC_SCALE_SCALAR_3V( diffuseContrib, spec_coef, - light->_MatSpecular[0]); - } - /*assert(light->_sli > 0.0);*/ - specularCI += spec_coef * light->_sli * attenuation; - } - } - } - - ACC_SCALE_SCALAR_3V( diffuseColor, attenuation, diffuseContrib ); - ACC_SCALE_SCALAR_3V( specularColor, attenuation, specularContrib ); - } - - Rcolor[0] = CLAMP(diffuseColor[0], 0.0F, 1.0F); - Rcolor[1] = CLAMP(diffuseColor[1], 0.0F, 1.0F); - Rcolor[2] = CLAMP(diffuseColor[2], 0.0F, 1.0F); - Rcolor[3] = CLAMP(diffuseColor[3], 0.0F, 1.0F); - Rspec[0] = CLAMP(specularColor[0], 0.0F, 1.0F); - Rspec[1] = CLAMP(specularColor[1], 0.0F, 1.0F); - Rspec[2] = CLAMP(specularColor[2], 0.0F, 1.0F); - Rspec[3] = CLAMP(specularColor[3], 0.0F, 1.0F); -} - - -/** - * Do texgen needed for glRasterPos. - * \param ctx rendering context - * \param vObj object-space vertex coordinate - * \param vEye eye-space vertex coordinate - * \param normal vertex normal - * \param unit texture unit number - * \param texcoord incoming texcoord and resulting texcoord - */ -static void -compute_texgen(GLcontext *ctx, const GLfloat vObj[4], const GLfloat vEye[4], - const GLfloat normal[3], GLuint unit, GLfloat texcoord[4]) -{ - const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; - - /* always compute sphere map terms, just in case */ - GLfloat u[3], two_nu, rx, ry, rz, m, mInv; - COPY_3V(u, vEye); - NORMALIZE_3FV(u); - two_nu = 2.0F * DOT3(normal, u); - rx = u[0] - normal[0] * two_nu; - ry = u[1] - normal[1] * two_nu; - rz = u[2] - normal[2] * two_nu; - m = rx * rx + ry * ry + (rz + 1.0F) * (rz + 1.0F); - if (m > 0.0F) - mInv = 0.5F * _mesa_inv_sqrtf(m); - else - mInv = 0.0F; - - if (texUnit->TexGenEnabled & S_BIT) { - switch (texUnit->GenS.Mode) { - case GL_OBJECT_LINEAR: - texcoord[0] = DOT4(vObj, texUnit->GenS.ObjectPlane); - break; - case GL_EYE_LINEAR: - texcoord[0] = DOT4(vEye, texUnit->GenS.EyePlane); - break; - case GL_SPHERE_MAP: - texcoord[0] = rx * mInv + 0.5F; - break; - case GL_REFLECTION_MAP: - texcoord[0] = rx; - break; - case GL_NORMAL_MAP: - texcoord[0] = normal[0]; - break; - default: - _mesa_problem(ctx, "Bad S texgen in compute_texgen()"); - return; - } - } - - if (texUnit->TexGenEnabled & T_BIT) { - switch (texUnit->GenT.Mode) { - case GL_OBJECT_LINEAR: - texcoord[1] = DOT4(vObj, texUnit->GenT.ObjectPlane); - break; - case GL_EYE_LINEAR: - texcoord[1] = DOT4(vEye, texUnit->GenT.EyePlane); - break; - case GL_SPHERE_MAP: - texcoord[1] = ry * mInv + 0.5F; - break; - case GL_REFLECTION_MAP: - texcoord[1] = ry; - break; - case GL_NORMAL_MAP: - texcoord[1] = normal[1]; - break; - default: - _mesa_problem(ctx, "Bad T texgen in compute_texgen()"); - return; - } - } - - if (texUnit->TexGenEnabled & R_BIT) { - switch (texUnit->GenR.Mode) { - case GL_OBJECT_LINEAR: - texcoord[2] = DOT4(vObj, texUnit->GenR.ObjectPlane); - break; - case GL_EYE_LINEAR: - texcoord[2] = DOT4(vEye, texUnit->GenR.EyePlane); - break; - case GL_REFLECTION_MAP: - texcoord[2] = rz; - break; - case GL_NORMAL_MAP: - texcoord[2] = normal[2]; - break; - default: - _mesa_problem(ctx, "Bad R texgen in compute_texgen()"); - return; - } - } - - if (texUnit->TexGenEnabled & Q_BIT) { - switch (texUnit->GenQ.Mode) { - case GL_OBJECT_LINEAR: - texcoord[3] = DOT4(vObj, texUnit->GenQ.ObjectPlane); - break; - case GL_EYE_LINEAR: - texcoord[3] = DOT4(vEye, texUnit->GenQ.EyePlane); - break; - default: - _mesa_problem(ctx, "Bad Q texgen in compute_texgen()"); - return; - } - } -} - - -/** - * glRasterPos transformation. Typically called via ctx->Driver.RasterPos(). - * XXX some of this code (such as viewport xform, clip testing and setting - * of ctx->Current.Raster* fields) could get lifted up into the - * main/rasterpos.c code. - * - * \param vObj vertex position in object space - */ -void -_tnl_RasterPos(GLcontext *ctx, const GLfloat vObj[4]) -{ - if (ctx->VertexProgram._Enabled) { - /* XXX implement this */ - _mesa_problem(ctx, "Vertex programs not implemented for glRasterPos"); - return; - } - else { - GLfloat eye[4], clip[4], ndc[3], d; - GLfloat *norm, eyenorm[3]; - GLfloat *objnorm = ctx->Current.Attrib[VERT_ATTRIB_NORMAL]; - - /* apply modelview matrix: eye = MV * obj */ - TRANSFORM_POINT( eye, ctx->ModelviewMatrixStack.Top->m, vObj ); - /* apply projection matrix: clip = Proj * eye */ - TRANSFORM_POINT( clip, ctx->ProjectionMatrixStack.Top->m, eye ); - - /* clip to view volume. */ - if (!ctx->Transform.DepthClamp) { - if (viewclip_point_z(clip) == 0) { - ctx->Current.RasterPosValid = GL_FALSE; - return; - } - } - if (!ctx->Transform.RasterPositionUnclipped) { - if (viewclip_point_xy(clip) == 0) { - ctx->Current.RasterPosValid = GL_FALSE; - return; - } - } - - /* clip to user clipping planes */ - if (ctx->Transform.ClipPlanesEnabled && !userclip_point(ctx, clip)) { - ctx->Current.RasterPosValid = GL_FALSE; - return; - } - - /* ndc = clip / W */ - d = (clip[3] == 0.0F) ? 1.0F : 1.0F / clip[3]; - ndc[0] = clip[0] * d; - ndc[1] = clip[1] * d; - ndc[2] = clip[2] * d; - /* wincoord = viewport_mapping(ndc) */ - ctx->Current.RasterPos[0] = (ndc[0] * ctx->Viewport._WindowMap.m[MAT_SX] - + ctx->Viewport._WindowMap.m[MAT_TX]); - ctx->Current.RasterPos[1] = (ndc[1] * ctx->Viewport._WindowMap.m[MAT_SY] - + ctx->Viewport._WindowMap.m[MAT_TY]); - ctx->Current.RasterPos[2] = (ndc[2] * ctx->Viewport._WindowMap.m[MAT_SZ] - + ctx->Viewport._WindowMap.m[MAT_TZ]) - / ctx->DrawBuffer->_DepthMaxF; - ctx->Current.RasterPos[3] = clip[3]; - - if (ctx->Transform.DepthClamp) { - ctx->Current.RasterPos[3] = CLAMP(ctx->Current.RasterPos[3], - ctx->Viewport.Near, - ctx->Viewport.Far); - } - - /* compute raster distance */ - if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT) - ctx->Current.RasterDistance = ctx->Current.Attrib[VERT_ATTRIB_FOG][0]; - else - ctx->Current.RasterDistance = - SQRTF( eye[0]*eye[0] + eye[1]*eye[1] + eye[2]*eye[2] ); - - /* compute transformed normal vector (for lighting or texgen) */ - if (ctx->_NeedEyeCoords) { - const GLfloat *inv = ctx->ModelviewMatrixStack.Top->inv; - TRANSFORM_NORMAL( eyenorm, objnorm, inv ); - norm = eyenorm; - } - else { - norm = objnorm; - } - - /* update raster color */ - if (ctx->Light.Enabled) { - /* lighting */ - shade_rastpos( ctx, vObj, norm, - ctx->Current.RasterColor, - ctx->Current.RasterSecondaryColor ); - } - else { - /* use current color */ - COPY_4FV(ctx->Current.RasterColor, - ctx->Current.Attrib[VERT_ATTRIB_COLOR0]); - COPY_4FV(ctx->Current.RasterSecondaryColor, - ctx->Current.Attrib[VERT_ATTRIB_COLOR1]); - } - - /* texture coords */ - { - GLuint u; - for (u = 0; u < ctx->Const.MaxTextureCoordUnits; u++) { - GLfloat tc[4]; - COPY_4V(tc, ctx->Current.Attrib[VERT_ATTRIB_TEX0 + u]); - if (ctx->Texture.Unit[u].TexGenEnabled) { - compute_texgen(ctx, vObj, eye, norm, u, tc); - } - TRANSFORM_POINT(ctx->Current.RasterTexCoords[u], - ctx->TextureMatrixStack[u].Top->m, tc); - } - } - - ctx->Current.RasterPosValid = GL_TRUE; - } - - if (ctx->RenderMode == GL_SELECT) { - _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] ); - } -} +/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 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 "main/glheader.h"
+#include "main/colormac.h"
+#include "main/feedback.h"
+#include "main/light.h"
+#include "main/macros.h"
+#include "main/simple_list.h"
+#include "main/mtypes.h"
+
+#include "math/m_matrix.h"
+#include "tnl/tnl.h"
+
+
+
+/**
+ * Clip a point against the view volume.
+ *
+ * \param v vertex vector describing the point to clip.
+ *
+ * \return zero if outside view volume, or one if inside.
+ */
+static GLuint
+viewclip_point_xy( const GLfloat v[] )
+{
+ if ( v[0] > v[3] || v[0] < -v[3]
+ || v[1] > v[3] || v[1] < -v[3] ) {
+ return 0;
+ }
+ else {
+ return 1;
+ }
+}
+
+
+/**
+ * Clip a point against the far/near Z clipping planes.
+ *
+ * \param v vertex vector describing the point to clip.
+ *
+ * \return zero if outside view volume, or one if inside.
+ */
+static GLuint
+viewclip_point_z( const GLfloat v[] )
+{
+ if (v[2] > v[3] || v[2] < -v[3] ) {
+ return 0;
+ }
+ else {
+ return 1;
+ }
+}
+
+
+/**
+ * Clip a point against the user clipping planes.
+ *
+ * \param ctx GL context.
+ * \param v vertex vector describing the point to clip.
+ *
+ * \return zero if the point was clipped, or one otherwise.
+ */
+static GLuint
+userclip_point( struct gl_context *ctx, const GLfloat v[] )
+{
+ GLuint p;
+
+ for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
+ if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
+ GLfloat dot = v[0] * ctx->Transform._ClipUserPlane[p][0]
+ + v[1] * ctx->Transform._ClipUserPlane[p][1]
+ + v[2] * ctx->Transform._ClipUserPlane[p][2]
+ + v[3] * ctx->Transform._ClipUserPlane[p][3];
+ if (dot < 0.0F) {
+ return 0;
+ }
+ }
+ }
+
+ return 1;
+}
+
+
+/**
+ * Compute lighting for the raster position. Both RGB and CI modes computed.
+ * \param ctx the context
+ * \param vertex vertex location
+ * \param normal normal vector
+ * \param Rcolor returned color
+ * \param Rspec returned specular color (if separate specular enabled)
+ * \param Rindex returned color index
+ */
+static void
+shade_rastpos(struct gl_context *ctx,
+ const GLfloat vertex[4],
+ const GLfloat normal[3],
+ GLfloat Rcolor[4],
+ GLfloat Rspec[4])
+{
+ /*const*/ GLfloat (*base)[3] = ctx->Light._BaseColor;
+ const struct gl_light *light;
+ GLfloat diffuseColor[4], specularColor[4]; /* for RGB mode only */
+ GLfloat diffuseCI = 0.0, specularCI = 0.0; /* for CI mode only */
+
+ _mesa_validate_all_lighting_tables( ctx );
+
+ COPY_3V(diffuseColor, base[0]);
+ diffuseColor[3] = CLAMP(
+ ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3], 0.0F, 1.0F );
+ ASSIGN_4V(specularColor, 0.0, 0.0, 0.0, 1.0);
+
+ foreach (light, &ctx->Light.EnabledList) {
+ GLfloat attenuation = 1.0;
+ GLfloat VP[3]; /* vector from vertex to light pos */
+ GLfloat n_dot_VP;
+ GLfloat diffuseContrib[3], specularContrib[3];
+
+ if (!(light->_Flags & LIGHT_POSITIONAL)) {
+ /* light at infinity */
+ COPY_3V(VP, light->_VP_inf_norm);
+ attenuation = light->_VP_inf_spot_attenuation;
+ }
+ else {
+ /* local/positional light */
+ GLfloat d;
+
+ /* VP = vector from vertex pos to light[i].pos */
+ SUB_3V(VP, light->_Position, vertex);
+ /* d = length(VP) */
+ d = (GLfloat) LEN_3FV( VP );
+ if (d > 1.0e-6) {
+ /* normalize VP */
+ GLfloat invd = 1.0F / d;
+ SELF_SCALE_SCALAR_3V(VP, invd);
+ }
+
+ /* atti */
+ attenuation = 1.0F / (light->ConstantAttenuation + d *
+ (light->LinearAttenuation + d *
+ light->QuadraticAttenuation));
+
+ if (light->_Flags & LIGHT_SPOT) {
+ GLfloat PV_dot_dir = - DOT3(VP, light->_NormSpotDirection);
+
+ if (PV_dot_dir<light->_CosCutoff) {
+ continue;
+ }
+ else {
+ double x = PV_dot_dir * (EXP_TABLE_SIZE-1);
+ int k = (int) x;
+ GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
+ + (x-k)*light->_SpotExpTable[k][1]);
+ attenuation *= spot;
+ }
+ }
+ }
+
+ if (attenuation < 1e-3)
+ continue;
+
+ n_dot_VP = DOT3( normal, VP );
+
+ if (n_dot_VP < 0.0F) {
+ ACC_SCALE_SCALAR_3V(diffuseColor, attenuation, light->_MatAmbient[0]);
+ continue;
+ }
+
+ /* Ambient + diffuse */
+ COPY_3V(diffuseContrib, light->_MatAmbient[0]);
+ ACC_SCALE_SCALAR_3V(diffuseContrib, n_dot_VP, light->_MatDiffuse[0]);
+ diffuseCI += n_dot_VP * light->_dli * attenuation;
+
+ /* Specular */
+ {
+ const GLfloat *h;
+ GLfloat n_dot_h;
+
+ ASSIGN_3V(specularContrib, 0.0, 0.0, 0.0);
+
+ if (ctx->Light.Model.LocalViewer) {
+ GLfloat v[3];
+ COPY_3V(v, vertex);
+ NORMALIZE_3FV(v);
+ SUB_3V(VP, VP, v);
+ NORMALIZE_3FV(VP);
+ h = VP;
+ }
+ else if (light->_Flags & LIGHT_POSITIONAL) {
+ ACC_3V(VP, ctx->_EyeZDir);
+ NORMALIZE_3FV(VP);
+ h = VP;
+ }
+ else {
+ h = light->_h_inf_norm;
+ }
+
+ n_dot_h = DOT3(normal, h);
+
+ if (n_dot_h > 0.0F) {
+ GLfloat spec_coef;
+ GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec_coef );
+
+ if (spec_coef > 1.0e-10) {
+ if (ctx->Light.Model.ColorControl==GL_SEPARATE_SPECULAR_COLOR) {
+ ACC_SCALE_SCALAR_3V( specularContrib, spec_coef,
+ light->_MatSpecular[0]);
+ }
+ else {
+ ACC_SCALE_SCALAR_3V( diffuseContrib, spec_coef,
+ light->_MatSpecular[0]);
+ }
+ /*assert(light->_sli > 0.0);*/
+ specularCI += spec_coef * light->_sli * attenuation;
+ }
+ }
+ }
+
+ ACC_SCALE_SCALAR_3V( diffuseColor, attenuation, diffuseContrib );
+ ACC_SCALE_SCALAR_3V( specularColor, attenuation, specularContrib );
+ }
+
+ Rcolor[0] = CLAMP(diffuseColor[0], 0.0F, 1.0F);
+ Rcolor[1] = CLAMP(diffuseColor[1], 0.0F, 1.0F);
+ Rcolor[2] = CLAMP(diffuseColor[2], 0.0F, 1.0F);
+ Rcolor[3] = CLAMP(diffuseColor[3], 0.0F, 1.0F);
+ Rspec[0] = CLAMP(specularColor[0], 0.0F, 1.0F);
+ Rspec[1] = CLAMP(specularColor[1], 0.0F, 1.0F);
+ Rspec[2] = CLAMP(specularColor[2], 0.0F, 1.0F);
+ Rspec[3] = CLAMP(specularColor[3], 0.0F, 1.0F);
+}
+
+
+/**
+ * Do texgen needed for glRasterPos.
+ * \param ctx rendering context
+ * \param vObj object-space vertex coordinate
+ * \param vEye eye-space vertex coordinate
+ * \param normal vertex normal
+ * \param unit texture unit number
+ * \param texcoord incoming texcoord and resulting texcoord
+ */
+static void
+compute_texgen(struct gl_context *ctx, const GLfloat vObj[4], const GLfloat vEye[4],
+ const GLfloat normal[3], GLuint unit, GLfloat texcoord[4])
+{
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+
+ /* always compute sphere map terms, just in case */
+ GLfloat u[3], two_nu, rx, ry, rz, m, mInv;
+ COPY_3V(u, vEye);
+ NORMALIZE_3FV(u);
+ two_nu = 2.0F * DOT3(normal, u);
+ rx = u[0] - normal[0] * two_nu;
+ ry = u[1] - normal[1] * two_nu;
+ rz = u[2] - normal[2] * two_nu;
+ m = rx * rx + ry * ry + (rz + 1.0F) * (rz + 1.0F);
+ if (m > 0.0F)
+ mInv = 0.5F * _mesa_inv_sqrtf(m);
+ else
+ mInv = 0.0F;
+
+ if (texUnit->TexGenEnabled & S_BIT) {
+ switch (texUnit->GenS.Mode) {
+ case GL_OBJECT_LINEAR:
+ texcoord[0] = DOT4(vObj, texUnit->GenS.ObjectPlane);
+ break;
+ case GL_EYE_LINEAR:
+ texcoord[0] = DOT4(vEye, texUnit->GenS.EyePlane);
+ break;
+ case GL_SPHERE_MAP:
+ texcoord[0] = rx * mInv + 0.5F;
+ break;
+ case GL_REFLECTION_MAP:
+ texcoord[0] = rx;
+ break;
+ case GL_NORMAL_MAP:
+ texcoord[0] = normal[0];
+ break;
+ default:
+ _mesa_problem(ctx, "Bad S texgen in compute_texgen()");
+ return;
+ }
+ }
+
+ if (texUnit->TexGenEnabled & T_BIT) {
+ switch (texUnit->GenT.Mode) {
+ case GL_OBJECT_LINEAR:
+ texcoord[1] = DOT4(vObj, texUnit->GenT.ObjectPlane);
+ break;
+ case GL_EYE_LINEAR:
+ texcoord[1] = DOT4(vEye, texUnit->GenT.EyePlane);
+ break;
+ case GL_SPHERE_MAP:
+ texcoord[1] = ry * mInv + 0.5F;
+ break;
+ case GL_REFLECTION_MAP:
+ texcoord[1] = ry;
+ break;
+ case GL_NORMAL_MAP:
+ texcoord[1] = normal[1];
+ break;
+ default:
+ _mesa_problem(ctx, "Bad T texgen in compute_texgen()");
+ return;
+ }
+ }
+
+ if (texUnit->TexGenEnabled & R_BIT) {
+ switch (texUnit->GenR.Mode) {
+ case GL_OBJECT_LINEAR:
+ texcoord[2] = DOT4(vObj, texUnit->GenR.ObjectPlane);
+ break;
+ case GL_EYE_LINEAR:
+ texcoord[2] = DOT4(vEye, texUnit->GenR.EyePlane);
+ break;
+ case GL_REFLECTION_MAP:
+ texcoord[2] = rz;
+ break;
+ case GL_NORMAL_MAP:
+ texcoord[2] = normal[2];
+ break;
+ default:
+ _mesa_problem(ctx, "Bad R texgen in compute_texgen()");
+ return;
+ }
+ }
+
+ if (texUnit->TexGenEnabled & Q_BIT) {
+ switch (texUnit->GenQ.Mode) {
+ case GL_OBJECT_LINEAR:
+ texcoord[3] = DOT4(vObj, texUnit->GenQ.ObjectPlane);
+ break;
+ case GL_EYE_LINEAR:
+ texcoord[3] = DOT4(vEye, texUnit->GenQ.EyePlane);
+ break;
+ default:
+ _mesa_problem(ctx, "Bad Q texgen in compute_texgen()");
+ return;
+ }
+ }
+}
+
+
+/**
+ * glRasterPos transformation. Typically called via ctx->Driver.RasterPos().
+ * XXX some of this code (such as viewport xform, clip testing and setting
+ * of ctx->Current.Raster* fields) could get lifted up into the
+ * main/rasterpos.c code.
+ *
+ * \param vObj vertex position in object space
+ */
+void
+_tnl_RasterPos(struct gl_context *ctx, const GLfloat vObj[4])
+{
+ if (ctx->VertexProgram._Enabled) {
+ /* XXX implement this */
+ _mesa_problem(ctx, "Vertex programs not implemented for glRasterPos");
+ return;
+ }
+ else {
+ GLfloat eye[4], clip[4], ndc[3], d;
+ GLfloat *norm, eyenorm[3];
+ GLfloat *objnorm = ctx->Current.Attrib[VERT_ATTRIB_NORMAL];
+
+ /* apply modelview matrix: eye = MV * obj */
+ TRANSFORM_POINT( eye, ctx->ModelviewMatrixStack.Top->m, vObj );
+ /* apply projection matrix: clip = Proj * eye */
+ TRANSFORM_POINT( clip, ctx->ProjectionMatrixStack.Top->m, eye );
+
+ /* clip to view volume. */
+ if (!ctx->Transform.DepthClamp) {
+ if (viewclip_point_z(clip) == 0) {
+ ctx->Current.RasterPosValid = GL_FALSE;
+ return;
+ }
+ }
+ if (!ctx->Transform.RasterPositionUnclipped) {
+ if (viewclip_point_xy(clip) == 0) {
+ ctx->Current.RasterPosValid = GL_FALSE;
+ return;
+ }
+ }
+
+ /* clip to user clipping planes */
+ if (ctx->Transform.ClipPlanesEnabled && !userclip_point(ctx, clip)) {
+ ctx->Current.RasterPosValid = GL_FALSE;
+ return;
+ }
+
+ /* ndc = clip / W */
+ d = (clip[3] == 0.0F) ? 1.0F : 1.0F / clip[3];
+ ndc[0] = clip[0] * d;
+ ndc[1] = clip[1] * d;
+ ndc[2] = clip[2] * d;
+ /* wincoord = viewport_mapping(ndc) */
+ ctx->Current.RasterPos[0] = (ndc[0] * ctx->Viewport._WindowMap.m[MAT_SX]
+ + ctx->Viewport._WindowMap.m[MAT_TX]);
+ ctx->Current.RasterPos[1] = (ndc[1] * ctx->Viewport._WindowMap.m[MAT_SY]
+ + ctx->Viewport._WindowMap.m[MAT_TY]);
+ ctx->Current.RasterPos[2] = (ndc[2] * ctx->Viewport._WindowMap.m[MAT_SZ]
+ + ctx->Viewport._WindowMap.m[MAT_TZ])
+ / ctx->DrawBuffer->_DepthMaxF;
+ ctx->Current.RasterPos[3] = clip[3];
+
+ if (ctx->Transform.DepthClamp) {
+ ctx->Current.RasterPos[3] = CLAMP(ctx->Current.RasterPos[3],
+ ctx->Viewport.Near,
+ ctx->Viewport.Far);
+ }
+
+ /* compute raster distance */
+ if (ctx->Fog.FogCoordinateSource == GL_FOG_COORDINATE_EXT)
+ ctx->Current.RasterDistance = ctx->Current.Attrib[VERT_ATTRIB_FOG][0];
+ else
+ ctx->Current.RasterDistance =
+ SQRTF( eye[0]*eye[0] + eye[1]*eye[1] + eye[2]*eye[2] );
+
+ /* compute transformed normal vector (for lighting or texgen) */
+ if (ctx->_NeedEyeCoords) {
+ const GLfloat *inv = ctx->ModelviewMatrixStack.Top->inv;
+ TRANSFORM_NORMAL( eyenorm, objnorm, inv );
+ norm = eyenorm;
+ }
+ else {
+ norm = objnorm;
+ }
+
+ /* update raster color */
+ if (ctx->Light.Enabled) {
+ /* lighting */
+ shade_rastpos( ctx, vObj, norm,
+ ctx->Current.RasterColor,
+ ctx->Current.RasterSecondaryColor );
+ }
+ else {
+ /* use current color */
+ COPY_4FV(ctx->Current.RasterColor,
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR0]);
+ COPY_4FV(ctx->Current.RasterSecondaryColor,
+ ctx->Current.Attrib[VERT_ATTRIB_COLOR1]);
+ }
+
+ /* texture coords */
+ {
+ GLuint u;
+ for (u = 0; u < ctx->Const.MaxTextureCoordUnits; u++) {
+ GLfloat tc[4];
+ COPY_4V(tc, ctx->Current.Attrib[VERT_ATTRIB_TEX0 + u]);
+ if (ctx->Texture.Unit[u].TexGenEnabled) {
+ compute_texgen(ctx, vObj, eye, norm, u, tc);
+ }
+ TRANSFORM_POINT(ctx->Current.RasterTexCoords[u],
+ ctx->TextureMatrixStack[u].Top->m, tc);
+ }
+ }
+
+ ctx->Current.RasterPosValid = GL_TRUE;
+ }
+
+ if (ctx->RenderMode == GL_SELECT) {
+ _mesa_update_hitflag( ctx, ctx->Current.RasterPos[2] );
+ }
+}
diff --git a/mesalib/src/mesa/tnl/t_vb_cliptmp.h b/mesalib/src/mesa/tnl/t_vb_cliptmp.h index 8cc36e666..b67aaddda 100644 --- a/mesalib/src/mesa/tnl/t_vb_cliptmp.h +++ b/mesalib/src/mesa/tnl/t_vb_cliptmp.h @@ -1,320 +1,320 @@ -/* - * Mesa 3-D graphics library - * Version: 6.5.2 - * - * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Keith Whitwell <keith@tungstengraphics.com> - */ - - -#define CLIP_DOTPROD(K, A, B, C, D) X(K)*A + Y(K)*B + Z(K)*C + W(K)*D - -#define POLY_CLIP( PLANE_BIT, A, B, C, D ) \ -do { \ - if (mask & PLANE_BIT) { \ - GLuint idxPrev = inlist[0]; \ - GLfloat dpPrev = CLIP_DOTPROD(idxPrev, A, B, C, D ); \ - GLuint outcount = 0; \ - GLuint i; \ - \ - inlist[n] = inlist[0]; /* prevent rotation of vertices */ \ - for (i = 1; i <= n; i++) { \ - GLuint idx = inlist[i]; \ - GLfloat dp = CLIP_DOTPROD(idx, A, B, C, D ); \ - \ - if (!IS_NEGATIVE(dpPrev)) { \ - outlist[outcount++] = idxPrev; \ - } \ - \ - if (DIFFERENT_SIGNS(dp, dpPrev)) { \ - if (IS_NEGATIVE(dp)) { \ - /* Going out of bounds. Avoid division by zero as we \ - * know dp != dpPrev from DIFFERENT_SIGNS, above. \ - */ \ - GLfloat t = dp / (dp - dpPrev); \ - INTERP_4F( t, coord[newvert], coord[idx], coord[idxPrev]); \ - interp( ctx, t, newvert, idx, idxPrev, GL_TRUE ); \ - } else { \ - /* Coming back in. \ - */ \ - GLfloat t = dpPrev / (dpPrev - dp); \ - INTERP_4F( t, coord[newvert], coord[idxPrev], coord[idx]); \ - interp( ctx, t, newvert, idxPrev, idx, GL_FALSE ); \ - } \ - outlist[outcount++] = newvert++; \ - } \ - \ - idxPrev = idx; \ - dpPrev = dp; \ - } \ - \ - if (outcount < 3) \ - return; \ - \ - { \ - GLuint *tmp = inlist; \ - inlist = outlist; \ - outlist = tmp; \ - n = outcount; \ - } \ - } \ -} while (0) - - -#define LINE_CLIP(PLANE_BIT, A, B, C, D ) \ -do { \ - if (mask & PLANE_BIT) { \ - const GLfloat dp0 = CLIP_DOTPROD( v0, A, B, C, D ); \ - const GLfloat dp1 = CLIP_DOTPROD( v1, A, B, C, D ); \ - const GLboolean neg_dp0 = IS_NEGATIVE(dp0); \ - const GLboolean neg_dp1 = IS_NEGATIVE(dp1); \ - \ - /* For regular clipping, we know from the clipmask that one \ - * (or both) of these must be negative (otherwise we wouldn't \ - * be here). \ - * For userclip, there is only a single bit for all active \ - * planes, so we can end up here when there is nothing to do, \ - * hence the second IS_NEGATIVE() test: \ - */ \ - if (neg_dp0 && neg_dp1) \ - return; /* both vertices outside clip plane: discard */ \ - \ - if (neg_dp1) { \ - GLfloat t = dp1 / (dp1 - dp0); \ - if (t > t1) t1 = t; \ - } else if (neg_dp0) { \ - GLfloat t = dp0 / (dp0 - dp1); \ - if (t > t0) t0 = t; \ - } \ - if (t0 + t1 >= 1.0) \ - return; /* discard */ \ - } \ -} while (0) - - - -/* Clip a line against the viewport and user clip planes. - */ -static INLINE void -TAG(clip_line)( GLcontext *ctx, GLuint v0, GLuint v1, GLubyte mask ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - tnl_interp_func interp = tnl->Driver.Render.Interp; - GLfloat (*coord)[4] = VB->ClipPtr->data; - GLuint newvert = VB->Count; - GLfloat t0 = 0; - GLfloat t1 = 0; - GLuint p; - const GLuint v0_orig = v0; - - if (mask & CLIP_FRUSTUM_BITS) { - LINE_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 ); - LINE_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 ); - LINE_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 ); - LINE_CLIP( CLIP_BOTTOM_BIT, 0, 1, 0, 1 ); - LINE_CLIP( CLIP_FAR_BIT, 0, 0, -1, 1 ); - LINE_CLIP( CLIP_NEAR_BIT, 0, 0, 1, 1 ); - } - - if (mask & CLIP_USER_BIT) { - for (p = 0; p < ctx->Const.MaxClipPlanes; p++) { - if (ctx->Transform.ClipPlanesEnabled & (1 << p)) { - const GLfloat a = ctx->Transform._ClipUserPlane[p][0]; - const GLfloat b = ctx->Transform._ClipUserPlane[p][1]; - const GLfloat c = ctx->Transform._ClipUserPlane[p][2]; - const GLfloat d = ctx->Transform._ClipUserPlane[p][3]; - LINE_CLIP( CLIP_USER_BIT, a, b, c, d ); - } - } - } - - if (VB->ClipMask[v0]) { - INTERP_4F( t0, coord[newvert], coord[v0], coord[v1] ); - interp( ctx, t0, newvert, v0, v1, GL_FALSE ); - v0 = newvert; - newvert++; - } - else { - ASSERT(t0 == 0.0); - } - - /* Note: we need to use vertex v0_orig when computing the new - * interpolated/clipped vertex position, not the current v0 which - * may have got set when we clipped the other end of the line! - */ - if (VB->ClipMask[v1]) { - INTERP_4F( t1, coord[newvert], coord[v1], coord[v0_orig] ); - interp( ctx, t1, newvert, v1, v0_orig, GL_FALSE ); - - if (ctx->Light.ShadeModel == GL_FLAT) - tnl->Driver.Render.CopyPV( ctx, newvert, v1 ); - - v1 = newvert; - - newvert++; - } - else { - ASSERT(t1 == 0.0); - } - - tnl->Driver.Render.ClippedLine( ctx, v0, v1 ); -} - - -/* Clip a triangle against the viewport and user clip planes. - */ -static INLINE void -TAG(clip_tri)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLubyte mask ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - tnl_interp_func interp = tnl->Driver.Render.Interp; - GLuint newvert = VB->Count; - GLfloat (*coord)[4] = VB->ClipPtr->data; - GLuint pv = v2; - GLuint vlist[2][MAX_CLIPPED_VERTICES]; - GLuint *inlist = vlist[0], *outlist = vlist[1]; - GLuint p; - GLuint n = 3; - - ASSIGN_3V(inlist, v2, v0, v1 ); /* pv rotated to slot zero */ - - if (0) { - /* print pre-clip vertex coords */ - GLuint i, j; - printf("pre clip:\n"); - for (i = 0; i < n; i++) { - j = inlist[i]; - printf(" %u: %u: %f, %f, %f, %f\n", - i, j, - coord[j][0], coord[j][1], coord[j][2], coord[j][3]); - assert(!IS_INF_OR_NAN(coord[j][0])); - assert(!IS_INF_OR_NAN(coord[j][1])); - assert(!IS_INF_OR_NAN(coord[j][2])); - assert(!IS_INF_OR_NAN(coord[j][3])); - } - } - - - if (mask & CLIP_FRUSTUM_BITS) { - POLY_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 ); - POLY_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 ); - POLY_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 ); - POLY_CLIP( CLIP_BOTTOM_BIT, 0, 1, 0, 1 ); - POLY_CLIP( CLIP_FAR_BIT, 0, 0, -1, 1 ); - POLY_CLIP( CLIP_NEAR_BIT, 0, 0, 1, 1 ); - } - - if (mask & CLIP_USER_BIT) { - for (p = 0; p < ctx->Const.MaxClipPlanes; p++) { - if (ctx->Transform.ClipPlanesEnabled & (1 << p)) { - const GLfloat a = ctx->Transform._ClipUserPlane[p][0]; - const GLfloat b = ctx->Transform._ClipUserPlane[p][1]; - const GLfloat c = ctx->Transform._ClipUserPlane[p][2]; - const GLfloat d = ctx->Transform._ClipUserPlane[p][3]; - POLY_CLIP( CLIP_USER_BIT, a, b, c, d ); - } - } - } - - if (ctx->Light.ShadeModel == GL_FLAT) { - if (pv != inlist[0]) { - ASSERT( inlist[0] >= VB->Count ); - tnl->Driver.Render.CopyPV( ctx, inlist[0], pv ); - } - } - - if (0) { - /* print post-clip vertex coords */ - GLuint i, j; - printf("post clip:\n"); - for (i = 0; i < n; i++) { - j = inlist[i]; - printf(" %u: %u: %f, %f, %f, %f\n", - i, j, - coord[j][0], coord[j][1], coord[j][2], coord[j][3]); - } - } - - tnl->Driver.Render.ClippedPolygon( ctx, inlist, n ); -} - - -/* Clip a quad against the viewport and user clip planes. - */ -static INLINE void -TAG(clip_quad)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3, - GLubyte mask ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - tnl_interp_func interp = tnl->Driver.Render.Interp; - GLuint newvert = VB->Count; - GLfloat (*coord)[4] = VB->ClipPtr->data; - GLuint pv = v3; - GLuint vlist[2][MAX_CLIPPED_VERTICES]; - GLuint *inlist = vlist[0], *outlist = vlist[1]; - GLuint p; - GLuint n = 4; - - ASSIGN_4V(inlist, v3, v0, v1, v2 ); /* pv rotated to slot zero */ - - if (mask & CLIP_FRUSTUM_BITS) { - POLY_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 ); - POLY_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 ); - POLY_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 ); - POLY_CLIP( CLIP_BOTTOM_BIT, 0, 1, 0, 1 ); - POLY_CLIP( CLIP_FAR_BIT, 0, 0, -1, 1 ); - POLY_CLIP( CLIP_NEAR_BIT, 0, 0, 1, 1 ); - } - - if (mask & CLIP_USER_BIT) { - for (p = 0; p < ctx->Const.MaxClipPlanes; p++) { - if (ctx->Transform.ClipPlanesEnabled & (1 << p)) { - const GLfloat a = ctx->Transform._ClipUserPlane[p][0]; - const GLfloat b = ctx->Transform._ClipUserPlane[p][1]; - const GLfloat c = ctx->Transform._ClipUserPlane[p][2]; - const GLfloat d = ctx->Transform._ClipUserPlane[p][3]; - POLY_CLIP( CLIP_USER_BIT, a, b, c, d ); - } - } - } - - if (ctx->Light.ShadeModel == GL_FLAT) { - if (pv != inlist[0]) { - ASSERT( inlist[0] >= VB->Count ); - tnl->Driver.Render.CopyPV( ctx, inlist[0], pv ); - } - } - - tnl->Driver.Render.ClippedPolygon( ctx, inlist, n ); -} - -#undef W -#undef Z -#undef Y -#undef X -#undef SIZE -#undef TAG -#undef POLY_CLIP -#undef LINE_CLIP +/*
+ * Mesa 3-D graphics library
+ * Version: 6.5.2
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#define CLIP_DOTPROD(K, A, B, C, D) X(K)*A + Y(K)*B + Z(K)*C + W(K)*D
+
+#define POLY_CLIP( PLANE_BIT, A, B, C, D ) \
+do { \
+ if (mask & PLANE_BIT) { \
+ GLuint idxPrev = inlist[0]; \
+ GLfloat dpPrev = CLIP_DOTPROD(idxPrev, A, B, C, D ); \
+ GLuint outcount = 0; \
+ GLuint i; \
+ \
+ inlist[n] = inlist[0]; /* prevent rotation of vertices */ \
+ for (i = 1; i <= n; i++) { \
+ GLuint idx = inlist[i]; \
+ GLfloat dp = CLIP_DOTPROD(idx, A, B, C, D ); \
+ \
+ if (!IS_NEGATIVE(dpPrev)) { \
+ outlist[outcount++] = idxPrev; \
+ } \
+ \
+ if (DIFFERENT_SIGNS(dp, dpPrev)) { \
+ if (IS_NEGATIVE(dp)) { \
+ /* Going out of bounds. Avoid division by zero as we \
+ * know dp != dpPrev from DIFFERENT_SIGNS, above. \
+ */ \
+ GLfloat t = dp / (dp - dpPrev); \
+ INTERP_4F( t, coord[newvert], coord[idx], coord[idxPrev]); \
+ interp( ctx, t, newvert, idx, idxPrev, GL_TRUE ); \
+ } else { \
+ /* Coming back in. \
+ */ \
+ GLfloat t = dpPrev / (dpPrev - dp); \
+ INTERP_4F( t, coord[newvert], coord[idxPrev], coord[idx]); \
+ interp( ctx, t, newvert, idxPrev, idx, GL_FALSE ); \
+ } \
+ outlist[outcount++] = newvert++; \
+ } \
+ \
+ idxPrev = idx; \
+ dpPrev = dp; \
+ } \
+ \
+ if (outcount < 3) \
+ return; \
+ \
+ { \
+ GLuint *tmp = inlist; \
+ inlist = outlist; \
+ outlist = tmp; \
+ n = outcount; \
+ } \
+ } \
+} while (0)
+
+
+#define LINE_CLIP(PLANE_BIT, A, B, C, D ) \
+do { \
+ if (mask & PLANE_BIT) { \
+ const GLfloat dp0 = CLIP_DOTPROD( v0, A, B, C, D ); \
+ const GLfloat dp1 = CLIP_DOTPROD( v1, A, B, C, D ); \
+ const GLboolean neg_dp0 = IS_NEGATIVE(dp0); \
+ const GLboolean neg_dp1 = IS_NEGATIVE(dp1); \
+ \
+ /* For regular clipping, we know from the clipmask that one \
+ * (or both) of these must be negative (otherwise we wouldn't \
+ * be here). \
+ * For userclip, there is only a single bit for all active \
+ * planes, so we can end up here when there is nothing to do, \
+ * hence the second IS_NEGATIVE() test: \
+ */ \
+ if (neg_dp0 && neg_dp1) \
+ return; /* both vertices outside clip plane: discard */ \
+ \
+ if (neg_dp1) { \
+ GLfloat t = dp1 / (dp1 - dp0); \
+ if (t > t1) t1 = t; \
+ } else if (neg_dp0) { \
+ GLfloat t = dp0 / (dp0 - dp1); \
+ if (t > t0) t0 = t; \
+ } \
+ if (t0 + t1 >= 1.0) \
+ return; /* discard */ \
+ } \
+} while (0)
+
+
+
+/* Clip a line against the viewport and user clip planes.
+ */
+static INLINE void
+TAG(clip_line)( struct gl_context *ctx, GLuint v0, GLuint v1, GLubyte mask )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ tnl_interp_func interp = tnl->Driver.Render.Interp;
+ GLfloat (*coord)[4] = VB->ClipPtr->data;
+ GLuint newvert = VB->Count;
+ GLfloat t0 = 0;
+ GLfloat t1 = 0;
+ GLuint p;
+ const GLuint v0_orig = v0;
+
+ if (mask & CLIP_FRUSTUM_BITS) {
+ LINE_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 );
+ LINE_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 );
+ LINE_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 );
+ LINE_CLIP( CLIP_BOTTOM_BIT, 0, 1, 0, 1 );
+ LINE_CLIP( CLIP_FAR_BIT, 0, 0, -1, 1 );
+ LINE_CLIP( CLIP_NEAR_BIT, 0, 0, 1, 1 );
+ }
+
+ if (mask & CLIP_USER_BIT) {
+ for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
+ if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
+ const GLfloat a = ctx->Transform._ClipUserPlane[p][0];
+ const GLfloat b = ctx->Transform._ClipUserPlane[p][1];
+ const GLfloat c = ctx->Transform._ClipUserPlane[p][2];
+ const GLfloat d = ctx->Transform._ClipUserPlane[p][3];
+ LINE_CLIP( CLIP_USER_BIT, a, b, c, d );
+ }
+ }
+ }
+
+ if (VB->ClipMask[v0]) {
+ INTERP_4F( t0, coord[newvert], coord[v0], coord[v1] );
+ interp( ctx, t0, newvert, v0, v1, GL_FALSE );
+ v0 = newvert;
+ newvert++;
+ }
+ else {
+ ASSERT(t0 == 0.0);
+ }
+
+ /* Note: we need to use vertex v0_orig when computing the new
+ * interpolated/clipped vertex position, not the current v0 which
+ * may have got set when we clipped the other end of the line!
+ */
+ if (VB->ClipMask[v1]) {
+ INTERP_4F( t1, coord[newvert], coord[v1], coord[v0_orig] );
+ interp( ctx, t1, newvert, v1, v0_orig, GL_FALSE );
+
+ if (ctx->Light.ShadeModel == GL_FLAT)
+ tnl->Driver.Render.CopyPV( ctx, newvert, v1 );
+
+ v1 = newvert;
+
+ newvert++;
+ }
+ else {
+ ASSERT(t1 == 0.0);
+ }
+
+ tnl->Driver.Render.ClippedLine( ctx, v0, v1 );
+}
+
+
+/* Clip a triangle against the viewport and user clip planes.
+ */
+static INLINE void
+TAG(clip_tri)( struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2, GLubyte mask )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ tnl_interp_func interp = tnl->Driver.Render.Interp;
+ GLuint newvert = VB->Count;
+ GLfloat (*coord)[4] = VB->ClipPtr->data;
+ GLuint pv = v2;
+ GLuint vlist[2][MAX_CLIPPED_VERTICES];
+ GLuint *inlist = vlist[0], *outlist = vlist[1];
+ GLuint p;
+ GLuint n = 3;
+
+ ASSIGN_3V(inlist, v2, v0, v1 ); /* pv rotated to slot zero */
+
+ if (0) {
+ /* print pre-clip vertex coords */
+ GLuint i, j;
+ printf("pre clip:\n");
+ for (i = 0; i < n; i++) {
+ j = inlist[i];
+ printf(" %u: %u: %f, %f, %f, %f\n",
+ i, j,
+ coord[j][0], coord[j][1], coord[j][2], coord[j][3]);
+ assert(!IS_INF_OR_NAN(coord[j][0]));
+ assert(!IS_INF_OR_NAN(coord[j][1]));
+ assert(!IS_INF_OR_NAN(coord[j][2]));
+ assert(!IS_INF_OR_NAN(coord[j][3]));
+ }
+ }
+
+
+ if (mask & CLIP_FRUSTUM_BITS) {
+ POLY_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 );
+ POLY_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 );
+ POLY_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 );
+ POLY_CLIP( CLIP_BOTTOM_BIT, 0, 1, 0, 1 );
+ POLY_CLIP( CLIP_FAR_BIT, 0, 0, -1, 1 );
+ POLY_CLIP( CLIP_NEAR_BIT, 0, 0, 1, 1 );
+ }
+
+ if (mask & CLIP_USER_BIT) {
+ for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
+ if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
+ const GLfloat a = ctx->Transform._ClipUserPlane[p][0];
+ const GLfloat b = ctx->Transform._ClipUserPlane[p][1];
+ const GLfloat c = ctx->Transform._ClipUserPlane[p][2];
+ const GLfloat d = ctx->Transform._ClipUserPlane[p][3];
+ POLY_CLIP( CLIP_USER_BIT, a, b, c, d );
+ }
+ }
+ }
+
+ if (ctx->Light.ShadeModel == GL_FLAT) {
+ if (pv != inlist[0]) {
+ ASSERT( inlist[0] >= VB->Count );
+ tnl->Driver.Render.CopyPV( ctx, inlist[0], pv );
+ }
+ }
+
+ if (0) {
+ /* print post-clip vertex coords */
+ GLuint i, j;
+ printf("post clip:\n");
+ for (i = 0; i < n; i++) {
+ j = inlist[i];
+ printf(" %u: %u: %f, %f, %f, %f\n",
+ i, j,
+ coord[j][0], coord[j][1], coord[j][2], coord[j][3]);
+ }
+ }
+
+ tnl->Driver.Render.ClippedPolygon( ctx, inlist, n );
+}
+
+
+/* Clip a quad against the viewport and user clip planes.
+ */
+static INLINE void
+TAG(clip_quad)( struct gl_context *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3,
+ GLubyte mask )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ tnl_interp_func interp = tnl->Driver.Render.Interp;
+ GLuint newvert = VB->Count;
+ GLfloat (*coord)[4] = VB->ClipPtr->data;
+ GLuint pv = v3;
+ GLuint vlist[2][MAX_CLIPPED_VERTICES];
+ GLuint *inlist = vlist[0], *outlist = vlist[1];
+ GLuint p;
+ GLuint n = 4;
+
+ ASSIGN_4V(inlist, v3, v0, v1, v2 ); /* pv rotated to slot zero */
+
+ if (mask & CLIP_FRUSTUM_BITS) {
+ POLY_CLIP( CLIP_RIGHT_BIT, -1, 0, 0, 1 );
+ POLY_CLIP( CLIP_LEFT_BIT, 1, 0, 0, 1 );
+ POLY_CLIP( CLIP_TOP_BIT, 0, -1, 0, 1 );
+ POLY_CLIP( CLIP_BOTTOM_BIT, 0, 1, 0, 1 );
+ POLY_CLIP( CLIP_FAR_BIT, 0, 0, -1, 1 );
+ POLY_CLIP( CLIP_NEAR_BIT, 0, 0, 1, 1 );
+ }
+
+ if (mask & CLIP_USER_BIT) {
+ for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
+ if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
+ const GLfloat a = ctx->Transform._ClipUserPlane[p][0];
+ const GLfloat b = ctx->Transform._ClipUserPlane[p][1];
+ const GLfloat c = ctx->Transform._ClipUserPlane[p][2];
+ const GLfloat d = ctx->Transform._ClipUserPlane[p][3];
+ POLY_CLIP( CLIP_USER_BIT, a, b, c, d );
+ }
+ }
+ }
+
+ if (ctx->Light.ShadeModel == GL_FLAT) {
+ if (pv != inlist[0]) {
+ ASSERT( inlist[0] >= VB->Count );
+ tnl->Driver.Render.CopyPV( ctx, inlist[0], pv );
+ }
+ }
+
+ tnl->Driver.Render.ClippedPolygon( ctx, inlist, n );
+}
+
+#undef W
+#undef Z
+#undef Y
+#undef X
+#undef SIZE
+#undef TAG
+#undef POLY_CLIP
+#undef LINE_CLIP
diff --git a/mesalib/src/mesa/tnl/t_vb_cull.c b/mesalib/src/mesa/tnl/t_vb_cull.c deleted file mode 100644 index 22df71667..000000000 --- a/mesalib/src/mesa/tnl/t_vb_cull.c +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Mesa 3-D graphics library - * Version: 6.5 - * - * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Keith Whitwell <keith@tungstengraphics.com> - */ - - -#include "main/glheader.h" -#include "main/colormac.h" -#include "main/macros.h" -#include "main/imports.h" -#include "main/mtypes.h" - -#include "math/m_xform.h" - -#include "t_context.h" -#include "t_pipeline.h" - - - -/* EXT_vertex_cull. Not really a big win, but probably depends on - * your application. This stage not included in the default pipeline. - */ -static GLboolean run_cull_stage( GLcontext *ctx, - struct tnl_pipeline_stage *stage ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - - const GLfloat a = ctx->Transform.CullObjPos[0]; - const GLfloat b = ctx->Transform.CullObjPos[1]; - const GLfloat c = ctx->Transform.CullObjPos[2]; - GLfloat *norm = (GLfloat *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data; - GLuint stride = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride; - GLuint count = VB->Count; - GLuint i; - - if (ctx->VertexProgram._Current || - !ctx->Transform.CullVertexFlag) - return GL_TRUE; - - VB->ClipOrMask &= ~CLIP_CULL_BIT; - VB->ClipAndMask |= CLIP_CULL_BIT; - - for (i = 0 ; i < count ; i++) { - GLfloat dp = (norm[0] * a + - norm[1] * b + - norm[2] * c); - - if (dp < 0) { - VB->ClipMask[i] |= CLIP_CULL_BIT; - VB->ClipOrMask |= CLIP_CULL_BIT; - } - else { - VB->ClipMask[i] &= ~CLIP_CULL_BIT; - VB->ClipAndMask &= ~CLIP_CULL_BIT; - } - - STRIDE_F(norm, stride); - } - - return !(VB->ClipAndMask & CLIP_CULL_BIT); -} - - - -const struct tnl_pipeline_stage _tnl_vertex_cull_stage = -{ - "EXT_cull_vertex", - NULL, /* private data */ - NULL, /* ctr */ - NULL, /* destructor */ - NULL, - run_cull_stage /* run -- initially set to init */ -}; diff --git a/mesalib/src/mesa/tnl/t_vb_fog.c b/mesalib/src/mesa/tnl/t_vb_fog.c index 9faae24ec..3e5c99735 100644 --- a/mesalib/src/mesa/tnl/t_vb_fog.c +++ b/mesalib/src/mesa/tnl/t_vb_fog.c @@ -1,276 +1,276 @@ -/* - * Mesa 3-D graphics library - * Version: 6.5 - * - * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Keith Whitwell <keith@tungstengraphics.com> - */ - - -#include "main/glheader.h" -#include "main/colormac.h" -#include "main/macros.h" -#include "main/imports.h" -#include "main/mtypes.h" - -#include "math/m_xform.h" - -#include "t_context.h" -#include "t_pipeline.h" - - -struct fog_stage_data { - GLvector4f fogcoord; /* has actual storage allocated */ -}; - -#define FOG_STAGE_DATA(stage) ((struct fog_stage_data *)stage->privatePtr) - -#define FOG_EXP_TABLE_SIZE 256 -#define FOG_MAX (10.0) -#define EXP_FOG_MAX .0006595 -#define FOG_INCR (FOG_MAX/FOG_EXP_TABLE_SIZE) -static GLfloat exp_table[FOG_EXP_TABLE_SIZE]; -static GLfloat inited = 0; - -#if 1 -#define NEG_EXP( result, narg ) \ -do { \ - GLfloat f = (GLfloat) (narg * (1.0/FOG_INCR)); \ - GLint k = (GLint) f; \ - if (k > FOG_EXP_TABLE_SIZE-2) \ - result = (GLfloat) EXP_FOG_MAX; \ - else \ - result = exp_table[k] + (f-k)*(exp_table[k+1]-exp_table[k]); \ -} while (0) -#else -#define NEG_EXP( result, narg ) \ -do { \ - result = exp(-narg); \ -} while (0) -#endif - - -/** - * Initialize the exp_table[] lookup table for approximating exp(). - */ -static void -init_static_data( void ) -{ - GLfloat f = 0.0F; - GLint i = 0; - for ( ; i < FOG_EXP_TABLE_SIZE ; i++, f += FOG_INCR) { - exp_table[i] = EXPF(-f); - } - inited = 1; -} - - -/** - * Compute per-vertex fog blend factors from fog coordinates by - * evaluating the GL_LINEAR, GL_EXP or GL_EXP2 fog function. - * Fog coordinates are distances from the eye (typically between the - * near and far clip plane distances). - * Note that fogcoords may be negative, if eye z is source absolute - * value must be taken earlier. - * Fog blend factors are in the range [0,1]. - */ -static void -compute_fog_blend_factors(GLcontext *ctx, GLvector4f *out, const GLvector4f *in) -{ - GLfloat end = ctx->Fog.End; - GLfloat *v = in->start; - GLuint stride = in->stride; - GLuint n = in->count; - GLfloat (*data)[4] = out->data; - GLfloat d; - GLuint i; - - out->count = in->count; - - switch (ctx->Fog.Mode) { - case GL_LINEAR: - if (ctx->Fog.Start == ctx->Fog.End) - d = 1.0F; - else - d = 1.0F / (ctx->Fog.End - ctx->Fog.Start); - for ( i = 0 ; i < n ; i++, STRIDE_F(v, stride)) { - const GLfloat z = *v; - GLfloat f = (end - z) * d; - data[i][0] = CLAMP(f, 0.0F, 1.0F); - } - break; - case GL_EXP: - d = ctx->Fog.Density; - for ( i = 0 ; i < n ; i++, STRIDE_F(v,stride)) { - const GLfloat z = *v; - NEG_EXP( data[i][0], d * z ); - } - break; - case GL_EXP2: - d = ctx->Fog.Density*ctx->Fog.Density; - for ( i = 0 ; i < n ; i++, STRIDE_F(v, stride)) { - const GLfloat z = *v; - NEG_EXP( data[i][0], d * z * z ); - } - break; - default: - _mesa_problem(ctx, "Bad fog mode in make_fog_coord"); - return; - } -} - - -static GLboolean -run_fog_stage(GLcontext *ctx, struct tnl_pipeline_stage *stage) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - struct fog_stage_data *store = FOG_STAGE_DATA(stage); - GLvector4f *input; - - - if (!ctx->Fog.Enabled) - return GL_TRUE; - - if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT && !ctx->VertexProgram._Current) { - GLuint i; - GLfloat *coord; - /* Fog is computed from vertex or fragment Z values */ - /* source = VB->AttribPtr[_TNL_ATTRIB_POS] or VB->EyePtr coords */ - /* dest = VB->AttribPtr[_TNL_ATTRIB_FOG] = fog stage private storage */ - VB->AttribPtr[_TNL_ATTRIB_FOG] = &store->fogcoord; - - if (!ctx->_NeedEyeCoords) { - /* compute fog coords from object coords */ - const GLfloat *m = ctx->ModelviewMatrixStack.Top->m; - GLfloat plane[4]; - - /* Use this to store calculated eye z values: - */ - input = &store->fogcoord; - - plane[0] = m[2]; - plane[1] = m[6]; - plane[2] = m[10]; - plane[3] = m[14]; - /* Full eye coords weren't required, just calculate the - * eye Z values. - */ - _mesa_dotprod_tab[VB->AttribPtr[_TNL_ATTRIB_POS]->size] - ( (GLfloat *) input->data, - 4 * sizeof(GLfloat), - VB->AttribPtr[_TNL_ATTRIB_POS], plane ); - - input->count = VB->AttribPtr[_TNL_ATTRIB_POS]->count; - - /* make sure coords are really positive - NOTE should avoid going through array twice */ - coord = input->start; - for (i = 0; i < input->count; i++) { - *coord = FABSF(*coord); - STRIDE_F(coord, input->stride); - } - } - else { - /* fog coordinates = eye Z coordinates - need to copy for ABS */ - input = &store->fogcoord; - - if (VB->EyePtr->size < 2) - _mesa_vector4f_clean_elem( VB->EyePtr, VB->Count, 2 ); - - input->stride = 4 * sizeof(GLfloat); - input->count = VB->EyePtr->count; - coord = VB->EyePtr->start; - for (i = 0 ; i < VB->EyePtr->count; i++) { - input->data[i][0] = FABSF(coord[2]); - STRIDE_F(coord, VB->EyePtr->stride); - } - } - } - else { - /* use glFogCoord() coordinates */ - input = VB->AttribPtr[_TNL_ATTRIB_FOG]; /* source data */ - - /* input->count may be one if glFogCoord was only called once - * before glBegin. But we need to compute fog for all vertices. - */ - input->count = VB->AttribPtr[_TNL_ATTRIB_POS]->count; - - VB->AttribPtr[_TNL_ATTRIB_FOG] = &store->fogcoord; /* dest data */ - } - - if (tnl->_DoVertexFog) { - /* compute blend factors from fog coordinates */ - compute_fog_blend_factors( ctx, VB->AttribPtr[_TNL_ATTRIB_FOG], input ); - } - else { - /* results = incoming fog coords (compute fog per-fragment later) */ - VB->AttribPtr[_TNL_ATTRIB_FOG] = input; - } - - return GL_TRUE; -} - - - -/* Called the first time stage->run() is invoked. - */ -static GLboolean -alloc_fog_data(GLcontext *ctx, struct tnl_pipeline_stage *stage) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct fog_stage_data *store; - stage->privatePtr = MALLOC(sizeof(*store)); - store = FOG_STAGE_DATA(stage); - if (!store) - return GL_FALSE; - - _mesa_vector4f_alloc( &store->fogcoord, 0, tnl->vb.Size, 32 ); - - if (!inited) - init_static_data(); - - return GL_TRUE; -} - - -static void -free_fog_data(struct tnl_pipeline_stage *stage) -{ - struct fog_stage_data *store = FOG_STAGE_DATA(stage); - if (store) { - _mesa_vector4f_free( &store->fogcoord ); - FREE( store ); - stage->privatePtr = NULL; - } -} - - -const struct tnl_pipeline_stage _tnl_fog_coordinate_stage = -{ - "build fog coordinates", /* name */ - NULL, /* private_data */ - alloc_fog_data, /* dtr */ - free_fog_data, /* dtr */ - NULL, /* check */ - run_fog_stage /* run -- initially set to init. */ -}; +/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "main/glheader.h"
+#include "main/colormac.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+
+#include "math/m_xform.h"
+
+#include "t_context.h"
+#include "t_pipeline.h"
+
+
+struct fog_stage_data {
+ GLvector4f fogcoord; /* has actual storage allocated */
+};
+
+#define FOG_STAGE_DATA(stage) ((struct fog_stage_data *)stage->privatePtr)
+
+#define FOG_EXP_TABLE_SIZE 256
+#define FOG_MAX (10.0)
+#define EXP_FOG_MAX .0006595
+#define FOG_INCR (FOG_MAX/FOG_EXP_TABLE_SIZE)
+static GLfloat exp_table[FOG_EXP_TABLE_SIZE];
+static GLfloat inited = 0;
+
+#if 1
+#define NEG_EXP( result, narg ) \
+do { \
+ GLfloat f = (GLfloat) (narg * (1.0/FOG_INCR)); \
+ GLint k = (GLint) f; \
+ if (k > FOG_EXP_TABLE_SIZE-2) \
+ result = (GLfloat) EXP_FOG_MAX; \
+ else \
+ result = exp_table[k] + (f-k)*(exp_table[k+1]-exp_table[k]); \
+} while (0)
+#else
+#define NEG_EXP( result, narg ) \
+do { \
+ result = exp(-narg); \
+} while (0)
+#endif
+
+
+/**
+ * Initialize the exp_table[] lookup table for approximating exp().
+ */
+static void
+init_static_data( void )
+{
+ GLfloat f = 0.0F;
+ GLint i = 0;
+ for ( ; i < FOG_EXP_TABLE_SIZE ; i++, f += FOG_INCR) {
+ exp_table[i] = EXPF(-f);
+ }
+ inited = 1;
+}
+
+
+/**
+ * Compute per-vertex fog blend factors from fog coordinates by
+ * evaluating the GL_LINEAR, GL_EXP or GL_EXP2 fog function.
+ * Fog coordinates are distances from the eye (typically between the
+ * near and far clip plane distances).
+ * Note that fogcoords may be negative, if eye z is source absolute
+ * value must be taken earlier.
+ * Fog blend factors are in the range [0,1].
+ */
+static void
+compute_fog_blend_factors(struct gl_context *ctx, GLvector4f *out, const GLvector4f *in)
+{
+ GLfloat end = ctx->Fog.End;
+ GLfloat *v = in->start;
+ GLuint stride = in->stride;
+ GLuint n = in->count;
+ GLfloat (*data)[4] = out->data;
+ GLfloat d;
+ GLuint i;
+
+ out->count = in->count;
+
+ switch (ctx->Fog.Mode) {
+ case GL_LINEAR:
+ if (ctx->Fog.Start == ctx->Fog.End)
+ d = 1.0F;
+ else
+ d = 1.0F / (ctx->Fog.End - ctx->Fog.Start);
+ for ( i = 0 ; i < n ; i++, STRIDE_F(v, stride)) {
+ const GLfloat z = *v;
+ GLfloat f = (end - z) * d;
+ data[i][0] = CLAMP(f, 0.0F, 1.0F);
+ }
+ break;
+ case GL_EXP:
+ d = ctx->Fog.Density;
+ for ( i = 0 ; i < n ; i++, STRIDE_F(v,stride)) {
+ const GLfloat z = *v;
+ NEG_EXP( data[i][0], d * z );
+ }
+ break;
+ case GL_EXP2:
+ d = ctx->Fog.Density*ctx->Fog.Density;
+ for ( i = 0 ; i < n ; i++, STRIDE_F(v, stride)) {
+ const GLfloat z = *v;
+ NEG_EXP( data[i][0], d * z * z );
+ }
+ break;
+ default:
+ _mesa_problem(ctx, "Bad fog mode in make_fog_coord");
+ return;
+ }
+}
+
+
+static GLboolean
+run_fog_stage(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ struct fog_stage_data *store = FOG_STAGE_DATA(stage);
+ GLvector4f *input;
+
+
+ if (!ctx->Fog.Enabled)
+ return GL_TRUE;
+
+ if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT && !ctx->VertexProgram._Current) {
+ GLuint i;
+ GLfloat *coord;
+ /* Fog is computed from vertex or fragment Z values */
+ /* source = VB->AttribPtr[_TNL_ATTRIB_POS] or VB->EyePtr coords */
+ /* dest = VB->AttribPtr[_TNL_ATTRIB_FOG] = fog stage private storage */
+ VB->AttribPtr[_TNL_ATTRIB_FOG] = &store->fogcoord;
+
+ if (!ctx->_NeedEyeCoords) {
+ /* compute fog coords from object coords */
+ const GLfloat *m = ctx->ModelviewMatrixStack.Top->m;
+ GLfloat plane[4];
+
+ /* Use this to store calculated eye z values:
+ */
+ input = &store->fogcoord;
+
+ plane[0] = m[2];
+ plane[1] = m[6];
+ plane[2] = m[10];
+ plane[3] = m[14];
+ /* Full eye coords weren't required, just calculate the
+ * eye Z values.
+ */
+ _mesa_dotprod_tab[VB->AttribPtr[_TNL_ATTRIB_POS]->size]
+ ( (GLfloat *) input->data,
+ 4 * sizeof(GLfloat),
+ VB->AttribPtr[_TNL_ATTRIB_POS], plane );
+
+ input->count = VB->AttribPtr[_TNL_ATTRIB_POS]->count;
+
+ /* make sure coords are really positive
+ NOTE should avoid going through array twice */
+ coord = input->start;
+ for (i = 0; i < input->count; i++) {
+ *coord = FABSF(*coord);
+ STRIDE_F(coord, input->stride);
+ }
+ }
+ else {
+ /* fog coordinates = eye Z coordinates - need to copy for ABS */
+ input = &store->fogcoord;
+
+ if (VB->EyePtr->size < 2)
+ _mesa_vector4f_clean_elem( VB->EyePtr, VB->Count, 2 );
+
+ input->stride = 4 * sizeof(GLfloat);
+ input->count = VB->EyePtr->count;
+ coord = VB->EyePtr->start;
+ for (i = 0 ; i < VB->EyePtr->count; i++) {
+ input->data[i][0] = FABSF(coord[2]);
+ STRIDE_F(coord, VB->EyePtr->stride);
+ }
+ }
+ }
+ else {
+ /* use glFogCoord() coordinates */
+ input = VB->AttribPtr[_TNL_ATTRIB_FOG]; /* source data */
+
+ /* input->count may be one if glFogCoord was only called once
+ * before glBegin. But we need to compute fog for all vertices.
+ */
+ input->count = VB->AttribPtr[_TNL_ATTRIB_POS]->count;
+
+ VB->AttribPtr[_TNL_ATTRIB_FOG] = &store->fogcoord; /* dest data */
+ }
+
+ if (tnl->_DoVertexFog) {
+ /* compute blend factors from fog coordinates */
+ compute_fog_blend_factors( ctx, VB->AttribPtr[_TNL_ATTRIB_FOG], input );
+ }
+ else {
+ /* results = incoming fog coords (compute fog per-fragment later) */
+ VB->AttribPtr[_TNL_ATTRIB_FOG] = input;
+ }
+
+ return GL_TRUE;
+}
+
+
+
+/* Called the first time stage->run() is invoked.
+ */
+static GLboolean
+alloc_fog_data(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct fog_stage_data *store;
+ stage->privatePtr = MALLOC(sizeof(*store));
+ store = FOG_STAGE_DATA(stage);
+ if (!store)
+ return GL_FALSE;
+
+ _mesa_vector4f_alloc( &store->fogcoord, 0, tnl->vb.Size, 32 );
+
+ if (!inited)
+ init_static_data();
+
+ return GL_TRUE;
+}
+
+
+static void
+free_fog_data(struct tnl_pipeline_stage *stage)
+{
+ struct fog_stage_data *store = FOG_STAGE_DATA(stage);
+ if (store) {
+ _mesa_vector4f_free( &store->fogcoord );
+ FREE( store );
+ stage->privatePtr = NULL;
+ }
+}
+
+
+const struct tnl_pipeline_stage _tnl_fog_coordinate_stage =
+{
+ "build fog coordinates", /* name */
+ NULL, /* private_data */
+ alloc_fog_data, /* dtr */
+ free_fog_data, /* dtr */
+ NULL, /* check */
+ run_fog_stage /* run -- initially set to init. */
+};
diff --git a/mesalib/src/mesa/tnl/t_vb_light.c b/mesalib/src/mesa/tnl/t_vb_light.c index e7309aaac..0760e6630 100644 --- a/mesalib/src/mesa/tnl/t_vb_light.c +++ b/mesalib/src/mesa/tnl/t_vb_light.c @@ -1,343 +1,343 @@ -/* - * Mesa 3-D graphics library - * Version: 6.5 - * - * Copyright (C) 1999-2006 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 "main/glheader.h" -#include "main/colormac.h" -#include "main/light.h" -#include "main/macros.h" -#include "main/imports.h" -#include "main/simple_list.h" -#include "main/mtypes.h" - -#include "math/m_translate.h" - -#include "t_context.h" -#include "t_pipeline.h" - -#define LIGHT_TWOSIDE 0x1 -#define LIGHT_MATERIAL 0x2 -#define MAX_LIGHT_FUNC 0x4 - -typedef void (*light_func)( GLcontext *ctx, - struct vertex_buffer *VB, - struct tnl_pipeline_stage *stage, - GLvector4f *input ); - -/** - * Information for updating current material attributes from vertex color, - * for GL_COLOR_MATERIAL. - */ -struct material_cursor { - const GLfloat *ptr; /* points to src vertex color (in VB array) */ - GLuint stride; /* stride to next vertex color (bytes) */ - GLfloat *current; /* points to material attribute to update */ - GLuint size; /* vertex/color size: 1, 2, 3 or 4 */ -}; - -/** - * Data private to this pipeline stage. - */ -struct light_stage_data { - GLvector4f Input; - GLvector4f LitColor[2]; - GLvector4f LitSecondary[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)) - - - -/** - * 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. - * This function copies the vertex's color to the material attributes - * which are tracking glColor. - * It's called per-vertex in the lighting loop. - */ -static void -update_materials(GLcontext *ctx, struct light_stage_data *store) -{ - GLuint i; - - for (i = 0 ; i < store->mat_count ; i++) { - /* update the material */ - COPY_CLEAN_4V(store->mat[i].current, store->mat[i].size, store->mat[i].ptr); - /* increment src vertex color pointer */ - STRIDE_F(store->mat[i].ptr, store->mat[i].stride); - } - - /* recompute derived light/material values */ - _mesa_update_material( ctx, store->mat_bitmask ); - /* XXX we should only call this if we're tracking/changing the specular - * exponent. - */ - _mesa_validate_all_lighting_tables( ctx ); -} - - -/** - * Prepare things prior to running the lighting stage. - * Return number of material attributes which will track vertex color. - */ -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; - - /* Examine the ColorMaterialBitmask to determine which materials - * track vertex color. Override the material attribute's pointer - * with the color pointer for each one. - */ - if (ctx->Light.ColorMaterialEnabled) { - const GLuint bitmask = ctx->Light.ColorMaterialBitmask; - for (i = 0 ; i < MAT_ATTRIB_MAX ; i++) - if (bitmask & (1<<i)) - VB->AttribPtr[_TNL_ATTRIB_MAT_FRONT_AMBIENT + i] = VB->AttribPtr[_TNL_ATTRIB_COLOR0]; - } - - /* Now, for each material attribute that's tracking vertex color, save - * some values (ptr, stride, size, current) that we'll need in - * update_materials(), above, that'll actually copy the vertex color to - * the material attribute(s). - */ - for (i = _TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) { - if (VB->AttribPtr[i]->stride) { - const GLuint j = store->mat_count++; - const 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].size = VB->AttribPtr[i]->size; - store->mat[j].current = ctx->Light.Material.Attrib[attr]; - store->mat_bitmask |= (1<<attr); - } - } - - /* FIXME: Is this already done? - */ - _mesa_update_material( ctx, ~0 ); - _mesa_validate_all_lighting_tables( ctx ); - - return store->mat_count; -} - -/* Tables for all the shading functions. - */ -static light_func _tnl_light_tab[MAX_LIGHT_FUNC]; -static light_func _tnl_light_fast_tab[MAX_LIGHT_FUNC]; -static light_func _tnl_light_fast_single_tab[MAX_LIGHT_FUNC]; -static light_func _tnl_light_spec_tab[MAX_LIGHT_FUNC]; - -#define TAG(x) x -#define IDX (0) -#include "t_vb_lighttmp.h" - -#define TAG(x) x##_twoside -#define IDX (LIGHT_TWOSIDE) -#include "t_vb_lighttmp.h" - -#define TAG(x) x##_material -#define IDX (LIGHT_MATERIAL) -#include "t_vb_lighttmp.h" - -#define TAG(x) x##_twoside_material -#define IDX (LIGHT_TWOSIDE|LIGHT_MATERIAL) -#include "t_vb_lighttmp.h" - - -static void init_lighting_tables( void ) -{ - static int done; - - if (!done) { - init_light_tab(); - init_light_tab_twoside(); - init_light_tab_material(); - init_light_tab_twoside_material(); - done = 1; - } -} - - -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->AttribPtr[_TNL_ATTRIB_POS]; - GLuint idx; - - if (!ctx->Light.Enabled || ctx->VertexProgram._Current) - return GL_TRUE; - - /* Make sure we can talk about position x,y and z: - */ - if (input->size <= 2 && input == VB->AttribPtr[_TNL_ATTRIB_POS]) { - - _math_trans_4f( store->Input.data, - VB->AttribPtr[_TNL_ATTRIB_POS]->data, - VB->AttribPtr[_TNL_ATTRIB_POS]->stride, - GL_FLOAT, - VB->AttribPtr[_TNL_ATTRIB_POS]->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); - } - - input = &store->Input; - } - - idx = 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[idx]( ctx, VB, stage, input ); - - return GL_TRUE; -} - - -/* Called in place of do_lighting when the light table may have changed. - */ -static void validate_lighting( GLcontext *ctx, - struct tnl_pipeline_stage *stage ) -{ - light_func *tab; - - if (!ctx->Light.Enabled || ctx->VertexProgram._Current) - return; - - if (ctx->Light._NeedVertices) { - if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) - tab = _tnl_light_spec_tab; - else - tab = _tnl_light_tab; - } - else { - if (ctx->Light.EnabledList.next == ctx->Light.EnabledList.prev) - tab = _tnl_light_fast_single_tab; - else - tab = _tnl_light_fast_tab; - } - - - LIGHT_STAGE_DATA(stage)->light_func_tab = tab; - - /* This and the above should only be done on _NEW_LIGHT: - */ - TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx ); -} - - - -/* Called the first time stage->run is called. In effect, don't - * allocate data until the first time the stage is run. - */ -static GLboolean init_lighting( GLcontext *ctx, - struct tnl_pipeline_stage *stage ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct light_stage_data *store; - GLuint size = tnl->vb.Size; - - stage->privatePtr = MALLOC(sizeof(*store)); - store = LIGHT_STAGE_DATA(stage); - if (!store) - return GL_FALSE; - - /* Do onetime init. - */ - init_lighting_tables(); - - _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 ); - - store->LitColor[0].size = 4; - store->LitColor[1].size = 4; - store->LitSecondary[0].size = 3; - store->LitSecondary[1].size = 3; - - return GL_TRUE; -} - - - - -static void dtr( struct tnl_pipeline_stage *stage ) -{ - struct light_stage_data *store = LIGHT_STAGE_DATA(stage); - - if (store) { - _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] ); - FREE( store ); - stage->privatePtr = NULL; - } -} - -const struct tnl_pipeline_stage _tnl_lighting_stage = -{ - "lighting", /* name */ - NULL, /* private_data */ - init_lighting, - dtr, /* destroy */ - validate_lighting, - run_lighting -}; +/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 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 "main/glheader.h"
+#include "main/colormac.h"
+#include "main/light.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/simple_list.h"
+#include "main/mtypes.h"
+
+#include "math/m_translate.h"
+
+#include "t_context.h"
+#include "t_pipeline.h"
+
+#define LIGHT_TWOSIDE 0x1
+#define LIGHT_MATERIAL 0x2
+#define MAX_LIGHT_FUNC 0x4
+
+typedef void (*light_func)( struct gl_context *ctx,
+ struct vertex_buffer *VB,
+ struct tnl_pipeline_stage *stage,
+ GLvector4f *input );
+
+/**
+ * Information for updating current material attributes from vertex color,
+ * for GL_COLOR_MATERIAL.
+ */
+struct material_cursor {
+ const GLfloat *ptr; /* points to src vertex color (in VB array) */
+ GLuint stride; /* stride to next vertex color (bytes) */
+ GLfloat *current; /* points to material attribute to update */
+ GLuint size; /* vertex/color size: 1, 2, 3 or 4 */
+};
+
+/**
+ * Data private to this pipeline stage.
+ */
+struct light_stage_data {
+ GLvector4f Input;
+ GLvector4f LitColor[2];
+ GLvector4f LitSecondary[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))
+
+
+
+/**
+ * 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.
+ * This function copies the vertex's color to the material attributes
+ * which are tracking glColor.
+ * It's called per-vertex in the lighting loop.
+ */
+static void
+update_materials(struct gl_context *ctx, struct light_stage_data *store)
+{
+ GLuint i;
+
+ for (i = 0 ; i < store->mat_count ; i++) {
+ /* update the material */
+ COPY_CLEAN_4V(store->mat[i].current, store->mat[i].size, store->mat[i].ptr);
+ /* increment src vertex color pointer */
+ STRIDE_F(store->mat[i].ptr, store->mat[i].stride);
+ }
+
+ /* recompute derived light/material values */
+ _mesa_update_material( ctx, store->mat_bitmask );
+ /* XXX we should only call this if we're tracking/changing the specular
+ * exponent.
+ */
+ _mesa_validate_all_lighting_tables( ctx );
+}
+
+
+/**
+ * Prepare things prior to running the lighting stage.
+ * Return number of material attributes which will track vertex color.
+ */
+static GLuint
+prepare_materials(struct gl_context *ctx,
+ struct vertex_buffer *VB, struct light_stage_data *store)
+{
+ GLuint i;
+
+ store->mat_count = 0;
+ store->mat_bitmask = 0;
+
+ /* Examine the ColorMaterialBitmask to determine which materials
+ * track vertex color. Override the material attribute's pointer
+ * with the color pointer for each one.
+ */
+ if (ctx->Light.ColorMaterialEnabled) {
+ const GLuint bitmask = ctx->Light.ColorMaterialBitmask;
+ for (i = 0 ; i < MAT_ATTRIB_MAX ; i++)
+ if (bitmask & (1<<i))
+ VB->AttribPtr[_TNL_ATTRIB_MAT_FRONT_AMBIENT + i] = VB->AttribPtr[_TNL_ATTRIB_COLOR0];
+ }
+
+ /* Now, for each material attribute that's tracking vertex color, save
+ * some values (ptr, stride, size, current) that we'll need in
+ * update_materials(), above, that'll actually copy the vertex color to
+ * the material attribute(s).
+ */
+ for (i = _TNL_FIRST_MAT; i <= _TNL_LAST_MAT; i++) {
+ if (VB->AttribPtr[i]->stride) {
+ const GLuint j = store->mat_count++;
+ const 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].size = VB->AttribPtr[i]->size;
+ store->mat[j].current = ctx->Light.Material.Attrib[attr];
+ store->mat_bitmask |= (1<<attr);
+ }
+ }
+
+ /* FIXME: Is this already done?
+ */
+ _mesa_update_material( ctx, ~0 );
+ _mesa_validate_all_lighting_tables( ctx );
+
+ return store->mat_count;
+}
+
+/* Tables for all the shading functions.
+ */
+static light_func _tnl_light_tab[MAX_LIGHT_FUNC];
+static light_func _tnl_light_fast_tab[MAX_LIGHT_FUNC];
+static light_func _tnl_light_fast_single_tab[MAX_LIGHT_FUNC];
+static light_func _tnl_light_spec_tab[MAX_LIGHT_FUNC];
+
+#define TAG(x) x
+#define IDX (0)
+#include "t_vb_lighttmp.h"
+
+#define TAG(x) x##_twoside
+#define IDX (LIGHT_TWOSIDE)
+#include "t_vb_lighttmp.h"
+
+#define TAG(x) x##_material
+#define IDX (LIGHT_MATERIAL)
+#include "t_vb_lighttmp.h"
+
+#define TAG(x) x##_twoside_material
+#define IDX (LIGHT_TWOSIDE|LIGHT_MATERIAL)
+#include "t_vb_lighttmp.h"
+
+
+static void init_lighting_tables( void )
+{
+ static int done;
+
+ if (!done) {
+ init_light_tab();
+ init_light_tab_twoside();
+ init_light_tab_material();
+ init_light_tab_twoside_material();
+ done = 1;
+ }
+}
+
+
+static GLboolean run_lighting( struct gl_context *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->AttribPtr[_TNL_ATTRIB_POS];
+ GLuint idx;
+
+ if (!ctx->Light.Enabled || ctx->VertexProgram._Current)
+ return GL_TRUE;
+
+ /* Make sure we can talk about position x,y and z:
+ */
+ if (input->size <= 2 && input == VB->AttribPtr[_TNL_ATTRIB_POS]) {
+
+ _math_trans_4f( store->Input.data,
+ VB->AttribPtr[_TNL_ATTRIB_POS]->data,
+ VB->AttribPtr[_TNL_ATTRIB_POS]->stride,
+ GL_FLOAT,
+ VB->AttribPtr[_TNL_ATTRIB_POS]->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);
+ }
+
+ input = &store->Input;
+ }
+
+ idx = 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[idx]( ctx, VB, stage, input );
+
+ return GL_TRUE;
+}
+
+
+/* Called in place of do_lighting when the light table may have changed.
+ */
+static void validate_lighting( struct gl_context *ctx,
+ struct tnl_pipeline_stage *stage )
+{
+ light_func *tab;
+
+ if (!ctx->Light.Enabled || ctx->VertexProgram._Current)
+ return;
+
+ if (ctx->Light._NeedVertices) {
+ if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR)
+ tab = _tnl_light_spec_tab;
+ else
+ tab = _tnl_light_tab;
+ }
+ else {
+ if (ctx->Light.EnabledList.next == ctx->Light.EnabledList.prev)
+ tab = _tnl_light_fast_single_tab;
+ else
+ tab = _tnl_light_fast_tab;
+ }
+
+
+ LIGHT_STAGE_DATA(stage)->light_func_tab = tab;
+
+ /* This and the above should only be done on _NEW_LIGHT:
+ */
+ TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx );
+}
+
+
+
+/* Called the first time stage->run is called. In effect, don't
+ * allocate data until the first time the stage is run.
+ */
+static GLboolean init_lighting( struct gl_context *ctx,
+ struct tnl_pipeline_stage *stage )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct light_stage_data *store;
+ GLuint size = tnl->vb.Size;
+
+ stage->privatePtr = MALLOC(sizeof(*store));
+ store = LIGHT_STAGE_DATA(stage);
+ if (!store)
+ return GL_FALSE;
+
+ /* Do onetime init.
+ */
+ init_lighting_tables();
+
+ _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 );
+
+ store->LitColor[0].size = 4;
+ store->LitColor[1].size = 4;
+ store->LitSecondary[0].size = 3;
+ store->LitSecondary[1].size = 3;
+
+ return GL_TRUE;
+}
+
+
+
+
+static void dtr( struct tnl_pipeline_stage *stage )
+{
+ struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
+
+ if (store) {
+ _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] );
+ FREE( store );
+ stage->privatePtr = NULL;
+ }
+}
+
+const struct tnl_pipeline_stage _tnl_lighting_stage =
+{
+ "lighting", /* name */
+ NULL, /* private_data */
+ init_lighting,
+ dtr, /* destroy */
+ validate_lighting,
+ run_lighting
+};
diff --git a/mesalib/src/mesa/tnl/t_vb_lighttmp.h b/mesalib/src/mesa/tnl/t_vb_lighttmp.h index 0a98c6b02..63b817ab6 100644 --- a/mesalib/src/mesa/tnl/t_vb_lighttmp.h +++ b/mesalib/src/mesa/tnl/t_vb_lighttmp.h @@ -1,651 +1,651 @@ -/* - * 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: - * Brian Paul - * Keith Whitwell <keith@tungstengraphics.com> - */ - - -#if IDX & LIGHT_TWOSIDE -# define NR_SIDES 2 -#else -# define NR_SIDES 1 -#endif - - -/* define TRACE to trace lighting code */ -/* #define TRACE 1 */ - -/* - * ctx is the current context - * VB is the vertex buffer - * stage is the lighting stage-private data - * input is the vector of eye or object-space vertex coordinates - */ -static void TAG(light_rgba_spec)( GLcontext *ctx, - struct vertex_buffer *VB, - struct tnl_pipeline_stage *stage, - GLvector4f *input ) -{ - struct light_stage_data *store = LIGHT_STAGE_DATA(stage); - GLfloat (*base)[3] = ctx->Light._BaseColor; - GLfloat sumA[2]; - GLuint j; - - const GLuint vstride = input->stride; - const GLfloat *vertex = (GLfloat *)input->data; - const GLuint nstride = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride; - const GLfloat *normal = (GLfloat *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data; - - GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data; - GLfloat (*Fspec)[4] = (GLfloat (*)[4]) store->LitSecondary[0].data; -#if IDX & LIGHT_TWOSIDE - GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data; - GLfloat (*Bspec)[4] = (GLfloat (*)[4]) store->LitSecondary[1].data; -#endif - - const GLuint nr = VB->Count; - -#ifdef TRACE - fprintf(stderr, "%s\n", __FUNCTION__ ); -#endif - - VB->AttribPtr[_TNL_ATTRIB_COLOR0] = &store->LitColor[0]; - VB->AttribPtr[_TNL_ATTRIB_COLOR1] = &store->LitSecondary[0]; - sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; - -#if IDX & LIGHT_TWOSIDE - VB->BackfaceColorPtr = &store->LitColor[1]; - VB->BackfaceSecondaryColorPtr = &store->LitSecondary[1]; - sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; -#endif - - - store->LitColor[0].stride = 16; - store->LitColor[1].stride = 16; - - for (j = 0; j < nr; j++,STRIDE_F(vertex,vstride),STRIDE_F(normal,nstride)) { - GLfloat sum[2][3], spec[2][3]; - struct gl_light *light; - -#if IDX & LIGHT_MATERIAL - update_materials( ctx, store ); - 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]; -#endif -#endif - - COPY_3V(sum[0], base[0]); - ZERO_3V(spec[0]); - -#if IDX & LIGHT_TWOSIDE - COPY_3V(sum[1], base[1]); - ZERO_3V(spec[1]); -#endif - - /* Add contribution from each enabled light source */ - foreach (light, &ctx->Light.EnabledList) { - GLfloat n_dot_h; - GLfloat correction; - GLint side; - GLfloat contrib[3]; - GLfloat attenuation; - GLfloat VP[3]; /* unit vector from vertex to light */ - GLfloat n_dot_VP; /* n dot VP */ - GLfloat *h; - - /* compute VP and attenuation */ - if (!(light->_Flags & LIGHT_POSITIONAL)) { - /* directional light */ - COPY_3V(VP, light->_VP_inf_norm); - attenuation = light->_VP_inf_spot_attenuation; - } - else { - GLfloat d; /* distance from vertex to light */ - - SUB_3V(VP, light->_Position, vertex); - - d = (GLfloat) LEN_3FV( VP ); - - if (d > 1e-6) { - GLfloat invd = 1.0F / d; - SELF_SCALE_SCALAR_3V(VP, invd); - } - - attenuation = 1.0F / (light->ConstantAttenuation + d * - (light->LinearAttenuation + d * - light->QuadraticAttenuation)); - - /* spotlight attenuation */ - if (light->_Flags & LIGHT_SPOT) { - GLfloat PV_dot_dir = - DOT3(VP, light->_NormSpotDirection); - - if (PV_dot_dir<light->_CosCutoff) { - continue; /* this light makes no contribution */ - } - else { - GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1); - GLint k = (GLint) x; - GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0] - + (x-k)*light->_SpotExpTable[k][1]); - attenuation *= spot; - } - } - } - - if (attenuation < 1e-3) - continue; /* this light makes no contribution */ - - /* Compute dot product or normal and vector from V to light pos */ - n_dot_VP = DOT3( normal, VP ); - - /* Which side gets the diffuse & specular terms? */ - if (n_dot_VP < 0.0F) { - ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]); -#if IDX & LIGHT_TWOSIDE - side = 1; - correction = -1; - n_dot_VP = -n_dot_VP; -#else - continue; -#endif - } - else { -#if IDX & LIGHT_TWOSIDE - ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]); -#endif - side = 0; - correction = 1; - } - - /* diffuse term */ - COPY_3V(contrib, light->_MatAmbient[side]); - ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]); - ACC_SCALE_SCALAR_3V(sum[side], attenuation, contrib ); - - /* specular term - cannibalize VP... */ - if (ctx->Light.Model.LocalViewer) { - GLfloat v[3]; - COPY_3V(v, vertex); - NORMALIZE_3FV(v); - SUB_3V(VP, VP, v); /* h = VP + VPe */ - h = VP; - NORMALIZE_3FV(h); - } - else if (light->_Flags & LIGHT_POSITIONAL) { - h = VP; - ACC_3V(h, ctx->_EyeZDir); - NORMALIZE_3FV(h); - } - else { - h = light->_h_inf_norm; - } - - n_dot_h = correction * DOT3(normal, h); - - if (n_dot_h > 0.0F) { - GLfloat spec_coef; - struct gl_shine_tab *tab = ctx->_ShineTable[side]; - GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef ); - - if (spec_coef > 1.0e-10) { - spec_coef *= attenuation; - ACC_SCALE_SCALAR_3V( spec[side], spec_coef, - light->_MatSpecular[side]); - } - } - } /*loop over lights*/ - - COPY_3V( Fcolor[j], sum[0] ); - COPY_3V( Fspec[j], spec[0] ); - Fcolor[j][3] = sumA[0]; - -#if IDX & LIGHT_TWOSIDE - COPY_3V( Bcolor[j], sum[1] ); - COPY_3V( Bspec[j], spec[1] ); - Bcolor[j][3] = sumA[1]; -#endif - } -} - - -static void TAG(light_rgba)( GLcontext *ctx, - struct vertex_buffer *VB, - struct tnl_pipeline_stage *stage, - GLvector4f *input ) -{ - struct light_stage_data *store = LIGHT_STAGE_DATA(stage); - GLuint j; - - GLfloat (*base)[3] = ctx->Light._BaseColor; - GLfloat sumA[2]; - - const GLuint vstride = input->stride; - const GLfloat *vertex = (GLfloat *) input->data; - const GLuint nstride = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride; - const GLfloat *normal = (GLfloat *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data; - - GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data; -#if IDX & LIGHT_TWOSIDE - GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data; -#endif - - const GLuint nr = VB->Count; - -#ifdef TRACE - fprintf(stderr, "%s\n", __FUNCTION__ ); -#endif - - VB->AttribPtr[_TNL_ATTRIB_COLOR0] = &store->LitColor[0]; - sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; - -#if IDX & LIGHT_TWOSIDE - VB->BackfaceColorPtr = &store->LitColor[1]; - sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; -#endif - - store->LitColor[0].stride = 16; - store->LitColor[1].stride = 16; - - for (j = 0; j < nr; j++,STRIDE_F(vertex,vstride),STRIDE_F(normal,nstride)) { - GLfloat sum[2][3]; - struct gl_light *light; - -#if IDX & LIGHT_MATERIAL - update_materials( ctx, store ); - 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]; -#endif -#endif - - COPY_3V(sum[0], base[0]); - -#if IDX & LIGHT_TWOSIDE - COPY_3V(sum[1], base[1]); -#endif - - /* Add contribution from each enabled light source */ - foreach (light, &ctx->Light.EnabledList) { - - GLfloat n_dot_h; - GLfloat correction; - GLint side; - GLfloat contrib[3]; - GLfloat attenuation = 1.0; - GLfloat VP[3]; /* unit vector from vertex to light */ - GLfloat n_dot_VP; /* n dot VP */ - GLfloat *h; - - /* compute VP and attenuation */ - if (!(light->_Flags & LIGHT_POSITIONAL)) { - /* directional light */ - COPY_3V(VP, light->_VP_inf_norm); - attenuation = light->_VP_inf_spot_attenuation; - } - else { - GLfloat d; /* distance from vertex to light */ - - - SUB_3V(VP, light->_Position, vertex); - - d = (GLfloat) LEN_3FV( VP ); - - if ( d > 1e-6) { - GLfloat invd = 1.0F / d; - SELF_SCALE_SCALAR_3V(VP, invd); - } - - attenuation = 1.0F / (light->ConstantAttenuation + d * - (light->LinearAttenuation + d * - light->QuadraticAttenuation)); - - /* spotlight attenuation */ - if (light->_Flags & LIGHT_SPOT) { - GLfloat PV_dot_dir = - DOT3(VP, light->_NormSpotDirection); - - if (PV_dot_dir<light->_CosCutoff) { - continue; /* this light makes no contribution */ - } - else { - GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1); - GLint k = (GLint) x; - GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0] - + (x-k)*light->_SpotExpTable[k][1]); - attenuation *= spot; - } - } - } - - if (attenuation < 1e-3) - continue; /* this light makes no contribution */ - - /* Compute dot product or normal and vector from V to light pos */ - n_dot_VP = DOT3( normal, VP ); - - /* which side are we lighting? */ - if (n_dot_VP < 0.0F) { - ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]); -#if IDX & LIGHT_TWOSIDE - side = 1; - correction = -1; - n_dot_VP = -n_dot_VP; -#else - continue; -#endif - } - else { -#if IDX & LIGHT_TWOSIDE - ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]); -#endif - side = 0; - correction = 1; - } - - COPY_3V(contrib, light->_MatAmbient[side]); - - /* diffuse term */ - ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]); - - /* specular term - cannibalize VP... */ - { - if (ctx->Light.Model.LocalViewer) { - GLfloat v[3]; - COPY_3V(v, vertex); - NORMALIZE_3FV(v); - SUB_3V(VP, VP, v); /* h = VP + VPe */ - h = VP; - NORMALIZE_3FV(h); - } - else if (light->_Flags & LIGHT_POSITIONAL) { - h = VP; - ACC_3V(h, ctx->_EyeZDir); - NORMALIZE_3FV(h); - } - else { - h = light->_h_inf_norm; - } - - n_dot_h = correction * DOT3(normal, h); - - if (n_dot_h > 0.0F) - { - GLfloat spec_coef; - struct gl_shine_tab *tab = ctx->_ShineTable[side]; - - GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef ); - - ACC_SCALE_SCALAR_3V( contrib, spec_coef, - light->_MatSpecular[side]); - } - } - - ACC_SCALE_SCALAR_3V( sum[side], attenuation, contrib ); - } - - COPY_3V( Fcolor[j], sum[0] ); - Fcolor[j][3] = sumA[0]; - -#if IDX & LIGHT_TWOSIDE - COPY_3V( Bcolor[j], sum[1] ); - Bcolor[j][3] = sumA[1]; -#endif - } -} - - - - -/* As below, but with just a single light. - */ -static void TAG(light_fast_rgba_single)( GLcontext *ctx, - struct vertex_buffer *VB, - struct tnl_pipeline_stage *stage, - GLvector4f *input ) - -{ - struct light_stage_data *store = LIGHT_STAGE_DATA(stage); - const GLuint nstride = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride; - const GLfloat *normal = (GLfloat *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data; - GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data; -#if IDX & LIGHT_TWOSIDE - GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data; -#endif - const struct gl_light *light = ctx->Light.EnabledList.next; - GLuint j = 0; - GLfloat base[2][4]; -#if IDX & LIGHT_MATERIAL - const GLuint nr = VB->Count; -#else - const GLuint nr = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->count; -#endif - -#ifdef TRACE - fprintf(stderr, "%s\n", __FUNCTION__ ); -#endif - - (void) input; /* doesn't refer to Eye or Obj */ - - VB->AttribPtr[_TNL_ATTRIB_COLOR0] = &store->LitColor[0]; -#if IDX & LIGHT_TWOSIDE - VB->BackfaceColorPtr = &store->LitColor[1]; -#endif - - if (nr > 1) { - store->LitColor[0].stride = 16; - store->LitColor[1].stride = 16; - } - else { - store->LitColor[0].stride = 0; - store->LitColor[1].stride = 0; - } - - for (j = 0; j < nr; j++, STRIDE_F(normal,nstride)) { - - GLfloat n_dot_VP; - -#if IDX & LIGHT_MATERIAL - update_materials( ctx, store ); -#endif - - /* No attenuation, so incoporate _MatAmbient into base color. - */ -#if !(IDX & LIGHT_MATERIAL) - if ( j == 0 ) -#endif - { - 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]); - base[1][3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; -#endif - } - - 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]); - } - COPY_3V(Bcolor[j], sum ); - Bcolor[j][3] = base[1][3]; -#endif - 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]); - - } - COPY_3V(Fcolor[j], sum ); - Fcolor[j][3] = base[0][3]; -#if IDX & LIGHT_TWOSIDE - COPY_4FV(Bcolor[j], base[1]); -#endif - } - } -} - - -/* Light infinite lights - */ -static void TAG(light_fast_rgba)( GLcontext *ctx, - struct vertex_buffer *VB, - struct tnl_pipeline_stage *stage, - GLvector4f *input ) -{ - struct light_stage_data *store = LIGHT_STAGE_DATA(stage); - GLfloat sumA[2]; - const GLuint nstride = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride; - const GLfloat *normal = (GLfloat *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data; - GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data; -#if IDX & LIGHT_TWOSIDE - GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data; -#endif - GLuint j = 0; -#if IDX & LIGHT_MATERIAL - const GLuint nr = VB->Count; -#else - const GLuint nr = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->count; -#endif - const struct gl_light *light; - -#ifdef TRACE - fprintf(stderr, "%s %d\n", __FUNCTION__, nr ); -#endif - - (void) input; - - sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3]; - sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3]; - - VB->AttribPtr[_TNL_ATTRIB_COLOR0] = &store->LitColor[0]; -#if IDX & LIGHT_TWOSIDE - VB->BackfaceColorPtr = &store->LitColor[1]; -#endif - - if (nr > 1) { - store->LitColor[0].stride = 16; - store->LitColor[1].stride = 16; - } - else { - store->LitColor[0].stride = 0; - store->LitColor[1].stride = 0; - } - - for (j = 0; j < nr; j++, STRIDE_F(normal,nstride)) { - - GLfloat sum[2][3]; - -#if IDX & LIGHT_MATERIAL - update_materials( ctx, store ); - - 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]; -#endif -#endif - - - COPY_3V(sum[0], ctx->Light._BaseColor[0]); -#if IDX & LIGHT_TWOSIDE - COPY_3V(sum[1], ctx->Light._BaseColor[1]); -#endif - - 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]); -#endif - - 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]); - } - } -#if IDX & LIGHT_TWOSIDE - else { - 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]); - } - } -#endif - } - - COPY_3V( Fcolor[j], sum[0] ); - Fcolor[j][3] = sumA[0]; - -#if IDX & LIGHT_TWOSIDE - COPY_3V( Bcolor[j], sum[1] ); - Bcolor[j][3] = sumA[1]; -#endif - } -} - - - - -static void TAG(init_light_tab)( void ) -{ - _tnl_light_tab[IDX] = TAG(light_rgba); - _tnl_light_fast_tab[IDX] = TAG(light_fast_rgba); - _tnl_light_fast_single_tab[IDX] = TAG(light_fast_rgba_single); - _tnl_light_spec_tab[IDX] = TAG(light_rgba_spec); -} - - -#undef TAG -#undef IDX -#undef NR_SIDES +/*
+ * 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:
+ * Brian Paul
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#if IDX & LIGHT_TWOSIDE
+# define NR_SIDES 2
+#else
+# define NR_SIDES 1
+#endif
+
+
+/* define TRACE to trace lighting code */
+/* #define TRACE 1 */
+
+/*
+ * ctx is the current context
+ * VB is the vertex buffer
+ * stage is the lighting stage-private data
+ * input is the vector of eye or object-space vertex coordinates
+ */
+static void TAG(light_rgba_spec)( struct gl_context *ctx,
+ struct vertex_buffer *VB,
+ struct tnl_pipeline_stage *stage,
+ GLvector4f *input )
+{
+ struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
+ GLfloat (*base)[3] = ctx->Light._BaseColor;
+ GLfloat sumA[2];
+ GLuint j;
+
+ const GLuint vstride = input->stride;
+ const GLfloat *vertex = (GLfloat *)input->data;
+ const GLuint nstride = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride;
+ const GLfloat *normal = (GLfloat *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data;
+
+ GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data;
+ GLfloat (*Fspec)[4] = (GLfloat (*)[4]) store->LitSecondary[0].data;
+#if IDX & LIGHT_TWOSIDE
+ GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data;
+ GLfloat (*Bspec)[4] = (GLfloat (*)[4]) store->LitSecondary[1].data;
+#endif
+
+ const GLuint nr = VB->Count;
+
+#ifdef TRACE
+ fprintf(stderr, "%s\n", __FUNCTION__ );
+#endif
+
+ VB->AttribPtr[_TNL_ATTRIB_COLOR0] = &store->LitColor[0];
+ VB->AttribPtr[_TNL_ATTRIB_COLOR1] = &store->LitSecondary[0];
+ sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
+
+#if IDX & LIGHT_TWOSIDE
+ VB->BackfaceColorPtr = &store->LitColor[1];
+ VB->BackfaceSecondaryColorPtr = &store->LitSecondary[1];
+ sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
+#endif
+
+
+ store->LitColor[0].stride = 16;
+ store->LitColor[1].stride = 16;
+
+ for (j = 0; j < nr; j++,STRIDE_F(vertex,vstride),STRIDE_F(normal,nstride)) {
+ GLfloat sum[2][3], spec[2][3];
+ struct gl_light *light;
+
+#if IDX & LIGHT_MATERIAL
+ update_materials( ctx, store );
+ 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];
+#endif
+#endif
+
+ COPY_3V(sum[0], base[0]);
+ ZERO_3V(spec[0]);
+
+#if IDX & LIGHT_TWOSIDE
+ COPY_3V(sum[1], base[1]);
+ ZERO_3V(spec[1]);
+#endif
+
+ /* Add contribution from each enabled light source */
+ foreach (light, &ctx->Light.EnabledList) {
+ GLfloat n_dot_h;
+ GLfloat correction;
+ GLint side;
+ GLfloat contrib[3];
+ GLfloat attenuation;
+ GLfloat VP[3]; /* unit vector from vertex to light */
+ GLfloat n_dot_VP; /* n dot VP */
+ GLfloat *h;
+
+ /* compute VP and attenuation */
+ if (!(light->_Flags & LIGHT_POSITIONAL)) {
+ /* directional light */
+ COPY_3V(VP, light->_VP_inf_norm);
+ attenuation = light->_VP_inf_spot_attenuation;
+ }
+ else {
+ GLfloat d; /* distance from vertex to light */
+
+ SUB_3V(VP, light->_Position, vertex);
+
+ d = (GLfloat) LEN_3FV( VP );
+
+ if (d > 1e-6) {
+ GLfloat invd = 1.0F / d;
+ SELF_SCALE_SCALAR_3V(VP, invd);
+ }
+
+ attenuation = 1.0F / (light->ConstantAttenuation + d *
+ (light->LinearAttenuation + d *
+ light->QuadraticAttenuation));
+
+ /* spotlight attenuation */
+ if (light->_Flags & LIGHT_SPOT) {
+ GLfloat PV_dot_dir = - DOT3(VP, light->_NormSpotDirection);
+
+ if (PV_dot_dir<light->_CosCutoff) {
+ continue; /* this light makes no contribution */
+ }
+ else {
+ GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1);
+ GLint k = (GLint) x;
+ GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
+ + (x-k)*light->_SpotExpTable[k][1]);
+ attenuation *= spot;
+ }
+ }
+ }
+
+ if (attenuation < 1e-3)
+ continue; /* this light makes no contribution */
+
+ /* Compute dot product or normal and vector from V to light pos */
+ n_dot_VP = DOT3( normal, VP );
+
+ /* Which side gets the diffuse & specular terms? */
+ if (n_dot_VP < 0.0F) {
+ ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]);
+#if IDX & LIGHT_TWOSIDE
+ side = 1;
+ correction = -1;
+ n_dot_VP = -n_dot_VP;
+#else
+ continue;
+#endif
+ }
+ else {
+#if IDX & LIGHT_TWOSIDE
+ ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]);
+#endif
+ side = 0;
+ correction = 1;
+ }
+
+ /* diffuse term */
+ COPY_3V(contrib, light->_MatAmbient[side]);
+ ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]);
+ ACC_SCALE_SCALAR_3V(sum[side], attenuation, contrib );
+
+ /* specular term - cannibalize VP... */
+ if (ctx->Light.Model.LocalViewer) {
+ GLfloat v[3];
+ COPY_3V(v, vertex);
+ NORMALIZE_3FV(v);
+ SUB_3V(VP, VP, v); /* h = VP + VPe */
+ h = VP;
+ NORMALIZE_3FV(h);
+ }
+ else if (light->_Flags & LIGHT_POSITIONAL) {
+ h = VP;
+ ACC_3V(h, ctx->_EyeZDir);
+ NORMALIZE_3FV(h);
+ }
+ else {
+ h = light->_h_inf_norm;
+ }
+
+ n_dot_h = correction * DOT3(normal, h);
+
+ if (n_dot_h > 0.0F) {
+ GLfloat spec_coef;
+ struct gl_shine_tab *tab = ctx->_ShineTable[side];
+ GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
+
+ if (spec_coef > 1.0e-10) {
+ spec_coef *= attenuation;
+ ACC_SCALE_SCALAR_3V( spec[side], spec_coef,
+ light->_MatSpecular[side]);
+ }
+ }
+ } /*loop over lights*/
+
+ COPY_3V( Fcolor[j], sum[0] );
+ COPY_3V( Fspec[j], spec[0] );
+ Fcolor[j][3] = sumA[0];
+
+#if IDX & LIGHT_TWOSIDE
+ COPY_3V( Bcolor[j], sum[1] );
+ COPY_3V( Bspec[j], spec[1] );
+ Bcolor[j][3] = sumA[1];
+#endif
+ }
+}
+
+
+static void TAG(light_rgba)( struct gl_context *ctx,
+ struct vertex_buffer *VB,
+ struct tnl_pipeline_stage *stage,
+ GLvector4f *input )
+{
+ struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
+ GLuint j;
+
+ GLfloat (*base)[3] = ctx->Light._BaseColor;
+ GLfloat sumA[2];
+
+ const GLuint vstride = input->stride;
+ const GLfloat *vertex = (GLfloat *) input->data;
+ const GLuint nstride = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride;
+ const GLfloat *normal = (GLfloat *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data;
+
+ GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data;
+#if IDX & LIGHT_TWOSIDE
+ GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data;
+#endif
+
+ const GLuint nr = VB->Count;
+
+#ifdef TRACE
+ fprintf(stderr, "%s\n", __FUNCTION__ );
+#endif
+
+ VB->AttribPtr[_TNL_ATTRIB_COLOR0] = &store->LitColor[0];
+ sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
+
+#if IDX & LIGHT_TWOSIDE
+ VB->BackfaceColorPtr = &store->LitColor[1];
+ sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
+#endif
+
+ store->LitColor[0].stride = 16;
+ store->LitColor[1].stride = 16;
+
+ for (j = 0; j < nr; j++,STRIDE_F(vertex,vstride),STRIDE_F(normal,nstride)) {
+ GLfloat sum[2][3];
+ struct gl_light *light;
+
+#if IDX & LIGHT_MATERIAL
+ update_materials( ctx, store );
+ 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];
+#endif
+#endif
+
+ COPY_3V(sum[0], base[0]);
+
+#if IDX & LIGHT_TWOSIDE
+ COPY_3V(sum[1], base[1]);
+#endif
+
+ /* Add contribution from each enabled light source */
+ foreach (light, &ctx->Light.EnabledList) {
+
+ GLfloat n_dot_h;
+ GLfloat correction;
+ GLint side;
+ GLfloat contrib[3];
+ GLfloat attenuation = 1.0;
+ GLfloat VP[3]; /* unit vector from vertex to light */
+ GLfloat n_dot_VP; /* n dot VP */
+ GLfloat *h;
+
+ /* compute VP and attenuation */
+ if (!(light->_Flags & LIGHT_POSITIONAL)) {
+ /* directional light */
+ COPY_3V(VP, light->_VP_inf_norm);
+ attenuation = light->_VP_inf_spot_attenuation;
+ }
+ else {
+ GLfloat d; /* distance from vertex to light */
+
+
+ SUB_3V(VP, light->_Position, vertex);
+
+ d = (GLfloat) LEN_3FV( VP );
+
+ if ( d > 1e-6) {
+ GLfloat invd = 1.0F / d;
+ SELF_SCALE_SCALAR_3V(VP, invd);
+ }
+
+ attenuation = 1.0F / (light->ConstantAttenuation + d *
+ (light->LinearAttenuation + d *
+ light->QuadraticAttenuation));
+
+ /* spotlight attenuation */
+ if (light->_Flags & LIGHT_SPOT) {
+ GLfloat PV_dot_dir = - DOT3(VP, light->_NormSpotDirection);
+
+ if (PV_dot_dir<light->_CosCutoff) {
+ continue; /* this light makes no contribution */
+ }
+ else {
+ GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1);
+ GLint k = (GLint) x;
+ GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0]
+ + (x-k)*light->_SpotExpTable[k][1]);
+ attenuation *= spot;
+ }
+ }
+ }
+
+ if (attenuation < 1e-3)
+ continue; /* this light makes no contribution */
+
+ /* Compute dot product or normal and vector from V to light pos */
+ n_dot_VP = DOT3( normal, VP );
+
+ /* which side are we lighting? */
+ if (n_dot_VP < 0.0F) {
+ ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]);
+#if IDX & LIGHT_TWOSIDE
+ side = 1;
+ correction = -1;
+ n_dot_VP = -n_dot_VP;
+#else
+ continue;
+#endif
+ }
+ else {
+#if IDX & LIGHT_TWOSIDE
+ ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]);
+#endif
+ side = 0;
+ correction = 1;
+ }
+
+ COPY_3V(contrib, light->_MatAmbient[side]);
+
+ /* diffuse term */
+ ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]);
+
+ /* specular term - cannibalize VP... */
+ {
+ if (ctx->Light.Model.LocalViewer) {
+ GLfloat v[3];
+ COPY_3V(v, vertex);
+ NORMALIZE_3FV(v);
+ SUB_3V(VP, VP, v); /* h = VP + VPe */
+ h = VP;
+ NORMALIZE_3FV(h);
+ }
+ else if (light->_Flags & LIGHT_POSITIONAL) {
+ h = VP;
+ ACC_3V(h, ctx->_EyeZDir);
+ NORMALIZE_3FV(h);
+ }
+ else {
+ h = light->_h_inf_norm;
+ }
+
+ n_dot_h = correction * DOT3(normal, h);
+
+ if (n_dot_h > 0.0F)
+ {
+ GLfloat spec_coef;
+ struct gl_shine_tab *tab = ctx->_ShineTable[side];
+
+ GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef );
+
+ ACC_SCALE_SCALAR_3V( contrib, spec_coef,
+ light->_MatSpecular[side]);
+ }
+ }
+
+ ACC_SCALE_SCALAR_3V( sum[side], attenuation, contrib );
+ }
+
+ COPY_3V( Fcolor[j], sum[0] );
+ Fcolor[j][3] = sumA[0];
+
+#if IDX & LIGHT_TWOSIDE
+ COPY_3V( Bcolor[j], sum[1] );
+ Bcolor[j][3] = sumA[1];
+#endif
+ }
+}
+
+
+
+
+/* As below, but with just a single light.
+ */
+static void TAG(light_fast_rgba_single)( struct gl_context *ctx,
+ struct vertex_buffer *VB,
+ struct tnl_pipeline_stage *stage,
+ GLvector4f *input )
+
+{
+ struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
+ const GLuint nstride = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride;
+ const GLfloat *normal = (GLfloat *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data;
+ GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data;
+#if IDX & LIGHT_TWOSIDE
+ GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data;
+#endif
+ const struct gl_light *light = ctx->Light.EnabledList.next;
+ GLuint j = 0;
+ GLfloat base[2][4];
+#if IDX & LIGHT_MATERIAL
+ const GLuint nr = VB->Count;
+#else
+ const GLuint nr = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->count;
+#endif
+
+#ifdef TRACE
+ fprintf(stderr, "%s\n", __FUNCTION__ );
+#endif
+
+ (void) input; /* doesn't refer to Eye or Obj */
+
+ VB->AttribPtr[_TNL_ATTRIB_COLOR0] = &store->LitColor[0];
+#if IDX & LIGHT_TWOSIDE
+ VB->BackfaceColorPtr = &store->LitColor[1];
+#endif
+
+ if (nr > 1) {
+ store->LitColor[0].stride = 16;
+ store->LitColor[1].stride = 16;
+ }
+ else {
+ store->LitColor[0].stride = 0;
+ store->LitColor[1].stride = 0;
+ }
+
+ for (j = 0; j < nr; j++, STRIDE_F(normal,nstride)) {
+
+ GLfloat n_dot_VP;
+
+#if IDX & LIGHT_MATERIAL
+ update_materials( ctx, store );
+#endif
+
+ /* No attenuation, so incoporate _MatAmbient into base color.
+ */
+#if !(IDX & LIGHT_MATERIAL)
+ if ( j == 0 )
+#endif
+ {
+ 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]);
+ base[1][3] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
+#endif
+ }
+
+ 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]);
+ }
+ COPY_3V(Bcolor[j], sum );
+ Bcolor[j][3] = base[1][3];
+#endif
+ 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]);
+
+ }
+ COPY_3V(Fcolor[j], sum );
+ Fcolor[j][3] = base[0][3];
+#if IDX & LIGHT_TWOSIDE
+ COPY_4FV(Bcolor[j], base[1]);
+#endif
+ }
+ }
+}
+
+
+/* Light infinite lights
+ */
+static void TAG(light_fast_rgba)( struct gl_context *ctx,
+ struct vertex_buffer *VB,
+ struct tnl_pipeline_stage *stage,
+ GLvector4f *input )
+{
+ struct light_stage_data *store = LIGHT_STAGE_DATA(stage);
+ GLfloat sumA[2];
+ const GLuint nstride = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->stride;
+ const GLfloat *normal = (GLfloat *)VB->AttribPtr[_TNL_ATTRIB_NORMAL]->data;
+ GLfloat (*Fcolor)[4] = (GLfloat (*)[4]) store->LitColor[0].data;
+#if IDX & LIGHT_TWOSIDE
+ GLfloat (*Bcolor)[4] = (GLfloat (*)[4]) store->LitColor[1].data;
+#endif
+ GLuint j = 0;
+#if IDX & LIGHT_MATERIAL
+ const GLuint nr = VB->Count;
+#else
+ const GLuint nr = VB->AttribPtr[_TNL_ATTRIB_NORMAL]->count;
+#endif
+ const struct gl_light *light;
+
+#ifdef TRACE
+ fprintf(stderr, "%s %d\n", __FUNCTION__, nr );
+#endif
+
+ (void) input;
+
+ sumA[0] = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_DIFFUSE][3];
+ sumA[1] = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_DIFFUSE][3];
+
+ VB->AttribPtr[_TNL_ATTRIB_COLOR0] = &store->LitColor[0];
+#if IDX & LIGHT_TWOSIDE
+ VB->BackfaceColorPtr = &store->LitColor[1];
+#endif
+
+ if (nr > 1) {
+ store->LitColor[0].stride = 16;
+ store->LitColor[1].stride = 16;
+ }
+ else {
+ store->LitColor[0].stride = 0;
+ store->LitColor[1].stride = 0;
+ }
+
+ for (j = 0; j < nr; j++, STRIDE_F(normal,nstride)) {
+
+ GLfloat sum[2][3];
+
+#if IDX & LIGHT_MATERIAL
+ update_materials( ctx, store );
+
+ 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];
+#endif
+#endif
+
+
+ COPY_3V(sum[0], ctx->Light._BaseColor[0]);
+#if IDX & LIGHT_TWOSIDE
+ COPY_3V(sum[1], ctx->Light._BaseColor[1]);
+#endif
+
+ 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]);
+#endif
+
+ 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]);
+ }
+ }
+#if IDX & LIGHT_TWOSIDE
+ else {
+ 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]);
+ }
+ }
+#endif
+ }
+
+ COPY_3V( Fcolor[j], sum[0] );
+ Fcolor[j][3] = sumA[0];
+
+#if IDX & LIGHT_TWOSIDE
+ COPY_3V( Bcolor[j], sum[1] );
+ Bcolor[j][3] = sumA[1];
+#endif
+ }
+}
+
+
+
+
+static void TAG(init_light_tab)( void )
+{
+ _tnl_light_tab[IDX] = TAG(light_rgba);
+ _tnl_light_fast_tab[IDX] = TAG(light_fast_rgba);
+ _tnl_light_fast_single_tab[IDX] = TAG(light_fast_rgba_single);
+ _tnl_light_spec_tab[IDX] = TAG(light_rgba_spec);
+}
+
+
+#undef TAG
+#undef IDX
+#undef NR_SIDES
diff --git a/mesalib/src/mesa/tnl/t_vb_normals.c b/mesalib/src/mesa/tnl/t_vb_normals.c index c2aa65567..94e8d0ab5 100644 --- a/mesalib/src/mesa/tnl/t_vb_normals.c +++ b/mesalib/src/mesa/tnl/t_vb_normals.c @@ -1,187 +1,187 @@ -/* - * Mesa 3-D graphics library - * Version: 6.5 - * - * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Keith Whitwell <keith@tungstengraphics.com> - */ - - -#include "main/glheader.h" -#include "main/colormac.h" -#include "main/macros.h" -#include "main/imports.h" -#include "main/mtypes.h" - -#include "math/m_xform.h" - -#include "t_context.h" -#include "t_pipeline.h" - - -struct normal_stage_data { - normal_func NormalTransform; - GLvector4f normal; -}; - -#define NORMAL_STAGE_DATA(stage) ((struct normal_stage_data *)stage->privatePtr) - - -static GLboolean -run_normal_stage(GLcontext *ctx, struct tnl_pipeline_stage *stage) -{ - struct normal_stage_data *store = NORMAL_STAGE_DATA(stage); - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; - const GLfloat *lengths; - - if (!store->NormalTransform) - return GL_TRUE; - - /* We can only use the display list's saved normal lengths if we've - * got a transformation matrix with uniform scaling. - */ - if (_math_matrix_is_general_scale(ctx->ModelviewMatrixStack.Top)) - lengths = NULL; - else - lengths = VB->NormalLengthPtr; - - store->NormalTransform( ctx->ModelviewMatrixStack.Top, - ctx->_ModelViewInvScale, - VB->AttribPtr[_TNL_ATTRIB_NORMAL], /* input normals */ - lengths, - &store->normal ); /* resulting normals */ - - if (VB->AttribPtr[_TNL_ATTRIB_NORMAL]->count > 1) { - store->normal.stride = 4 * sizeof(GLfloat); - } - else { - store->normal.stride = 0; - } - - VB->AttribPtr[_TNL_ATTRIB_NORMAL] = &store->normal; - - VB->NormalLengthPtr = NULL; /* no longer valid */ - return GL_TRUE; -} - - -/** - * Examine current GL state and set the store->NormalTransform pointer - * to point to the appropriate normal transformation routine. - */ -static void -validate_normal_stage(GLcontext *ctx, struct tnl_pipeline_stage *stage) -{ - struct normal_stage_data *store = NORMAL_STAGE_DATA(stage); - - if (ctx->VertexProgram._Current || - (!ctx->Light.Enabled && - !(ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS))) { - store->NormalTransform = NULL; - return; - } - - if (ctx->_NeedEyeCoords) { - /* Eye coordinates are needed, for whatever reasons. - * Do lighting in eye coordinates, as the GL spec says. - */ - GLuint transform = NORM_TRANSFORM_NO_ROT; - - if (_math_matrix_has_rotation(ctx->ModelviewMatrixStack.Top)) { - /* need to do full (3x3) matrix transform */ - transform = NORM_TRANSFORM; - } - - if (ctx->Transform.Normalize) { - store->NormalTransform = _mesa_normal_tab[transform | NORM_NORMALIZE]; - } - else if (ctx->Transform.RescaleNormals && - ctx->_ModelViewInvScale != 1.0) { - store->NormalTransform = _mesa_normal_tab[transform | NORM_RESCALE]; - } - else { - store->NormalTransform = _mesa_normal_tab[transform]; - } - } - else { - /* We don't need eye coordinates. - * Do lighting in object coordinates. Thus, we don't need to fully - * transform normal vectors (just leave them in object coordinates) - * but we still need to do normalization/rescaling if enabled. - */ - if (ctx->Transform.Normalize) { - store->NormalTransform = _mesa_normal_tab[NORM_NORMALIZE]; - } - else if (!ctx->Transform.RescaleNormals && - ctx->_ModelViewInvScale != 1.0) { - store->NormalTransform = _mesa_normal_tab[NORM_RESCALE]; - } - else { - store->NormalTransform = NULL; - } - } -} - - -/** - * Allocate stage's private data (storage for transformed normals). - */ -static GLboolean -alloc_normal_data(GLcontext *ctx, struct tnl_pipeline_stage *stage) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct normal_stage_data *store; - - stage->privatePtr = malloc(sizeof(*store)); - store = NORMAL_STAGE_DATA(stage); - if (!store) - return GL_FALSE; - - _mesa_vector4f_alloc( &store->normal, 0, tnl->vb.Size, 32 ); - return GL_TRUE; -} - - -/** - * Free stage's private data. - */ -static void -free_normal_data(struct tnl_pipeline_stage *stage) -{ - struct normal_stage_data *store = NORMAL_STAGE_DATA(stage); - if (store) { - _mesa_vector4f_free( &store->normal ); - free( store ); - stage->privatePtr = NULL; - } -} - - -const struct tnl_pipeline_stage _tnl_normal_transform_stage = -{ - "normal transform", /* name */ - NULL, /* privatePtr */ - alloc_normal_data, /* create */ - free_normal_data, /* destroy */ - validate_normal_stage, /* validate */ - run_normal_stage /* run */ -}; +/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "main/glheader.h"
+#include "main/colormac.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+
+#include "math/m_xform.h"
+
+#include "t_context.h"
+#include "t_pipeline.h"
+
+
+struct normal_stage_data {
+ normal_func NormalTransform;
+ GLvector4f normal;
+};
+
+#define NORMAL_STAGE_DATA(stage) ((struct normal_stage_data *)stage->privatePtr)
+
+
+static GLboolean
+run_normal_stage(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
+{
+ struct normal_stage_data *store = NORMAL_STAGE_DATA(stage);
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ const GLfloat *lengths;
+
+ if (!store->NormalTransform)
+ return GL_TRUE;
+
+ /* We can only use the display list's saved normal lengths if we've
+ * got a transformation matrix with uniform scaling.
+ */
+ if (_math_matrix_is_general_scale(ctx->ModelviewMatrixStack.Top))
+ lengths = NULL;
+ else
+ lengths = VB->NormalLengthPtr;
+
+ store->NormalTransform( ctx->ModelviewMatrixStack.Top,
+ ctx->_ModelViewInvScale,
+ VB->AttribPtr[_TNL_ATTRIB_NORMAL], /* input normals */
+ lengths,
+ &store->normal ); /* resulting normals */
+
+ if (VB->AttribPtr[_TNL_ATTRIB_NORMAL]->count > 1) {
+ store->normal.stride = 4 * sizeof(GLfloat);
+ }
+ else {
+ store->normal.stride = 0;
+ }
+
+ VB->AttribPtr[_TNL_ATTRIB_NORMAL] = &store->normal;
+
+ VB->NormalLengthPtr = NULL; /* no longer valid */
+ return GL_TRUE;
+}
+
+
+/**
+ * Examine current GL state and set the store->NormalTransform pointer
+ * to point to the appropriate normal transformation routine.
+ */
+static void
+validate_normal_stage(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
+{
+ struct normal_stage_data *store = NORMAL_STAGE_DATA(stage);
+
+ if (ctx->VertexProgram._Current ||
+ (!ctx->Light.Enabled &&
+ !(ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS))) {
+ store->NormalTransform = NULL;
+ return;
+ }
+
+ if (ctx->_NeedEyeCoords) {
+ /* Eye coordinates are needed, for whatever reasons.
+ * Do lighting in eye coordinates, as the GL spec says.
+ */
+ GLuint transform = NORM_TRANSFORM_NO_ROT;
+
+ if (_math_matrix_has_rotation(ctx->ModelviewMatrixStack.Top)) {
+ /* need to do full (3x3) matrix transform */
+ transform = NORM_TRANSFORM;
+ }
+
+ if (ctx->Transform.Normalize) {
+ store->NormalTransform = _mesa_normal_tab[transform | NORM_NORMALIZE];
+ }
+ else if (ctx->Transform.RescaleNormals &&
+ ctx->_ModelViewInvScale != 1.0) {
+ store->NormalTransform = _mesa_normal_tab[transform | NORM_RESCALE];
+ }
+ else {
+ store->NormalTransform = _mesa_normal_tab[transform];
+ }
+ }
+ else {
+ /* We don't need eye coordinates.
+ * Do lighting in object coordinates. Thus, we don't need to fully
+ * transform normal vectors (just leave them in object coordinates)
+ * but we still need to do normalization/rescaling if enabled.
+ */
+ if (ctx->Transform.Normalize) {
+ store->NormalTransform = _mesa_normal_tab[NORM_NORMALIZE];
+ }
+ else if (!ctx->Transform.RescaleNormals &&
+ ctx->_ModelViewInvScale != 1.0) {
+ store->NormalTransform = _mesa_normal_tab[NORM_RESCALE];
+ }
+ else {
+ store->NormalTransform = NULL;
+ }
+ }
+}
+
+
+/**
+ * Allocate stage's private data (storage for transformed normals).
+ */
+static GLboolean
+alloc_normal_data(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct normal_stage_data *store;
+
+ stage->privatePtr = malloc(sizeof(*store));
+ store = NORMAL_STAGE_DATA(stage);
+ if (!store)
+ return GL_FALSE;
+
+ _mesa_vector4f_alloc( &store->normal, 0, tnl->vb.Size, 32 );
+ return GL_TRUE;
+}
+
+
+/**
+ * Free stage's private data.
+ */
+static void
+free_normal_data(struct tnl_pipeline_stage *stage)
+{
+ struct normal_stage_data *store = NORMAL_STAGE_DATA(stage);
+ if (store) {
+ _mesa_vector4f_free( &store->normal );
+ free( store );
+ stage->privatePtr = NULL;
+ }
+}
+
+
+const struct tnl_pipeline_stage _tnl_normal_transform_stage =
+{
+ "normal transform", /* name */
+ NULL, /* privatePtr */
+ alloc_normal_data, /* create */
+ free_normal_data, /* destroy */
+ validate_normal_stage, /* validate */
+ run_normal_stage /* run */
+};
diff --git a/mesalib/src/mesa/tnl/t_vb_points.c b/mesalib/src/mesa/tnl/t_vb_points.c index 20634c80d..1bf961a6d 100644 --- a/mesalib/src/mesa/tnl/t_vb_points.c +++ b/mesalib/src/mesa/tnl/t_vb_points.c @@ -1,114 +1,114 @@ -/* - * Mesa 3-D graphics library - * Version: 7.0 - * - * Copyright (C) 1999-2007 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: - * Brian Paul - */ - -#include "main/glheader.h" -#include "main/mtypes.h" -#include "main/dd.h" -#include "main/imports.h" -#include "t_context.h" -#include "t_pipeline.h" - - -struct point_stage_data { - GLvector4f PointSize; -}; - -#define POINT_STAGE_DATA(stage) ((struct point_stage_data *)stage->privatePtr) - - -/** - * Compute point size for each vertex from the vertex eye-space Z - * coordinate and the point size attenuation factors. - * Only done when point size attenuation is enabled and vertex program is - * disabled. - */ -static GLboolean -run_point_stage(GLcontext *ctx, struct tnl_pipeline_stage *stage) -{ - if (ctx->Point._Attenuated && !ctx->VertexProgram._Current) { - struct point_stage_data *store = POINT_STAGE_DATA(stage); - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; - const GLfloat *eyeCoord = (GLfloat *) VB->EyePtr->data + 2; - const GLint eyeCoordStride = VB->EyePtr->stride / sizeof(GLfloat); - const GLfloat p0 = ctx->Point.Params[0]; - const GLfloat p1 = ctx->Point.Params[1]; - const GLfloat p2 = ctx->Point.Params[2]; - const GLfloat pointSize = ctx->Point.Size; - GLfloat (*size)[4] = store->PointSize.data; - GLuint i; - - for (i = 0; i < VB->Count; i++) { - const GLfloat dist = FABSF(*eyeCoord); - const GLfloat q = p0 + dist * (p1 + dist * p2); - const GLfloat atten = (q != 0.0F) ? SQRTF(1.0F / q) : 1.0F; - size[i][0] = pointSize * atten; /* clamping done in rasterization */ - eyeCoord += eyeCoordStride; - } - - VB->AttribPtr[_TNL_ATTRIB_POINTSIZE] = &store->PointSize; - } - - return GL_TRUE; -} - - -static GLboolean -alloc_point_data(GLcontext *ctx, struct tnl_pipeline_stage *stage) -{ - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; - struct point_stage_data *store; - stage->privatePtr = malloc(sizeof(*store)); - store = POINT_STAGE_DATA(stage); - if (!store) - return GL_FALSE; - - _mesa_vector4f_alloc( &store->PointSize, 0, VB->Size, 32 ); - return GL_TRUE; -} - - -static void -free_point_data(struct tnl_pipeline_stage *stage) -{ - struct point_stage_data *store = POINT_STAGE_DATA(stage); - if (store) { - _mesa_vector4f_free( &store->PointSize ); - free( store ); - stage->privatePtr = NULL; - } -} - - -const struct tnl_pipeline_stage _tnl_point_attenuation_stage = -{ - "point size attenuation", /* name */ - NULL, /* stage private data */ - alloc_point_data, /* alloc data */ - free_point_data, /* destructor */ - NULL, - run_point_stage /* run */ -}; +/*
+ * Mesa 3-D graphics library
+ * Version: 7.0
+ *
+ * Copyright (C) 1999-2007 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:
+ * Brian Paul
+ */
+
+#include "main/glheader.h"
+#include "main/mtypes.h"
+#include "main/dd.h"
+#include "main/imports.h"
+#include "t_context.h"
+#include "t_pipeline.h"
+
+
+struct point_stage_data {
+ GLvector4f PointSize;
+};
+
+#define POINT_STAGE_DATA(stage) ((struct point_stage_data *)stage->privatePtr)
+
+
+/**
+ * Compute point size for each vertex from the vertex eye-space Z
+ * coordinate and the point size attenuation factors.
+ * Only done when point size attenuation is enabled and vertex program is
+ * disabled.
+ */
+static GLboolean
+run_point_stage(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
+{
+ if (ctx->Point._Attenuated && !ctx->VertexProgram._Current) {
+ struct point_stage_data *store = POINT_STAGE_DATA(stage);
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ const GLfloat *eyeCoord = (GLfloat *) VB->EyePtr->data + 2;
+ const GLint eyeCoordStride = VB->EyePtr->stride / sizeof(GLfloat);
+ const GLfloat p0 = ctx->Point.Params[0];
+ const GLfloat p1 = ctx->Point.Params[1];
+ const GLfloat p2 = ctx->Point.Params[2];
+ const GLfloat pointSize = ctx->Point.Size;
+ GLfloat (*size)[4] = store->PointSize.data;
+ GLuint i;
+
+ for (i = 0; i < VB->Count; i++) {
+ const GLfloat dist = FABSF(*eyeCoord);
+ const GLfloat q = p0 + dist * (p1 + dist * p2);
+ const GLfloat atten = (q != 0.0F) ? SQRTF(1.0F / q) : 1.0F;
+ size[i][0] = pointSize * atten; /* clamping done in rasterization */
+ eyeCoord += eyeCoordStride;
+ }
+
+ VB->AttribPtr[_TNL_ATTRIB_POINTSIZE] = &store->PointSize;
+ }
+
+ return GL_TRUE;
+}
+
+
+static GLboolean
+alloc_point_data(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ struct point_stage_data *store;
+ stage->privatePtr = malloc(sizeof(*store));
+ store = POINT_STAGE_DATA(stage);
+ if (!store)
+ return GL_FALSE;
+
+ _mesa_vector4f_alloc( &store->PointSize, 0, VB->Size, 32 );
+ return GL_TRUE;
+}
+
+
+static void
+free_point_data(struct tnl_pipeline_stage *stage)
+{
+ struct point_stage_data *store = POINT_STAGE_DATA(stage);
+ if (store) {
+ _mesa_vector4f_free( &store->PointSize );
+ free( store );
+ stage->privatePtr = NULL;
+ }
+}
+
+
+const struct tnl_pipeline_stage _tnl_point_attenuation_stage =
+{
+ "point size attenuation", /* name */
+ NULL, /* stage private data */
+ alloc_point_data, /* alloc data */
+ free_point_data, /* destructor */
+ NULL,
+ run_point_stage /* run */
+};
diff --git a/mesalib/src/mesa/tnl/t_vb_program.c b/mesalib/src/mesa/tnl/t_vb_program.c index f3a338ef1..ea5717a7a 100644 --- a/mesalib/src/mesa/tnl/t_vb_program.c +++ b/mesalib/src/mesa/tnl/t_vb_program.c @@ -1,569 +1,571 @@ -/* - * Mesa 3-D graphics library - * Version: 7.6 - * - * Copyright (C) 1999-2008 Brian Paul All Rights Reserved. - * Copyright (C) 2009 VMware, Inc. 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_vb_program.c - * \brief Pipeline stage for executing vertex programs. - * \author Brian Paul, Keith Whitwell - */ - - -#include "main/glheader.h" -#include "main/colormac.h" -#include "main/macros.h" -#include "main/imports.h" -#include "math/m_xform.h" -#include "program/prog_instruction.h" -#include "program/prog_statevars.h" -#include "program/prog_execute.h" -#include "swrast/s_context.h" - -#include "tnl/tnl.h" -#include "tnl/t_context.h" -#include "tnl/t_pipeline.h" - - -#ifdef NAN_CHECK -/** Check for NaNs and very large values */ -static INLINE void -check_float(float x) -{ - assert(!IS_INF_OR_NAN(x)); - assert(1.0e-15 <= x && x <= 1.0e15); -} -#endif - - -/*! - * Private storage for the vertex program pipeline stage. - */ -struct vp_stage_data { - /** The results of running the vertex program go into these arrays. */ - GLvector4f results[VERT_RESULT_MAX]; - - GLvector4f ndcCoords; /**< normalized device coords */ - GLubyte *clipmask; /**< clip flags */ - GLubyte ormask, andmask; /**< for clipping */ -}; - - -#define VP_STAGE_DATA(stage) ((struct vp_stage_data *)(stage->privatePtr)) - - -static void -userclip( GLcontext *ctx, - GLvector4f *clip, - GLubyte *clipmask, - GLubyte *clipormask, - GLubyte *clipandmask ) -{ - GLuint p; - - for (p = 0; p < ctx->Const.MaxClipPlanes; p++) { - if (ctx->Transform.ClipPlanesEnabled & (1 << p)) { - GLuint nr, i; - const GLfloat a = ctx->Transform._ClipUserPlane[p][0]; - const GLfloat b = ctx->Transform._ClipUserPlane[p][1]; - const GLfloat c = ctx->Transform._ClipUserPlane[p][2]; - const GLfloat d = ctx->Transform._ClipUserPlane[p][3]; - GLfloat *coord = (GLfloat *)clip->data; - GLuint stride = clip->stride; - GLuint count = clip->count; - - for (nr = 0, i = 0 ; i < count ; i++) { - GLfloat dp = (coord[0] * a + - coord[1] * b + - coord[2] * c + - coord[3] * d); - - if (dp < 0) { - nr++; - clipmask[i] |= CLIP_USER_BIT; - } - - STRIDE_F(coord, stride); - } - - if (nr > 0) { - *clipormask |= CLIP_USER_BIT; - if (nr == count) { - *clipandmask |= CLIP_USER_BIT; - return; - } - } - } - } -} - - -static GLboolean -do_ndc_cliptest(GLcontext *ctx, struct vp_stage_data *store) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - /* Cliptest and perspective divide. Clip functions must clear - * the clipmask. - */ - store->ormask = 0; - store->andmask = CLIP_FRUSTUM_BITS; - - tnl_clip_prepare(ctx); - - if (tnl->NeedNdcCoords) { - VB->NdcPtr = - _mesa_clip_tab[VB->ClipPtr->size]( VB->ClipPtr, - &store->ndcCoords, - store->clipmask, - &store->ormask, - &store->andmask, - !ctx->Transform.DepthClamp ); - } - else { - VB->NdcPtr = NULL; - _mesa_clip_np_tab[VB->ClipPtr->size]( VB->ClipPtr, - NULL, - store->clipmask, - &store->ormask, - &store->andmask, - !ctx->Transform.DepthClamp ); - } - - if (store->andmask) { - /* All vertices are outside the frustum */ - return GL_FALSE; - } - - /* Test userclip planes. This contributes to VB->ClipMask. - */ - /** XXX NEW_SLANG _Enabled ??? */ - if (ctx->Transform.ClipPlanesEnabled && (!ctx->VertexProgram._Enabled || - ctx->VertexProgram.Current->IsPositionInvariant)) { - userclip( ctx, - VB->ClipPtr, - store->clipmask, - &store->ormask, - &store->andmask ); - - if (store->andmask) { - return GL_FALSE; - } - } - - VB->ClipAndMask = store->andmask; - VB->ClipOrMask = store->ormask; - VB->ClipMask = store->clipmask; - - return GL_TRUE; -} - - -/** - * XXX the texture sampling code in this module is a bit of a hack. - * The texture sampling code is in swrast, though it doesn't have any - * real dependencies on the rest of swrast. It should probably be - * moved into main/ someday. - */ -static void -vp_fetch_texel(GLcontext *ctx, const GLfloat texcoord[4], GLfloat lambda, - GLuint unit, GLfloat color[4]) -{ - SWcontext *swrast = SWRAST_CONTEXT(ctx); - - /* XXX use a float-valued TextureSample routine here!!! */ - swrast->TextureSample[unit](ctx, ctx->Texture.Unit[unit]._Current, - 1, (const GLfloat (*)[4]) texcoord, - &lambda, (GLfloat (*)[4]) color); -} - - -/** - * Called via ctx->Driver.ProgramStringNotify() after a new vertex program - * string has been parsed. - */ -GLboolean -_tnl_program_string(GLcontext *ctx, GLenum target, struct gl_program *program) -{ - /* No-op. - * If we had derived anything from the program that was private to this - * stage we'd recompute/validate it here. - */ - return GL_TRUE; -} - - -/** - * Initialize virtual machine state prior to executing vertex program. - */ -static void -init_machine(GLcontext *ctx, struct gl_program_machine *machine) -{ - /* Input registers get initialized from the current vertex attribs */ - memcpy(machine->VertAttribs, ctx->Current.Attrib, - MAX_VERTEX_GENERIC_ATTRIBS * 4 * sizeof(GLfloat)); - - if (ctx->VertexProgram._Current->IsNVProgram) { - GLuint i; - /* Output/result regs are initialized to [0,0,0,1] */ - for (i = 0; i < MAX_NV_VERTEX_PROGRAM_OUTPUTS; i++) { - ASSIGN_4V(machine->Outputs[i], 0.0F, 0.0F, 0.0F, 1.0F); - } - /* Temp regs are initialized to [0,0,0,0] */ - for (i = 0; i < MAX_NV_VERTEX_PROGRAM_TEMPS; i++) { - ASSIGN_4V(machine->Temporaries[i], 0.0F, 0.0F, 0.0F, 0.0F); - } - for (i = 0; i < MAX_VERTEX_PROGRAM_ADDRESS_REGS; i++) { - ASSIGN_4V(machine->AddressReg[i], 0, 0, 0, 0); - } - } - - machine->NumDeriv = 0; - - /* init condition codes */ - machine->CondCodes[0] = COND_EQ; - machine->CondCodes[1] = COND_EQ; - machine->CondCodes[2] = COND_EQ; - machine->CondCodes[3] = COND_EQ; - - /* init call stack */ - machine->StackDepth = 0; - - machine->FetchTexelLod = vp_fetch_texel; - machine->FetchTexelDeriv = NULL; /* not used by vertex programs */ - - machine->Samplers = ctx->VertexProgram._Current->Base.SamplerUnits; -} - - -/** - * Map the texture images which the vertex program will access (if any). - */ -static void -map_textures(GLcontext *ctx, const struct gl_vertex_program *vp) -{ - GLuint u; - - if (!ctx->Driver.MapTexture) - return; - - for (u = 0; u < ctx->Const.MaxVertexTextureImageUnits; u++) { - if (vp->Base.TexturesUsed[u]) { - /* Note: _Current *should* correspond to the target indicated - * in TexturesUsed[u]. - */ - ctx->Driver.MapTexture(ctx, ctx->Texture.Unit[u]._Current); - } - } -} - - -/** - * Unmap the texture images which were used by the vertex program (if any). - */ -static void -unmap_textures(GLcontext *ctx, const struct gl_vertex_program *vp) -{ - GLuint u; - - if (!ctx->Driver.MapTexture) - return; - - for (u = 0; u < ctx->Const.MaxVertexTextureImageUnits; u++) { - if (vp->Base.TexturesUsed[u]) { - /* Note: _Current *should* correspond to the target indicated - * in TexturesUsed[u]. - */ - ctx->Driver.UnmapTexture(ctx, ctx->Texture.Unit[u]._Current); - } - } -} - - -/** - * This function executes vertex programs - */ -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); - struct vertex_buffer *VB = &tnl->vb; - struct gl_vertex_program *program = ctx->VertexProgram._Current; - struct gl_program_machine machine; - GLuint outputs[VERT_RESULT_MAX], numOutputs; - GLuint i, j; - - if (!program) - return GL_TRUE; - - if (program->IsNVProgram) { - _mesa_load_tracked_matrices(ctx); - } - else { - /* ARB program or vertex shader */ - _mesa_load_state_parameters(ctx, program->Base.Parameters); - } - - /* make list of outputs to save some time below */ - numOutputs = 0; - for (i = 0; i < VERT_RESULT_MAX; i++) { - if (program->Base.OutputsWritten & BITFIELD64_BIT(i)) { - outputs[numOutputs++] = i; - } - } - - map_textures(ctx, program); - - for (i = 0; i < VB->Count; i++) { - GLuint attr; - - init_machine(ctx, &machine); - -#if 0 - printf("Input %d: %f, %f, %f, %f\n", i, - VB->AttribPtr[0]->data[i][0], - VB->AttribPtr[0]->data[i][1], - VB->AttribPtr[0]->data[i][2], - VB->AttribPtr[0]->data[i][3]); - printf(" color: %f, %f, %f, %f\n", - VB->AttribPtr[3]->data[i][0], - VB->AttribPtr[3]->data[i][1], - VB->AttribPtr[3]->data[i][2], - VB->AttribPtr[3]->data[i][3]); - printf(" normal: %f, %f, %f, %f\n", - VB->AttribPtr[2]->data[i][0], - VB->AttribPtr[2]->data[i][1], - VB->AttribPtr[2]->data[i][2], - VB->AttribPtr[2]->data[i][3]); -#endif - - /* the vertex array case */ - for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { - if (program->Base.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); -#ifdef NAN_CHECK - check_float(data[0]); - check_float(data[1]); - check_float(data[2]); - check_float(data[3]); -#endif - COPY_CLEAN_4V(machine.VertAttribs[attr], size, data); - } - } - - /* execute the program */ - _mesa_execute_program(ctx, &program->Base, &machine); - - /* copy the output registers into the VB->attribs arrays */ - for (j = 0; j < numOutputs; j++) { - const GLuint attr = outputs[j]; -#ifdef NAN_CHECK - check_float(machine.Outputs[attr][0]); - check_float(machine.Outputs[attr][1]); - check_float(machine.Outputs[attr][2]); - check_float(machine.Outputs[attr][3]); -#endif - COPY_4V(store->results[attr].data[i], machine.Outputs[attr]); - } - - /* FOGC is a special case. Fragment shader expects (f,0,0,1) */ - if (program->Base.OutputsWritten & BITFIELD64_BIT(VERT_RESULT_FOGC)) { - store->results[VERT_RESULT_FOGC].data[i][1] = 0.0; - store->results[VERT_RESULT_FOGC].data[i][2] = 0.0; - store->results[VERT_RESULT_FOGC].data[i][3] = 1.0; - } -#ifdef NAN_CHECK - ASSERT(machine.Outputs[0][3] != 0.0F); -#endif -#if 0 - printf("HPOS: %f %f %f %f\n", - machine.Outputs[0][0], - machine.Outputs[0][1], - machine.Outputs[0][2], - machine.Outputs[0][3]); -#endif - } - - unmap_textures(ctx, program); - - /* Fixup fog and point size results if needed */ - if (program->IsNVProgram) { - if (ctx->Fog.Enabled && - (program->Base.OutputsWritten & BITFIELD64_BIT(VERT_RESULT_FOGC)) == 0) { - for (i = 0; i < VB->Count; i++) { - store->results[VERT_RESULT_FOGC].data[i][0] = 1.0; - } - } - - if (ctx->VertexProgram.PointSizeEnabled && - (program->Base.OutputsWritten & BITFIELD64_BIT(VERT_RESULT_PSIZ)) == 0) { - for (i = 0; i < VB->Count; i++) { - store->results[VERT_RESULT_PSIZ].data[i][0] = ctx->Point.Size; - } - } - } - - if (program->IsPositionInvariant) { - /* We need the exact same transform as in the fixed function path here - * to guarantee invariance, depending on compiler optimization flags - * results could be different otherwise. - */ - VB->ClipPtr = TransformRaw( &store->results[0], - &ctx->_ModelProjectMatrix, - VB->AttribPtr[0] ); - - /* Drivers expect this to be clean to element 4... - */ - switch (VB->ClipPtr->size) { - case 1: - /* impossible */ - case 2: - _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 2 ); - /* fall-through */ - case 3: - _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 3 ); - /* fall-through */ - case 4: - break; - } - } - else { - /* Setup the VB pointers so that the next pipeline stages get - * their data from the right place (the program output arrays). - */ - VB->ClipPtr = &store->results[VERT_RESULT_HPOS]; - VB->ClipPtr->size = 4; - VB->ClipPtr->count = VB->Count; - } - - VB->AttribPtr[VERT_ATTRIB_COLOR0] = &store->results[VERT_RESULT_COL0]; - VB->AttribPtr[VERT_ATTRIB_COLOR1] = &store->results[VERT_RESULT_COL1]; - VB->AttribPtr[VERT_ATTRIB_FOG] = &store->results[VERT_RESULT_FOGC]; - VB->AttribPtr[_TNL_ATTRIB_POINTSIZE] = &store->results[VERT_RESULT_PSIZ]; - VB->BackfaceColorPtr = &store->results[VERT_RESULT_BFC0]; - VB->BackfaceSecondaryColorPtr = &store->results[VERT_RESULT_BFC1]; - - for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) { - VB->AttribPtr[_TNL_ATTRIB_TEX0 + i] - = &store->results[VERT_RESULT_TEX0 + i]; - } - - for (i = 0; i < ctx->Const.MaxVarying; i++) { - if (program->Base.OutputsWritten & BITFIELD64_BIT(VERT_RESULT_VAR0 + i)) { - /* Note: varying results get put into the generic attributes */ - VB->AttribPtr[VERT_ATTRIB_GENERIC0+i] - = &store->results[VERT_RESULT_VAR0 + i]; - } - } - - - /* Perform NDC and cliptest operations: - */ - return do_ndc_cliptest(ctx, store); -} - - -/** - * Called the first time stage->run is called. In effect, don't - * allocate data until the first time the stage is run. - */ -static GLboolean -init_vp(GLcontext *ctx, struct tnl_pipeline_stage *stage) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &(tnl->vb); - struct vp_stage_data *store; - const GLuint size = VB->Size; - GLuint i; - - stage->privatePtr = MALLOC(sizeof(*store)); - store = VP_STAGE_DATA(stage); - if (!store) - return GL_FALSE; - - /* Allocate arrays of vertex output values */ - for (i = 0; i < VERT_RESULT_MAX; i++) { - _mesa_vector4f_alloc( &store->results[i], 0, size, 32 ); - store->results[i].size = 4; - } - - /* a few other misc allocations */ - _mesa_vector4f_alloc( &store->ndcCoords, 0, size, 32 ); - store->clipmask = (GLubyte *) _mesa_align_malloc(sizeof(GLubyte)*size, 32 ); - - return GL_TRUE; -} - - -/** - * Destructor for this pipeline stage. - */ -static void -dtr(struct tnl_pipeline_stage *stage) -{ - struct vp_stage_data *store = VP_STAGE_DATA(stage); - - if (store) { - GLuint i; - - /* free the vertex program result arrays */ - for (i = 0; i < VERT_RESULT_MAX; i++) - _mesa_vector4f_free( &store->results[i] ); - - /* free misc arrays */ - _mesa_vector4f_free( &store->ndcCoords ); - _mesa_align_free( store->clipmask ); - - FREE( store ); - stage->privatePtr = NULL; - } -} - - -static void -validate_vp_stage(GLcontext *ctx, struct tnl_pipeline_stage *stage) -{ - if (ctx->VertexProgram._Current) { - _swrast_update_texture_samplers(ctx); - } -} - - - -/** - * Public description of this pipeline stage. - */ -const struct tnl_pipeline_stage _tnl_vertex_program_stage = -{ - "vertex-program", - NULL, /* private_data */ - init_vp, /* create */ - dtr, /* destroy */ - validate_vp_stage, /* validate */ - run_vp /* run -- initially set to ctr */ -}; +/*
+ * Mesa 3-D graphics library
+ * Version: 7.6
+ *
+ * Copyright (C) 1999-2008 Brian Paul All Rights Reserved.
+ * Copyright (C) 2009 VMware, Inc. 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_vb_program.c
+ * \brief Pipeline stage for executing vertex programs.
+ * \author Brian Paul, Keith Whitwell
+ */
+
+
+#include "main/glheader.h"
+#include "main/colormac.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "math/m_xform.h"
+#include "program/prog_instruction.h"
+#include "program/prog_statevars.h"
+#include "program/prog_execute.h"
+#include "swrast/s_context.h"
+
+#include "tnl/tnl.h"
+#include "tnl/t_context.h"
+#include "tnl/t_pipeline.h"
+
+
+#ifdef NAN_CHECK
+/** Check for NaNs and very large values */
+static INLINE void
+check_float(float x)
+{
+ assert(!IS_INF_OR_NAN(x));
+ assert(1.0e-15 <= x && x <= 1.0e15);
+}
+#endif
+
+
+/*!
+ * Private storage for the vertex program pipeline stage.
+ */
+struct vp_stage_data {
+ /** The results of running the vertex program go into these arrays. */
+ GLvector4f results[VERT_RESULT_MAX];
+
+ GLvector4f ndcCoords; /**< normalized device coords */
+ GLubyte *clipmask; /**< clip flags */
+ GLubyte ormask, andmask; /**< for clipping */
+
+ struct gl_program_machine machine;
+};
+
+
+#define VP_STAGE_DATA(stage) ((struct vp_stage_data *)(stage->privatePtr))
+
+
+static void
+userclip( struct gl_context *ctx,
+ GLvector4f *clip,
+ GLubyte *clipmask,
+ GLubyte *clipormask,
+ GLubyte *clipandmask )
+{
+ GLuint p;
+
+ for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
+ if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
+ GLuint nr, i;
+ const GLfloat a = ctx->Transform._ClipUserPlane[p][0];
+ const GLfloat b = ctx->Transform._ClipUserPlane[p][1];
+ const GLfloat c = ctx->Transform._ClipUserPlane[p][2];
+ const GLfloat d = ctx->Transform._ClipUserPlane[p][3];
+ GLfloat *coord = (GLfloat *)clip->data;
+ GLuint stride = clip->stride;
+ GLuint count = clip->count;
+
+ for (nr = 0, i = 0 ; i < count ; i++) {
+ GLfloat dp = (coord[0] * a +
+ coord[1] * b +
+ coord[2] * c +
+ coord[3] * d);
+
+ if (dp < 0) {
+ nr++;
+ clipmask[i] |= CLIP_USER_BIT;
+ }
+
+ STRIDE_F(coord, stride);
+ }
+
+ if (nr > 0) {
+ *clipormask |= CLIP_USER_BIT;
+ if (nr == count) {
+ *clipandmask |= CLIP_USER_BIT;
+ return;
+ }
+ }
+ }
+ }
+}
+
+
+static GLboolean
+do_ndc_cliptest(struct gl_context *ctx, struct vp_stage_data *store)
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ /* Cliptest and perspective divide. Clip functions must clear
+ * the clipmask.
+ */
+ store->ormask = 0;
+ store->andmask = CLIP_FRUSTUM_BITS;
+
+ tnl_clip_prepare(ctx);
+
+ if (tnl->NeedNdcCoords) {
+ VB->NdcPtr =
+ _mesa_clip_tab[VB->ClipPtr->size]( VB->ClipPtr,
+ &store->ndcCoords,
+ store->clipmask,
+ &store->ormask,
+ &store->andmask,
+ !ctx->Transform.DepthClamp );
+ }
+ else {
+ VB->NdcPtr = NULL;
+ _mesa_clip_np_tab[VB->ClipPtr->size]( VB->ClipPtr,
+ NULL,
+ store->clipmask,
+ &store->ormask,
+ &store->andmask,
+ !ctx->Transform.DepthClamp );
+ }
+
+ if (store->andmask) {
+ /* All vertices are outside the frustum */
+ return GL_FALSE;
+ }
+
+ /* Test userclip planes. This contributes to VB->ClipMask.
+ */
+ /** XXX NEW_SLANG _Enabled ??? */
+ if (ctx->Transform.ClipPlanesEnabled && (!ctx->VertexProgram._Enabled ||
+ ctx->VertexProgram.Current->IsPositionInvariant)) {
+ userclip( ctx,
+ VB->ClipPtr,
+ store->clipmask,
+ &store->ormask,
+ &store->andmask );
+
+ if (store->andmask) {
+ return GL_FALSE;
+ }
+ }
+
+ VB->ClipAndMask = store->andmask;
+ VB->ClipOrMask = store->ormask;
+ VB->ClipMask = store->clipmask;
+
+ return GL_TRUE;
+}
+
+
+/**
+ * XXX the texture sampling code in this module is a bit of a hack.
+ * The texture sampling code is in swrast, though it doesn't have any
+ * real dependencies on the rest of swrast. It should probably be
+ * moved into main/ someday.
+ */
+static void
+vp_fetch_texel(struct gl_context *ctx, const GLfloat texcoord[4], GLfloat lambda,
+ GLuint unit, GLfloat color[4])
+{
+ SWcontext *swrast = SWRAST_CONTEXT(ctx);
+
+ /* XXX use a float-valued TextureSample routine here!!! */
+ swrast->TextureSample[unit](ctx, ctx->Texture.Unit[unit]._Current,
+ 1, (const GLfloat (*)[4]) texcoord,
+ &lambda, (GLfloat (*)[4]) color);
+}
+
+
+/**
+ * Called via ctx->Driver.ProgramStringNotify() after a new vertex program
+ * string has been parsed.
+ */
+GLboolean
+_tnl_program_string(struct gl_context *ctx, GLenum target, struct gl_program *program)
+{
+ /* No-op.
+ * If we had derived anything from the program that was private to this
+ * stage we'd recompute/validate it here.
+ */
+ return GL_TRUE;
+}
+
+
+/**
+ * Initialize virtual machine state prior to executing vertex program.
+ */
+static void
+init_machine(struct gl_context *ctx, struct gl_program_machine *machine)
+{
+ /* Input registers get initialized from the current vertex attribs */
+ memcpy(machine->VertAttribs, ctx->Current.Attrib,
+ MAX_VERTEX_GENERIC_ATTRIBS * 4 * sizeof(GLfloat));
+
+ if (ctx->VertexProgram._Current->IsNVProgram) {
+ GLuint i;
+ /* Output/result regs are initialized to [0,0,0,1] */
+ for (i = 0; i < MAX_NV_VERTEX_PROGRAM_OUTPUTS; i++) {
+ ASSIGN_4V(machine->Outputs[i], 0.0F, 0.0F, 0.0F, 1.0F);
+ }
+ /* Temp regs are initialized to [0,0,0,0] */
+ for (i = 0; i < MAX_NV_VERTEX_PROGRAM_TEMPS; i++) {
+ ASSIGN_4V(machine->Temporaries[i], 0.0F, 0.0F, 0.0F, 0.0F);
+ }
+ for (i = 0; i < MAX_VERTEX_PROGRAM_ADDRESS_REGS; i++) {
+ ASSIGN_4V(machine->AddressReg[i], 0, 0, 0, 0);
+ }
+ }
+
+ machine->NumDeriv = 0;
+
+ /* init condition codes */
+ machine->CondCodes[0] = COND_EQ;
+ machine->CondCodes[1] = COND_EQ;
+ machine->CondCodes[2] = COND_EQ;
+ machine->CondCodes[3] = COND_EQ;
+
+ /* init call stack */
+ machine->StackDepth = 0;
+
+ machine->FetchTexelLod = vp_fetch_texel;
+ machine->FetchTexelDeriv = NULL; /* not used by vertex programs */
+
+ machine->Samplers = ctx->VertexProgram._Current->Base.SamplerUnits;
+}
+
+
+/**
+ * Map the texture images which the vertex program will access (if any).
+ */
+static void
+map_textures(struct gl_context *ctx, const struct gl_vertex_program *vp)
+{
+ GLuint u;
+
+ if (!ctx->Driver.MapTexture)
+ return;
+
+ for (u = 0; u < ctx->Const.MaxVertexTextureImageUnits; u++) {
+ if (vp->Base.TexturesUsed[u]) {
+ /* Note: _Current *should* correspond to the target indicated
+ * in TexturesUsed[u].
+ */
+ ctx->Driver.MapTexture(ctx, ctx->Texture.Unit[u]._Current);
+ }
+ }
+}
+
+
+/**
+ * Unmap the texture images which were used by the vertex program (if any).
+ */
+static void
+unmap_textures(struct gl_context *ctx, const struct gl_vertex_program *vp)
+{
+ GLuint u;
+
+ if (!ctx->Driver.MapTexture)
+ return;
+
+ for (u = 0; u < ctx->Const.MaxVertexTextureImageUnits; u++) {
+ if (vp->Base.TexturesUsed[u]) {
+ /* Note: _Current *should* correspond to the target indicated
+ * in TexturesUsed[u].
+ */
+ ctx->Driver.UnmapTexture(ctx, ctx->Texture.Unit[u]._Current);
+ }
+ }
+}
+
+
+/**
+ * This function executes vertex programs
+ */
+static GLboolean
+run_vp( struct gl_context *ctx, struct tnl_pipeline_stage *stage )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vp_stage_data *store = VP_STAGE_DATA(stage);
+ struct vertex_buffer *VB = &tnl->vb;
+ struct gl_vertex_program *program = ctx->VertexProgram._Current;
+ struct gl_program_machine *machine = &store->machine;
+ GLuint outputs[VERT_RESULT_MAX], numOutputs;
+ GLuint i, j;
+
+ if (!program)
+ return GL_TRUE;
+
+ if (program->IsNVProgram) {
+ _mesa_load_tracked_matrices(ctx);
+ }
+ else {
+ /* ARB program or vertex shader */
+ _mesa_load_state_parameters(ctx, program->Base.Parameters);
+ }
+
+ /* make list of outputs to save some time below */
+ numOutputs = 0;
+ for (i = 0; i < VERT_RESULT_MAX; i++) {
+ if (program->Base.OutputsWritten & BITFIELD64_BIT(i)) {
+ outputs[numOutputs++] = i;
+ }
+ }
+
+ map_textures(ctx, program);
+
+ for (i = 0; i < VB->Count; i++) {
+ GLuint attr;
+
+ init_machine(ctx, machine);
+
+#if 0
+ printf("Input %d: %f, %f, %f, %f\n", i,
+ VB->AttribPtr[0]->data[i][0],
+ VB->AttribPtr[0]->data[i][1],
+ VB->AttribPtr[0]->data[i][2],
+ VB->AttribPtr[0]->data[i][3]);
+ printf(" color: %f, %f, %f, %f\n",
+ VB->AttribPtr[3]->data[i][0],
+ VB->AttribPtr[3]->data[i][1],
+ VB->AttribPtr[3]->data[i][2],
+ VB->AttribPtr[3]->data[i][3]);
+ printf(" normal: %f, %f, %f, %f\n",
+ VB->AttribPtr[2]->data[i][0],
+ VB->AttribPtr[2]->data[i][1],
+ VB->AttribPtr[2]->data[i][2],
+ VB->AttribPtr[2]->data[i][3]);
+#endif
+
+ /* the vertex array case */
+ for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) {
+ if (program->Base.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);
+#ifdef NAN_CHECK
+ check_float(data[0]);
+ check_float(data[1]);
+ check_float(data[2]);
+ check_float(data[3]);
+#endif
+ COPY_CLEAN_4V(machine->VertAttribs[attr], size, data);
+ }
+ }
+
+ /* execute the program */
+ _mesa_execute_program(ctx, &program->Base, machine);
+
+ /* copy the output registers into the VB->attribs arrays */
+ for (j = 0; j < numOutputs; j++) {
+ const GLuint attr = outputs[j];
+#ifdef NAN_CHECK
+ check_float(machine->Outputs[attr][0]);
+ check_float(machine->Outputs[attr][1]);
+ check_float(machine->Outputs[attr][2]);
+ check_float(machine->Outputs[attr][3]);
+#endif
+ COPY_4V(store->results[attr].data[i], machine->Outputs[attr]);
+ }
+
+ /* FOGC is a special case. Fragment shader expects (f,0,0,1) */
+ if (program->Base.OutputsWritten & BITFIELD64_BIT(VERT_RESULT_FOGC)) {
+ store->results[VERT_RESULT_FOGC].data[i][1] = 0.0;
+ store->results[VERT_RESULT_FOGC].data[i][2] = 0.0;
+ store->results[VERT_RESULT_FOGC].data[i][3] = 1.0;
+ }
+#ifdef NAN_CHECK
+ ASSERT(machine->Outputs[0][3] != 0.0F);
+#endif
+#if 0
+ printf("HPOS: %f %f %f %f\n",
+ machine->Outputs[0][0],
+ machine->Outputs[0][1],
+ machine->Outputs[0][2],
+ machine->Outputs[0][3]);
+#endif
+ }
+
+ unmap_textures(ctx, program);
+
+ /* Fixup fog and point size results if needed */
+ if (program->IsNVProgram) {
+ if (ctx->Fog.Enabled &&
+ (program->Base.OutputsWritten & BITFIELD64_BIT(VERT_RESULT_FOGC)) == 0) {
+ for (i = 0; i < VB->Count; i++) {
+ store->results[VERT_RESULT_FOGC].data[i][0] = 1.0;
+ }
+ }
+
+ if (ctx->VertexProgram.PointSizeEnabled &&
+ (program->Base.OutputsWritten & BITFIELD64_BIT(VERT_RESULT_PSIZ)) == 0) {
+ for (i = 0; i < VB->Count; i++) {
+ store->results[VERT_RESULT_PSIZ].data[i][0] = ctx->Point.Size;
+ }
+ }
+ }
+
+ if (program->IsPositionInvariant) {
+ /* We need the exact same transform as in the fixed function path here
+ * to guarantee invariance, depending on compiler optimization flags
+ * results could be different otherwise.
+ */
+ VB->ClipPtr = TransformRaw( &store->results[0],
+ &ctx->_ModelProjectMatrix,
+ VB->AttribPtr[0] );
+
+ /* Drivers expect this to be clean to element 4...
+ */
+ switch (VB->ClipPtr->size) {
+ case 1:
+ /* impossible */
+ case 2:
+ _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 2 );
+ /* fall-through */
+ case 3:
+ _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 3 );
+ /* fall-through */
+ case 4:
+ break;
+ }
+ }
+ else {
+ /* Setup the VB pointers so that the next pipeline stages get
+ * their data from the right place (the program output arrays).
+ */
+ VB->ClipPtr = &store->results[VERT_RESULT_HPOS];
+ VB->ClipPtr->size = 4;
+ VB->ClipPtr->count = VB->Count;
+ }
+
+ VB->AttribPtr[VERT_ATTRIB_COLOR0] = &store->results[VERT_RESULT_COL0];
+ VB->AttribPtr[VERT_ATTRIB_COLOR1] = &store->results[VERT_RESULT_COL1];
+ VB->AttribPtr[VERT_ATTRIB_FOG] = &store->results[VERT_RESULT_FOGC];
+ VB->AttribPtr[_TNL_ATTRIB_POINTSIZE] = &store->results[VERT_RESULT_PSIZ];
+ VB->BackfaceColorPtr = &store->results[VERT_RESULT_BFC0];
+ VB->BackfaceSecondaryColorPtr = &store->results[VERT_RESULT_BFC1];
+
+ for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
+ VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]
+ = &store->results[VERT_RESULT_TEX0 + i];
+ }
+
+ for (i = 0; i < ctx->Const.MaxVarying; i++) {
+ if (program->Base.OutputsWritten & BITFIELD64_BIT(VERT_RESULT_VAR0 + i)) {
+ /* Note: varying results get put into the generic attributes */
+ VB->AttribPtr[VERT_ATTRIB_GENERIC0+i]
+ = &store->results[VERT_RESULT_VAR0 + i];
+ }
+ }
+
+
+ /* Perform NDC and cliptest operations:
+ */
+ return do_ndc_cliptest(ctx, store);
+}
+
+
+/**
+ * Called the first time stage->run is called. In effect, don't
+ * allocate data until the first time the stage is run.
+ */
+static GLboolean
+init_vp(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &(tnl->vb);
+ struct vp_stage_data *store;
+ const GLuint size = VB->Size;
+ GLuint i;
+
+ stage->privatePtr = CALLOC(sizeof(*store));
+ store = VP_STAGE_DATA(stage);
+ if (!store)
+ return GL_FALSE;
+
+ /* Allocate arrays of vertex output values */
+ for (i = 0; i < VERT_RESULT_MAX; i++) {
+ _mesa_vector4f_alloc( &store->results[i], 0, size, 32 );
+ store->results[i].size = 4;
+ }
+
+ /* a few other misc allocations */
+ _mesa_vector4f_alloc( &store->ndcCoords, 0, size, 32 );
+ store->clipmask = (GLubyte *) _mesa_align_malloc(sizeof(GLubyte)*size, 32 );
+
+ return GL_TRUE;
+}
+
+
+/**
+ * Destructor for this pipeline stage.
+ */
+static void
+dtr(struct tnl_pipeline_stage *stage)
+{
+ struct vp_stage_data *store = VP_STAGE_DATA(stage);
+
+ if (store) {
+ GLuint i;
+
+ /* free the vertex program result arrays */
+ for (i = 0; i < VERT_RESULT_MAX; i++)
+ _mesa_vector4f_free( &store->results[i] );
+
+ /* free misc arrays */
+ _mesa_vector4f_free( &store->ndcCoords );
+ _mesa_align_free( store->clipmask );
+
+ FREE( store );
+ stage->privatePtr = NULL;
+ }
+}
+
+
+static void
+validate_vp_stage(struct gl_context *ctx, struct tnl_pipeline_stage *stage)
+{
+ if (ctx->VertexProgram._Current) {
+ _swrast_update_texture_samplers(ctx);
+ }
+}
+
+
+
+/**
+ * Public description of this pipeline stage.
+ */
+const struct tnl_pipeline_stage _tnl_vertex_program_stage =
+{
+ "vertex-program",
+ NULL, /* private_data */
+ init_vp, /* create */
+ dtr, /* destroy */
+ validate_vp_stage, /* validate */
+ run_vp /* run -- initially set to ctr */
+};
diff --git a/mesalib/src/mesa/tnl/t_vb_render.c b/mesalib/src/mesa/tnl/t_vb_render.c index 7d991009a..64dabca98 100644 --- a/mesalib/src/mesa/tnl/t_vb_render.c +++ b/mesalib/src/mesa/tnl/t_vb_render.c @@ -1,348 +1,348 @@ -/* - * Mesa 3-D graphics library - * Version: 6.5 - * - * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Keith Whitwell <keith@tungstengraphics.com> - */ - - -/* - * Render whole vertex buffers, including projection of vertices from - * clip space and clipping of primitives. - * - * This file makes calls to project vertices and to the point, line - * and triangle rasterizers via the function pointers: - * - * context->Driver.Render.* - * - */ - - -#include "main/glheader.h" -#include "main/context.h" -#include "main/enums.h" -#include "main/macros.h" -#include "main/imports.h" -#include "main/mtypes.h" -#include "math/m_xform.h" - -#include "t_pipeline.h" - - - -/**********************************************************************/ -/* Clip single primitives */ -/**********************************************************************/ - - -#define W(i) coord[i][3] -#define Z(i) coord[i][2] -#define Y(i) coord[i][1] -#define X(i) coord[i][0] -#define SIZE 4 -#define TAG(x) x##_4 -#include "t_vb_cliptmp.h" - - - -/**********************************************************************/ -/* Clip and render whole begin/end objects */ -/**********************************************************************/ - -#define NEED_EDGEFLAG_SETUP (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL) -#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx] -#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val - - -/* This does NOT include the CLIP_USER_BIT! */ -#define CLIPMASK (CLIP_FRUSTUM_BITS | CLIP_CULL_BIT) - - -/* Vertices, with the possibility of clipping. - */ -#define RENDER_POINTS( start, count ) \ - tnl->Driver.Render.Points( ctx, start, count ) - -#define RENDER_LINE( v1, v2 ) \ -do { \ - GLubyte c1 = mask[v1], c2 = mask[v2]; \ - GLubyte ormask = c1|c2; \ - if (!ormask) \ - LineFunc( ctx, v1, v2 ); \ - else if (!(c1 & c2 & CLIPMASK)) \ - clip_line_4( ctx, v1, v2, ormask ); \ -} while (0) - -#define RENDER_TRI( v1, v2, v3 ) \ -do { \ - GLubyte c1 = mask[v1], c2 = mask[v2], c3 = mask[v3]; \ - GLubyte ormask = c1|c2|c3; \ - if (!ormask) \ - TriangleFunc( ctx, v1, v2, v3 ); \ - else if (!(c1 & c2 & c3 & CLIPMASK)) \ - clip_tri_4( ctx, v1, v2, v3, ormask ); \ -} while (0) - -#define RENDER_QUAD( v1, v2, v3, v4 ) \ -do { \ - GLubyte c1 = mask[v1], c2 = mask[v2]; \ - GLubyte c3 = mask[v3], c4 = mask[v4]; \ - GLubyte ormask = c1|c2|c3|c4; \ - if (!ormask) \ - QuadFunc( ctx, v1, v2, v3, v4 ); \ - else if (!(c1 & c2 & c3 & c4 & CLIPMASK)) \ - clip_quad_4( ctx, v1, v2, v3, v4, ormask ); \ -} while (0) - - -#define LOCAL_VARS \ - TNLcontext *tnl = TNL_CONTEXT(ctx); \ - struct vertex_buffer *VB = &tnl->vb; \ - const GLuint * const elt = VB->Elts; \ - const GLubyte *mask = VB->ClipMask; \ - const GLuint sz = VB->ClipPtr->size; \ - const tnl_line_func LineFunc = tnl->Driver.Render.Line; \ - const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \ - const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad; \ - const GLboolean stipple = ctx->Line.StippleFlag; \ - (void) (LineFunc && TriangleFunc && QuadFunc); \ - (void) elt; (void) mask; (void) sz; (void) stipple; - -#define TAG(x) clip_##x##_verts -#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x ) -#define RESET_STIPPLE if (stipple) tnl->Driver.Render.ResetLineStipple( ctx ) -#define PRESERVE_VB_DEFS -#include "t_vb_rendertmp.h" - - - -/* Elts, with the possibility of clipping. - */ -#undef ELT -#undef TAG -#define ELT(x) elt[x] -#define TAG(x) clip_##x##_elts -#include "t_vb_rendertmp.h" - -/* TODO: do this for all primitives, verts and elts: - */ -static void clip_elt_triangles( GLcontext *ctx, - GLuint start, - GLuint count, - GLuint flags ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - tnl_render_func render_tris = tnl->Driver.Render.PrimTabElts[GL_TRIANGLES]; - struct vertex_buffer *VB = &tnl->vb; - const GLuint * const elt = VB->Elts; - GLubyte *mask = VB->ClipMask; - GLuint last = count-2; - GLuint j; - (void) flags; - - tnl->Driver.Render.PrimitiveNotify( ctx, GL_TRIANGLES ); - - for (j=start; j < last; j+=3 ) { - GLubyte c1 = mask[elt[j]]; - GLubyte c2 = mask[elt[j+1]]; - GLubyte c3 = mask[elt[j+2]]; - GLubyte ormask = c1|c2|c3; - if (ormask) { - if (start < j) - render_tris( ctx, start, j, 0 ); - if (!(c1&c2&c3&CLIPMASK)) - clip_tri_4( ctx, elt[j], elt[j+1], elt[j+2], ormask ); - start = j+3; - } - } - - if (start < j) - render_tris( ctx, start, j, 0 ); -} - -/**********************************************************************/ -/* Render whole begin/end objects */ -/**********************************************************************/ - -#define NEED_EDGEFLAG_SETUP (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL) -#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx] -#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val - - -/* Vertices, no clipping. - */ -#define RENDER_POINTS( start, count ) \ - tnl->Driver.Render.Points( ctx, start, count ) - -#define RENDER_LINE( v1, v2 ) \ - LineFunc( ctx, v1, v2 ) - -#define RENDER_TRI( v1, v2, v3 ) \ - TriangleFunc( ctx, v1, v2, v3 ) - -#define RENDER_QUAD( v1, v2, v3, v4 ) \ - QuadFunc( ctx, v1, v2, v3, v4 ) - -#define TAG(x) _tnl_##x##_verts - -#define LOCAL_VARS \ - TNLcontext *tnl = TNL_CONTEXT(ctx); \ - struct vertex_buffer *VB = &tnl->vb; \ - const GLuint * const elt = VB->Elts; \ - const tnl_line_func LineFunc = tnl->Driver.Render.Line; \ - const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \ - const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad; \ - const GLboolean stipple = ctx->Line.StippleFlag; \ - (void) (LineFunc && TriangleFunc && QuadFunc); \ - (void) elt; (void) stipple - -#define RESET_STIPPLE if (stipple) tnl->Driver.Render.ResetLineStipple( ctx ) -#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x ) -#define RENDER_TAB_QUALIFIER -#define PRESERVE_VB_DEFS -#include "t_vb_rendertmp.h" - - -/* Elts, no clipping. - */ -#undef ELT -#define TAG(x) _tnl_##x##_elts -#define ELT(x) elt[x] -#include "t_vb_rendertmp.h" - - -/**********************************************************************/ -/* Helper functions for drivers */ -/**********************************************************************/ - -void _tnl_RenderClippedPolygon( GLcontext *ctx, const GLuint *elts, GLuint n ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - GLuint *tmp = VB->Elts; - - VB->Elts = (GLuint *)elts; - tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END ); - VB->Elts = tmp; -} - -void _tnl_RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - tnl->Driver.Render.Line( ctx, ii, jj ); -} - - - -/**********************************************************************/ -/* Clip and render whole vertex buffers */ -/**********************************************************************/ - - -static GLboolean run_render( GLcontext *ctx, - struct tnl_pipeline_stage *stage ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - tnl_render_func *tab; - GLint pass = 0; - - /* Allow the drivers to lock before projected verts are built so - * that window coordinates are guarenteed not to change before - * rendering. - */ - ASSERT(tnl->Driver.Render.Start); - - tnl->Driver.Render.Start( ctx ); - - ASSERT(tnl->Driver.Render.BuildVertices); - ASSERT(tnl->Driver.Render.PrimitiveNotify); - ASSERT(tnl->Driver.Render.Points); - ASSERT(tnl->Driver.Render.Line); - ASSERT(tnl->Driver.Render.Triangle); - ASSERT(tnl->Driver.Render.Quad); - ASSERT(tnl->Driver.Render.ResetLineStipple); - ASSERT(tnl->Driver.Render.Interp); - ASSERT(tnl->Driver.Render.CopyPV); - ASSERT(tnl->Driver.Render.ClippedLine); - ASSERT(tnl->Driver.Render.ClippedPolygon); - ASSERT(tnl->Driver.Render.Finish); - - tnl->Driver.Render.BuildVertices( ctx, 0, VB->Count, ~0 ); - - if (VB->ClipOrMask) { - tab = VB->Elts ? clip_render_tab_elts : clip_render_tab_verts; - clip_render_tab_elts[GL_TRIANGLES] = clip_elt_triangles; - } - else { - tab = (VB->Elts ? - tnl->Driver.Render.PrimTabElts : - tnl->Driver.Render.PrimTabVerts); - } - - do - { - GLuint i; - - for (i = 0 ; i < VB->PrimitiveCount ; i++) - { - GLuint prim = _tnl_translate_prim(&VB->Primitive[i]); - GLuint start = VB->Primitive[i].start; - GLuint length = VB->Primitive[i].count; - - assert((prim & PRIM_MODE_MASK) <= GL_POLYGON); - - if (MESA_VERBOSE & VERBOSE_PRIMS) - _mesa_debug(NULL, "MESA prim %s %d..%d\n", - _mesa_lookup_enum_by_nr(prim & PRIM_MODE_MASK), - start, start+length); - - if (length) - 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 ); - - return GL_FALSE; /* finished the pipe */ -} - - -/**********************************************************************/ -/* Render pipeline stage */ -/**********************************************************************/ - - - - - -const struct tnl_pipeline_stage _tnl_render_stage = -{ - "render", /* name */ - NULL, /* private data */ - NULL, /* creator */ - NULL, /* destructor */ - NULL, /* validate */ - run_render /* run */ -}; +/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+/*
+ * Render whole vertex buffers, including projection of vertices from
+ * clip space and clipping of primitives.
+ *
+ * This file makes calls to project vertices and to the point, line
+ * and triangle rasterizers via the function pointers:
+ *
+ * context->Driver.Render.*
+ *
+ */
+
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/enums.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+#include "math/m_xform.h"
+
+#include "t_pipeline.h"
+
+
+
+/**********************************************************************/
+/* Clip single primitives */
+/**********************************************************************/
+
+
+#define W(i) coord[i][3]
+#define Z(i) coord[i][2]
+#define Y(i) coord[i][1]
+#define X(i) coord[i][0]
+#define SIZE 4
+#define TAG(x) x##_4
+#include "t_vb_cliptmp.h"
+
+
+
+/**********************************************************************/
+/* Clip and render whole begin/end objects */
+/**********************************************************************/
+
+#define NEED_EDGEFLAG_SETUP (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL)
+#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
+#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
+
+
+/* This does NOT include the CLIP_USER_BIT! */
+#define CLIPMASK (CLIP_FRUSTUM_BITS | CLIP_CULL_BIT)
+
+
+/* Vertices, with the possibility of clipping.
+ */
+#define RENDER_POINTS( start, count ) \
+ tnl->Driver.Render.Points( ctx, start, count )
+
+#define RENDER_LINE( v1, v2 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2]; \
+ GLubyte ormask = c1|c2; \
+ if (!ormask) \
+ LineFunc( ctx, v1, v2 ); \
+ else if (!(c1 & c2 & CLIPMASK)) \
+ clip_line_4( ctx, v1, v2, ormask ); \
+} while (0)
+
+#define RENDER_TRI( v1, v2, v3 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2], c3 = mask[v3]; \
+ GLubyte ormask = c1|c2|c3; \
+ if (!ormask) \
+ TriangleFunc( ctx, v1, v2, v3 ); \
+ else if (!(c1 & c2 & c3 & CLIPMASK)) \
+ clip_tri_4( ctx, v1, v2, v3, ormask ); \
+} while (0)
+
+#define RENDER_QUAD( v1, v2, v3, v4 ) \
+do { \
+ GLubyte c1 = mask[v1], c2 = mask[v2]; \
+ GLubyte c3 = mask[v3], c4 = mask[v4]; \
+ GLubyte ormask = c1|c2|c3|c4; \
+ if (!ormask) \
+ QuadFunc( ctx, v1, v2, v3, v4 ); \
+ else if (!(c1 & c2 & c3 & c4 & CLIPMASK)) \
+ clip_quad_4( ctx, v1, v2, v3, v4, ormask ); \
+} while (0)
+
+
+#define LOCAL_VARS \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ const GLuint * const elt = VB->Elts; \
+ const GLubyte *mask = VB->ClipMask; \
+ const GLuint sz = VB->ClipPtr->size; \
+ const tnl_line_func LineFunc = tnl->Driver.Render.Line; \
+ const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \
+ const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad; \
+ const GLboolean stipple = ctx->Line.StippleFlag; \
+ (void) (LineFunc && TriangleFunc && QuadFunc); \
+ (void) elt; (void) mask; (void) sz; (void) stipple;
+
+#define TAG(x) clip_##x##_verts
+#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
+#define RESET_STIPPLE if (stipple) tnl->Driver.Render.ResetLineStipple( ctx )
+#define PRESERVE_VB_DEFS
+#include "t_vb_rendertmp.h"
+
+
+
+/* Elts, with the possibility of clipping.
+ */
+#undef ELT
+#undef TAG
+#define ELT(x) elt[x]
+#define TAG(x) clip_##x##_elts
+#include "t_vb_rendertmp.h"
+
+/* TODO: do this for all primitives, verts and elts:
+ */
+static void clip_elt_triangles( struct gl_context *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl_render_func render_tris = tnl->Driver.Render.PrimTabElts[GL_TRIANGLES];
+ struct vertex_buffer *VB = &tnl->vb;
+ const GLuint * const elt = VB->Elts;
+ GLubyte *mask = VB->ClipMask;
+ GLuint last = count-2;
+ GLuint j;
+ (void) flags;
+
+ tnl->Driver.Render.PrimitiveNotify( ctx, GL_TRIANGLES );
+
+ for (j=start; j < last; j+=3 ) {
+ GLubyte c1 = mask[elt[j]];
+ GLubyte c2 = mask[elt[j+1]];
+ GLubyte c3 = mask[elt[j+2]];
+ GLubyte ormask = c1|c2|c3;
+ if (ormask) {
+ if (start < j)
+ render_tris( ctx, start, j, 0 );
+ if (!(c1&c2&c3&CLIPMASK))
+ clip_tri_4( ctx, elt[j], elt[j+1], elt[j+2], ormask );
+ start = j+3;
+ }
+ }
+
+ if (start < j)
+ render_tris( ctx, start, j, 0 );
+}
+
+/**********************************************************************/
+/* Render whole begin/end objects */
+/**********************************************************************/
+
+#define NEED_EDGEFLAG_SETUP (ctx->Polygon.FrontMode != GL_FILL || ctx->Polygon.BackMode != GL_FILL)
+#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx]
+#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val
+
+
+/* Vertices, no clipping.
+ */
+#define RENDER_POINTS( start, count ) \
+ tnl->Driver.Render.Points( ctx, start, count )
+
+#define RENDER_LINE( v1, v2 ) \
+ LineFunc( ctx, v1, v2 )
+
+#define RENDER_TRI( v1, v2, v3 ) \
+ TriangleFunc( ctx, v1, v2, v3 )
+
+#define RENDER_QUAD( v1, v2, v3, v4 ) \
+ QuadFunc( ctx, v1, v2, v3, v4 )
+
+#define TAG(x) _tnl_##x##_verts
+
+#define LOCAL_VARS \
+ TNLcontext *tnl = TNL_CONTEXT(ctx); \
+ struct vertex_buffer *VB = &tnl->vb; \
+ const GLuint * const elt = VB->Elts; \
+ const tnl_line_func LineFunc = tnl->Driver.Render.Line; \
+ const tnl_triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \
+ const tnl_quad_func QuadFunc = tnl->Driver.Render.Quad; \
+ const GLboolean stipple = ctx->Line.StippleFlag; \
+ (void) (LineFunc && TriangleFunc && QuadFunc); \
+ (void) elt; (void) stipple
+
+#define RESET_STIPPLE if (stipple) tnl->Driver.Render.ResetLineStipple( ctx )
+#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x )
+#define RENDER_TAB_QUALIFIER
+#define PRESERVE_VB_DEFS
+#include "t_vb_rendertmp.h"
+
+
+/* Elts, no clipping.
+ */
+#undef ELT
+#define TAG(x) _tnl_##x##_elts
+#define ELT(x) elt[x]
+#include "t_vb_rendertmp.h"
+
+
+/**********************************************************************/
+/* Helper functions for drivers */
+/**********************************************************************/
+
+void _tnl_RenderClippedPolygon( struct gl_context *ctx, const GLuint *elts, GLuint n )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLuint *tmp = VB->Elts;
+
+ VB->Elts = (GLuint *)elts;
+ tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END );
+ VB->Elts = tmp;
+}
+
+void _tnl_RenderClippedLine( struct gl_context *ctx, GLuint ii, GLuint jj )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ tnl->Driver.Render.Line( ctx, ii, jj );
+}
+
+
+
+/**********************************************************************/
+/* Clip and render whole vertex buffers */
+/**********************************************************************/
+
+
+static GLboolean run_render( struct gl_context *ctx,
+ struct tnl_pipeline_stage *stage )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ tnl_render_func *tab;
+ GLint pass = 0;
+
+ /* Allow the drivers to lock before projected verts are built so
+ * that window coordinates are guarenteed not to change before
+ * rendering.
+ */
+ ASSERT(tnl->Driver.Render.Start);
+
+ tnl->Driver.Render.Start( ctx );
+
+ ASSERT(tnl->Driver.Render.BuildVertices);
+ ASSERT(tnl->Driver.Render.PrimitiveNotify);
+ ASSERT(tnl->Driver.Render.Points);
+ ASSERT(tnl->Driver.Render.Line);
+ ASSERT(tnl->Driver.Render.Triangle);
+ ASSERT(tnl->Driver.Render.Quad);
+ ASSERT(tnl->Driver.Render.ResetLineStipple);
+ ASSERT(tnl->Driver.Render.Interp);
+ ASSERT(tnl->Driver.Render.CopyPV);
+ ASSERT(tnl->Driver.Render.ClippedLine);
+ ASSERT(tnl->Driver.Render.ClippedPolygon);
+ ASSERT(tnl->Driver.Render.Finish);
+
+ tnl->Driver.Render.BuildVertices( ctx, 0, VB->Count, ~0 );
+
+ if (VB->ClipOrMask) {
+ tab = VB->Elts ? clip_render_tab_elts : clip_render_tab_verts;
+ clip_render_tab_elts[GL_TRIANGLES] = clip_elt_triangles;
+ }
+ else {
+ tab = (VB->Elts ?
+ tnl->Driver.Render.PrimTabElts :
+ tnl->Driver.Render.PrimTabVerts);
+ }
+
+ do
+ {
+ GLuint i;
+
+ for (i = 0 ; i < VB->PrimitiveCount ; i++)
+ {
+ GLuint prim = _tnl_translate_prim(&VB->Primitive[i]);
+ GLuint start = VB->Primitive[i].start;
+ GLuint length = VB->Primitive[i].count;
+
+ assert((prim & PRIM_MODE_MASK) <= GL_POLYGON);
+
+ if (MESA_VERBOSE & VERBOSE_PRIMS)
+ _mesa_debug(NULL, "MESA prim %s %d..%d\n",
+ _mesa_lookup_enum_by_nr(prim & PRIM_MODE_MASK),
+ start, start+length);
+
+ if (length)
+ 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 );
+
+ return GL_FALSE; /* finished the pipe */
+}
+
+
+/**********************************************************************/
+/* Render pipeline stage */
+/**********************************************************************/
+
+
+
+
+
+const struct tnl_pipeline_stage _tnl_render_stage =
+{
+ "render", /* name */
+ NULL, /* private data */
+ NULL, /* creator */
+ NULL, /* destructor */
+ NULL, /* validate */
+ run_render /* run */
+};
diff --git a/mesalib/src/mesa/tnl/t_vb_rendertmp.h b/mesalib/src/mesa/tnl/t_vb_rendertmp.h index 75f6f55bd..92dbf219d 100644 --- a/mesalib/src/mesa/tnl/t_vb_rendertmp.h +++ b/mesalib/src/mesa/tnl/t_vb_rendertmp.h @@ -1,486 +1,486 @@ -/* - * Mesa 3-D graphics library - * Version: 6.5 - * - * Copyright (C) 1999-2005 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Keith Whitwell <keith@tungstengraphics.com> - */ - - -#ifndef POSTFIX -#define POSTFIX -#endif - -#ifndef INIT -#define INIT(x) -#endif - -#ifndef NEED_EDGEFLAG_SETUP -#define NEED_EDGEFLAG_SETUP 0 -#define EDGEFLAG_GET(a) 0 -#define EDGEFLAG_SET(a,b) (void)b -#endif - -#ifndef RESET_STIPPLE -#define RESET_STIPPLE -#endif - -#ifndef TEST_PRIM_END -#define TEST_PRIM_END(prim) (flags & PRIM_END) -#define TEST_PRIM_BEGIN(prim) (flags & PRIM_BEGIN) -#endif - -#ifndef ELT -#define ELT(x) x -#endif - -#ifndef RENDER_TAB_QUALIFIER -#define RENDER_TAB_QUALIFIER static -#endif - -static void TAG(render_points)( GLcontext *ctx, - GLuint start, - GLuint count, - GLuint flags ) -{ - LOCAL_VARS; - (void) flags; - - INIT(GL_POINTS); - RENDER_POINTS( start, count ); - POSTFIX; -} - -static void TAG(render_lines)( GLcontext *ctx, - GLuint start, - GLuint count, - GLuint flags ) -{ - GLuint j; - LOCAL_VARS; - (void) flags; - - INIT(GL_LINES); - for (j=start+1; j<count; j+=2 ) { - RESET_STIPPLE; - if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) - RENDER_LINE( ELT(j-1), ELT(j) ); - else - RENDER_LINE( ELT(j), ELT(j-1) ); - } - POSTFIX; -} - - -static void TAG(render_line_strip)( GLcontext *ctx, - GLuint start, - GLuint count, - GLuint flags ) -{ - GLuint j; - LOCAL_VARS; - (void) flags; - - INIT(GL_LINE_STRIP); - - if (TEST_PRIM_BEGIN(flags)) { - RESET_STIPPLE; - } - - for (j=start+1; j<count; j++ ) { - if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) - RENDER_LINE( ELT(j-1), ELT(j) ); - else - RENDER_LINE( ELT(j), ELT(j-1) ); - } - POSTFIX; -} - - -static void TAG(render_line_loop)( GLcontext *ctx, - GLuint start, - GLuint count, - GLuint flags ) -{ - GLuint i; - LOCAL_VARS; - - (void) flags; - - INIT(GL_LINE_LOOP); - - if (start+1 < count) { - if (TEST_PRIM_BEGIN(flags)) { - RESET_STIPPLE; - if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) - RENDER_LINE( ELT(start), ELT(start+1) ); - else - RENDER_LINE( ELT(start+1), ELT(start) ); - } - - for ( i = start+2 ; i < count ; i++) { - if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) - RENDER_LINE( ELT(i-1), ELT(i) ); - else - RENDER_LINE( ELT(i), ELT(i-1) ); - } - - if ( TEST_PRIM_END(flags)) { - if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) - RENDER_LINE( ELT(count-1), ELT(start) ); - else - RENDER_LINE( ELT(start), ELT(count-1) ); - } - } - - POSTFIX; -} - - -static void TAG(render_triangles)( GLcontext *ctx, - GLuint start, - GLuint count, - GLuint flags ) -{ - GLuint j; - LOCAL_VARS; - (void) flags; - - INIT(GL_TRIANGLES); - if (NEED_EDGEFLAG_SETUP) { - for (j=start+2; j<count; j+=3) { - /* Leave the edgeflags as supplied by the user. - */ - RESET_STIPPLE; - if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) - RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) ); - else - RENDER_TRI( ELT(j-1), ELT(j), ELT(j-2) ); - } - } else { - for (j=start+2; j<count; j+=3) { - if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) - RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) ); - else - RENDER_TRI( ELT(j-1), ELT(j), ELT(j-2) ); - } - } - POSTFIX; -} - - - -static void TAG(render_tri_strip)( GLcontext *ctx, - GLuint start, - GLuint count, - GLuint flags ) -{ - GLuint j; - GLuint parity = 0; - LOCAL_VARS; - - INIT(GL_TRIANGLE_STRIP); - if (NEED_EDGEFLAG_SETUP) { - for (j=start+2;j<count;j++,parity^=1) { - GLuint ej2, ej1, ej; - GLboolean ef2, ef1, ef; - if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) { - ej2 = ELT(j-2+parity); - ej1 = ELT(j-1-parity); - ej = ELT(j); - } - else { - ej2 = ELT(j-1+parity); - ej1 = ELT(j-parity); - ej = ELT(j-2); - } - ef2 = EDGEFLAG_GET( ej2 ); - ef1 = EDGEFLAG_GET( ej1 ); - ef = EDGEFLAG_GET( ej ); - if (TEST_PRIM_BEGIN(flags)) { - RESET_STIPPLE; - } - EDGEFLAG_SET( ej2, GL_TRUE ); - EDGEFLAG_SET( ej1, GL_TRUE ); - EDGEFLAG_SET( ej, GL_TRUE ); - RENDER_TRI( ej2, ej1, ej ); - EDGEFLAG_SET( ej2, ef2 ); - EDGEFLAG_SET( ej1, ef1 ); - EDGEFLAG_SET( ej, ef ); - } - } else { - for (j=start+2; j<count ; j++, parity^=1) { - if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) - RENDER_TRI( ELT(j-2+parity), ELT(j-1-parity), ELT(j) ); - else - RENDER_TRI( ELT(j-1+parity), ELT(j-parity), ELT(j-2) ); - } - } - POSTFIX; -} - - -static void TAG(render_tri_fan)( GLcontext *ctx, - GLuint start, - GLuint count, - GLuint flags ) -{ - GLuint j; - LOCAL_VARS; - (void) flags; - - INIT(GL_TRIANGLE_FAN); - if (NEED_EDGEFLAG_SETUP) { - for (j=start+2;j<count;j++) { - /* For trifans, all edges are boundary. - */ - GLuint ejs = ELT(start); - GLuint ej1 = ELT(j-1); - GLuint ej = ELT(j); - GLboolean efs = EDGEFLAG_GET( ejs ); - GLboolean ef1 = EDGEFLAG_GET( ej1 ); - GLboolean ef = EDGEFLAG_GET( ej ); - if (TEST_PRIM_BEGIN(flags)) { - RESET_STIPPLE; - } - EDGEFLAG_SET( ejs, GL_TRUE ); - EDGEFLAG_SET( ej1, GL_TRUE ); - EDGEFLAG_SET( ej, GL_TRUE ); - if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) - RENDER_TRI( ejs, ej1, ej); - else - RENDER_TRI( ej, ejs, ej1); - EDGEFLAG_SET( ejs, efs ); - EDGEFLAG_SET( ej1, ef1 ); - EDGEFLAG_SET( ej, ef ); - } - } else { - for (j=start+2;j<count;j++) { - if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) - RENDER_TRI( ELT(start), ELT(j-1), ELT(j) ); - else - RENDER_TRI( ELT(j), ELT(start), ELT(j-1) ); - } - } - - POSTFIX; -} - - -static void TAG(render_poly)( GLcontext *ctx, - GLuint start, - GLuint count, - GLuint flags ) -{ - GLuint j = start+2; - LOCAL_VARS; - (void) flags; - - INIT(GL_POLYGON); - if (NEED_EDGEFLAG_SETUP) { - GLboolean efstart = EDGEFLAG_GET( ELT(start) ); - GLboolean efcount = EDGEFLAG_GET( ELT(count-1) ); - - /* If the primitive does not begin here, the first edge - * is non-boundary. - */ - if (!TEST_PRIM_BEGIN(flags)) - EDGEFLAG_SET( ELT(start), GL_FALSE ); - else { - RESET_STIPPLE; - } - - /* If the primitive does not end here, the final edge is - * non-boundary. - */ - if (!TEST_PRIM_END(flags)) - EDGEFLAG_SET( ELT(count-1), GL_FALSE ); - - /* Draw the first triangles (possibly zero) - */ - if (j+1<count) { - GLboolean ef = EDGEFLAG_GET( ELT(j) ); - EDGEFLAG_SET( ELT(j), GL_FALSE ); - RENDER_TRI( ELT(j-1), ELT(j), ELT(start) ); - EDGEFLAG_SET( ELT(j), ef ); - j++; - - /* Don't render the first edge again: - */ - EDGEFLAG_SET( ELT(start), GL_FALSE ); - - for (;j+1<count;j++) { - GLboolean efj = EDGEFLAG_GET( ELT(j) ); - EDGEFLAG_SET( ELT(j), GL_FALSE ); - RENDER_TRI( ELT(j-1), ELT(j), ELT(start) ); - EDGEFLAG_SET( ELT(j), efj ); - } - } - - /* Draw the last or only triangle - */ - if (j < count) - RENDER_TRI( ELT(j-1), ELT(j), ELT(start) ); - - /* Restore the first and last edgeflags: - */ - EDGEFLAG_SET( ELT(count-1), efcount ); - EDGEFLAG_SET( ELT(start), efstart ); - - } - else { - for (j=start+2;j<count;j++) { - RENDER_TRI( ELT(j-1), ELT(j), ELT(start) ); - } - } - POSTFIX; -} - -static void TAG(render_quads)( GLcontext *ctx, - GLuint start, - GLuint count, - GLuint flags ) -{ - GLuint j; - LOCAL_VARS; - (void) flags; - - INIT(GL_QUADS); - if (NEED_EDGEFLAG_SETUP) { - for (j=start+3; j<count; j+=4) { - /* Use user-specified edgeflags for quads. - */ - RESET_STIPPLE; - if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT || - !ctx->Const.QuadsFollowProvokingVertexConvention) - RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) ); - else - RENDER_QUAD( ELT(j-2), ELT(j-1), ELT(j), ELT(j-3) ); - } - } else { - for (j=start+3; j<count; j+=4) { - if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT || - !ctx->Const.QuadsFollowProvokingVertexConvention) - RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) ); - else - RENDER_QUAD( ELT(j-2), ELT(j-1), ELT(j), ELT(j-3) ); - } - } - POSTFIX; -} - -static void TAG(render_quad_strip)( GLcontext *ctx, - GLuint start, - GLuint count, - GLuint flags ) -{ - GLuint j; - LOCAL_VARS; - (void) flags; - - INIT(GL_QUAD_STRIP); - if (NEED_EDGEFLAG_SETUP) { - for (j=start+3;j<count;j+=2) { - /* All edges are boundary. Set edgeflags to 1, draw the - * quad, and restore them to the original values. - */ - GLboolean ef3 = EDGEFLAG_GET( ELT(j-3) ); - GLboolean ef2 = EDGEFLAG_GET( ELT(j-2) ); - GLboolean ef1 = EDGEFLAG_GET( ELT(j-1) ); - GLboolean ef = EDGEFLAG_GET( ELT(j) ); - if (TEST_PRIM_BEGIN(flags)) { - RESET_STIPPLE; - } - EDGEFLAG_SET( ELT(j-3), GL_TRUE ); - EDGEFLAG_SET( ELT(j-2), GL_TRUE ); - EDGEFLAG_SET( ELT(j-1), GL_TRUE ); - EDGEFLAG_SET( ELT(j), GL_TRUE ); - if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT || - !ctx->Const.QuadsFollowProvokingVertexConvention) - RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) ); - else - RENDER_QUAD( ELT(j-2), ELT(j), ELT(j-1), ELT(j-3) ); - EDGEFLAG_SET( ELT(j-3), ef3 ); - EDGEFLAG_SET( ELT(j-2), ef2 ); - EDGEFLAG_SET( ELT(j-1), ef1 ); - EDGEFLAG_SET( ELT(j), ef ); - } - } else { - for (j=start+3;j<count;j+=2) { - if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT || - !ctx->Const.QuadsFollowProvokingVertexConvention) - RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) ); - else - RENDER_QUAD( ELT(j-2), ELT(j), ELT(j-1), ELT(j-3) ); - } - } - POSTFIX; -} - -static void TAG(render_noop)( GLcontext *ctx, - GLuint start, - GLuint count, - GLuint flags ) -{ - (void)(ctx && start && count && flags); -} - -RENDER_TAB_QUALIFIER void (*TAG(render_tab)[GL_POLYGON+2])(GLcontext *, - GLuint, - GLuint, - GLuint) = -{ - TAG(render_points), - TAG(render_lines), - TAG(render_line_loop), - TAG(render_line_strip), - TAG(render_triangles), - TAG(render_tri_strip), - TAG(render_tri_fan), - TAG(render_quads), - TAG(render_quad_strip), - TAG(render_poly), - TAG(render_noop), -}; - - - -#ifndef PRESERVE_VB_DEFS -#undef RENDER_TRI -#undef RENDER_QUAD -#undef RENDER_LINE -#undef RENDER_POINTS -#undef LOCAL_VARS -#undef INIT -#undef POSTFIX -#undef RESET_STIPPLE -#undef DBG -#undef ELT -#undef RENDER_TAB_QUALIFIER -#endif - -#ifndef PRESERVE_TAG -#undef TAG -#endif - -#undef PRESERVE_VB_DEFS -#undef PRESERVE_TAG +/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2005 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#ifndef POSTFIX
+#define POSTFIX
+#endif
+
+#ifndef INIT
+#define INIT(x)
+#endif
+
+#ifndef NEED_EDGEFLAG_SETUP
+#define NEED_EDGEFLAG_SETUP 0
+#define EDGEFLAG_GET(a) 0
+#define EDGEFLAG_SET(a,b) (void)b
+#endif
+
+#ifndef RESET_STIPPLE
+#define RESET_STIPPLE
+#endif
+
+#ifndef TEST_PRIM_END
+#define TEST_PRIM_END(prim) (flags & PRIM_END)
+#define TEST_PRIM_BEGIN(prim) (flags & PRIM_BEGIN)
+#endif
+
+#ifndef ELT
+#define ELT(x) x
+#endif
+
+#ifndef RENDER_TAB_QUALIFIER
+#define RENDER_TAB_QUALIFIER static
+#endif
+
+static void TAG(render_points)( struct gl_context *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ LOCAL_VARS;
+ (void) flags;
+
+ INIT(GL_POINTS);
+ RENDER_POINTS( start, count );
+ POSTFIX;
+}
+
+static void TAG(render_lines)( struct gl_context *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ GLuint j;
+ LOCAL_VARS;
+ (void) flags;
+
+ INIT(GL_LINES);
+ for (j=start+1; j<count; j+=2 ) {
+ RESET_STIPPLE;
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_LINE( ELT(j-1), ELT(j) );
+ else
+ RENDER_LINE( ELT(j), ELT(j-1) );
+ }
+ POSTFIX;
+}
+
+
+static void TAG(render_line_strip)( struct gl_context *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ GLuint j;
+ LOCAL_VARS;
+ (void) flags;
+
+ INIT(GL_LINE_STRIP);
+
+ if (TEST_PRIM_BEGIN(flags)) {
+ RESET_STIPPLE;
+ }
+
+ for (j=start+1; j<count; j++ ) {
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_LINE( ELT(j-1), ELT(j) );
+ else
+ RENDER_LINE( ELT(j), ELT(j-1) );
+ }
+ POSTFIX;
+}
+
+
+static void TAG(render_line_loop)( struct gl_context *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ GLuint i;
+ LOCAL_VARS;
+
+ (void) flags;
+
+ INIT(GL_LINE_LOOP);
+
+ if (start+1 < count) {
+ if (TEST_PRIM_BEGIN(flags)) {
+ RESET_STIPPLE;
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_LINE( ELT(start), ELT(start+1) );
+ else
+ RENDER_LINE( ELT(start+1), ELT(start) );
+ }
+
+ for ( i = start+2 ; i < count ; i++) {
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_LINE( ELT(i-1), ELT(i) );
+ else
+ RENDER_LINE( ELT(i), ELT(i-1) );
+ }
+
+ if ( TEST_PRIM_END(flags)) {
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_LINE( ELT(count-1), ELT(start) );
+ else
+ RENDER_LINE( ELT(start), ELT(count-1) );
+ }
+ }
+
+ POSTFIX;
+}
+
+
+static void TAG(render_triangles)( struct gl_context *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ GLuint j;
+ LOCAL_VARS;
+ (void) flags;
+
+ INIT(GL_TRIANGLES);
+ if (NEED_EDGEFLAG_SETUP) {
+ for (j=start+2; j<count; j+=3) {
+ /* Leave the edgeflags as supplied by the user.
+ */
+ RESET_STIPPLE;
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) );
+ else
+ RENDER_TRI( ELT(j-1), ELT(j), ELT(j-2) );
+ }
+ } else {
+ for (j=start+2; j<count; j+=3) {
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) );
+ else
+ RENDER_TRI( ELT(j-1), ELT(j), ELT(j-2) );
+ }
+ }
+ POSTFIX;
+}
+
+
+
+static void TAG(render_tri_strip)( struct gl_context *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ GLuint j;
+ GLuint parity = 0;
+ LOCAL_VARS;
+
+ INIT(GL_TRIANGLE_STRIP);
+ if (NEED_EDGEFLAG_SETUP) {
+ for (j=start+2;j<count;j++,parity^=1) {
+ GLuint ej2, ej1, ej;
+ GLboolean ef2, ef1, ef;
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT) {
+ ej2 = ELT(j-2+parity);
+ ej1 = ELT(j-1-parity);
+ ej = ELT(j);
+ }
+ else {
+ ej2 = ELT(j-1+parity);
+ ej1 = ELT(j-parity);
+ ej = ELT(j-2);
+ }
+ ef2 = EDGEFLAG_GET( ej2 );
+ ef1 = EDGEFLAG_GET( ej1 );
+ ef = EDGEFLAG_GET( ej );
+ if (TEST_PRIM_BEGIN(flags)) {
+ RESET_STIPPLE;
+ }
+ EDGEFLAG_SET( ej2, GL_TRUE );
+ EDGEFLAG_SET( ej1, GL_TRUE );
+ EDGEFLAG_SET( ej, GL_TRUE );
+ RENDER_TRI( ej2, ej1, ej );
+ EDGEFLAG_SET( ej2, ef2 );
+ EDGEFLAG_SET( ej1, ef1 );
+ EDGEFLAG_SET( ej, ef );
+ }
+ } else {
+ for (j=start+2; j<count ; j++, parity^=1) {
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_TRI( ELT(j-2+parity), ELT(j-1-parity), ELT(j) );
+ else
+ RENDER_TRI( ELT(j-1+parity), ELT(j-parity), ELT(j-2) );
+ }
+ }
+ POSTFIX;
+}
+
+
+static void TAG(render_tri_fan)( struct gl_context *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ GLuint j;
+ LOCAL_VARS;
+ (void) flags;
+
+ INIT(GL_TRIANGLE_FAN);
+ if (NEED_EDGEFLAG_SETUP) {
+ for (j=start+2;j<count;j++) {
+ /* For trifans, all edges are boundary.
+ */
+ GLuint ejs = ELT(start);
+ GLuint ej1 = ELT(j-1);
+ GLuint ej = ELT(j);
+ GLboolean efs = EDGEFLAG_GET( ejs );
+ GLboolean ef1 = EDGEFLAG_GET( ej1 );
+ GLboolean ef = EDGEFLAG_GET( ej );
+ if (TEST_PRIM_BEGIN(flags)) {
+ RESET_STIPPLE;
+ }
+ EDGEFLAG_SET( ejs, GL_TRUE );
+ EDGEFLAG_SET( ej1, GL_TRUE );
+ EDGEFLAG_SET( ej, GL_TRUE );
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_TRI( ejs, ej1, ej);
+ else
+ RENDER_TRI( ej, ejs, ej1);
+ EDGEFLAG_SET( ejs, efs );
+ EDGEFLAG_SET( ej1, ef1 );
+ EDGEFLAG_SET( ej, ef );
+ }
+ } else {
+ for (j=start+2;j<count;j++) {
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT)
+ RENDER_TRI( ELT(start), ELT(j-1), ELT(j) );
+ else
+ RENDER_TRI( ELT(j), ELT(start), ELT(j-1) );
+ }
+ }
+
+ POSTFIX;
+}
+
+
+static void TAG(render_poly)( struct gl_context *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ GLuint j = start+2;
+ LOCAL_VARS;
+ (void) flags;
+
+ INIT(GL_POLYGON);
+ if (NEED_EDGEFLAG_SETUP) {
+ GLboolean efstart = EDGEFLAG_GET( ELT(start) );
+ GLboolean efcount = EDGEFLAG_GET( ELT(count-1) );
+
+ /* If the primitive does not begin here, the first edge
+ * is non-boundary.
+ */
+ if (!TEST_PRIM_BEGIN(flags))
+ EDGEFLAG_SET( ELT(start), GL_FALSE );
+ else {
+ RESET_STIPPLE;
+ }
+
+ /* If the primitive does not end here, the final edge is
+ * non-boundary.
+ */
+ if (!TEST_PRIM_END(flags))
+ EDGEFLAG_SET( ELT(count-1), GL_FALSE );
+
+ /* Draw the first triangles (possibly zero)
+ */
+ if (j+1<count) {
+ GLboolean ef = EDGEFLAG_GET( ELT(j) );
+ EDGEFLAG_SET( ELT(j), GL_FALSE );
+ RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
+ EDGEFLAG_SET( ELT(j), ef );
+ j++;
+
+ /* Don't render the first edge again:
+ */
+ EDGEFLAG_SET( ELT(start), GL_FALSE );
+
+ for (;j+1<count;j++) {
+ GLboolean efj = EDGEFLAG_GET( ELT(j) );
+ EDGEFLAG_SET( ELT(j), GL_FALSE );
+ RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
+ EDGEFLAG_SET( ELT(j), efj );
+ }
+ }
+
+ /* Draw the last or only triangle
+ */
+ if (j < count)
+ RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
+
+ /* Restore the first and last edgeflags:
+ */
+ EDGEFLAG_SET( ELT(count-1), efcount );
+ EDGEFLAG_SET( ELT(start), efstart );
+
+ }
+ else {
+ for (j=start+2;j<count;j++) {
+ RENDER_TRI( ELT(j-1), ELT(j), ELT(start) );
+ }
+ }
+ POSTFIX;
+}
+
+static void TAG(render_quads)( struct gl_context *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ GLuint j;
+ LOCAL_VARS;
+ (void) flags;
+
+ INIT(GL_QUADS);
+ if (NEED_EDGEFLAG_SETUP) {
+ for (j=start+3; j<count; j+=4) {
+ /* Use user-specified edgeflags for quads.
+ */
+ RESET_STIPPLE;
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
+ !ctx->Const.QuadsFollowProvokingVertexConvention)
+ RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) );
+ else
+ RENDER_QUAD( ELT(j-2), ELT(j-1), ELT(j), ELT(j-3) );
+ }
+ } else {
+ for (j=start+3; j<count; j+=4) {
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
+ !ctx->Const.QuadsFollowProvokingVertexConvention)
+ RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) );
+ else
+ RENDER_QUAD( ELT(j-2), ELT(j-1), ELT(j), ELT(j-3) );
+ }
+ }
+ POSTFIX;
+}
+
+static void TAG(render_quad_strip)( struct gl_context *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ GLuint j;
+ LOCAL_VARS;
+ (void) flags;
+
+ INIT(GL_QUAD_STRIP);
+ if (NEED_EDGEFLAG_SETUP) {
+ for (j=start+3;j<count;j+=2) {
+ /* All edges are boundary. Set edgeflags to 1, draw the
+ * quad, and restore them to the original values.
+ */
+ GLboolean ef3 = EDGEFLAG_GET( ELT(j-3) );
+ GLboolean ef2 = EDGEFLAG_GET( ELT(j-2) );
+ GLboolean ef1 = EDGEFLAG_GET( ELT(j-1) );
+ GLboolean ef = EDGEFLAG_GET( ELT(j) );
+ if (TEST_PRIM_BEGIN(flags)) {
+ RESET_STIPPLE;
+ }
+ EDGEFLAG_SET( ELT(j-3), GL_TRUE );
+ EDGEFLAG_SET( ELT(j-2), GL_TRUE );
+ EDGEFLAG_SET( ELT(j-1), GL_TRUE );
+ EDGEFLAG_SET( ELT(j), GL_TRUE );
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
+ !ctx->Const.QuadsFollowProvokingVertexConvention)
+ RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) );
+ else
+ RENDER_QUAD( ELT(j-2), ELT(j), ELT(j-1), ELT(j-3) );
+ EDGEFLAG_SET( ELT(j-3), ef3 );
+ EDGEFLAG_SET( ELT(j-2), ef2 );
+ EDGEFLAG_SET( ELT(j-1), ef1 );
+ EDGEFLAG_SET( ELT(j), ef );
+ }
+ } else {
+ for (j=start+3;j<count;j+=2) {
+ if (ctx->Light.ProvokingVertex == GL_LAST_VERTEX_CONVENTION_EXT ||
+ !ctx->Const.QuadsFollowProvokingVertexConvention)
+ RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) );
+ else
+ RENDER_QUAD( ELT(j-2), ELT(j), ELT(j-1), ELT(j-3) );
+ }
+ }
+ POSTFIX;
+}
+
+static void TAG(render_noop)( struct gl_context *ctx,
+ GLuint start,
+ GLuint count,
+ GLuint flags )
+{
+ (void)(ctx && start && count && flags);
+}
+
+RENDER_TAB_QUALIFIER void (*TAG(render_tab)[GL_POLYGON+2])(struct gl_context *,
+ GLuint,
+ GLuint,
+ GLuint) =
+{
+ TAG(render_points),
+ TAG(render_lines),
+ TAG(render_line_loop),
+ TAG(render_line_strip),
+ TAG(render_triangles),
+ TAG(render_tri_strip),
+ TAG(render_tri_fan),
+ TAG(render_quads),
+ TAG(render_quad_strip),
+ TAG(render_poly),
+ TAG(render_noop),
+};
+
+
+
+#ifndef PRESERVE_VB_DEFS
+#undef RENDER_TRI
+#undef RENDER_QUAD
+#undef RENDER_LINE
+#undef RENDER_POINTS
+#undef LOCAL_VARS
+#undef INIT
+#undef POSTFIX
+#undef RESET_STIPPLE
+#undef DBG
+#undef ELT
+#undef RENDER_TAB_QUALIFIER
+#endif
+
+#ifndef PRESERVE_TAG
+#undef TAG
+#endif
+
+#undef PRESERVE_VB_DEFS
+#undef PRESERVE_TAG
diff --git a/mesalib/src/mesa/tnl/t_vb_texgen.c b/mesalib/src/mesa/tnl/t_vb_texgen.c index 950e0f54e..228808461 100644 --- a/mesalib/src/mesa/tnl/t_vb_texgen.c +++ b/mesalib/src/mesa/tnl/t_vb_texgen.c @@ -1,609 +1,609 @@ -/* - * Mesa 3-D graphics library - * Version: 6.5 - * - * Copyright (C) 1999-2006 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: - * Brian Paul - * Keith Whitwell <keith@tungstengraphics.com> - */ - -/* - * Regarding GL_NV_texgen_reflection: - * - * Portions of this software may use or implement intellectual - * property owned and licensed by NVIDIA Corporation. NVIDIA disclaims - * any and all warranties with respect to such intellectual property, - * including any use thereof or modifications thereto. - */ - -#include "main/glheader.h" -#include "main/colormac.h" -#include "main/macros.h" -#include "main/imports.h" -#include "main/mtypes.h" - -#include "math/m_xform.h" - -#include "t_context.h" -#include "t_pipeline.h" - - -/*********************************************************************** - * Automatic texture coordinate generation (texgen) code. - */ - - -struct texgen_stage_data; - -typedef void (*texgen_func)( GLcontext *ctx, - struct texgen_stage_data *store, - GLuint unit); - - -struct texgen_stage_data { - - /* Per-texunit derived state. - */ - GLuint TexgenSize[MAX_TEXTURE_COORD_UNITS]; - texgen_func TexgenFunc[MAX_TEXTURE_COORD_UNITS]; - - /* Temporary values used in texgen. - */ - GLfloat (*tmp_f)[3]; - GLfloat *tmp_m; - - /* Buffered outputs of the stage. - */ - GLvector4f texcoord[MAX_TEXTURE_COORD_UNITS]; -}; - - -#define TEXGEN_STAGE_DATA(stage) ((struct texgen_stage_data *)stage->privatePtr) - - - -static GLuint all_bits[5] = { - 0, - VEC_SIZE_1, - VEC_SIZE_2, - VEC_SIZE_3, - VEC_SIZE_4, -}; - -#define VEC_SIZE_FLAGS (VEC_SIZE_1|VEC_SIZE_2|VEC_SIZE_3|VEC_SIZE_4) - -#define TEXGEN_NEED_M (TEXGEN_SPHERE_MAP) -#define TEXGEN_NEED_F (TEXGEN_SPHERE_MAP | \ - TEXGEN_REFLECTION_MAP_NV) - - - -static void build_m3( GLfloat f[][3], GLfloat m[], - const GLvector4f *normal, - const GLvector4f *eye ) -{ - GLuint stride = eye->stride; - GLfloat *coord = (GLfloat *)eye->start; - GLuint count = eye->count; - const GLfloat *norm = normal->start; - GLuint i; - - for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(norm,normal->stride)) { - GLfloat u[3], two_nu, fx, fy, fz; - COPY_3V( u, coord ); - NORMALIZE_3FV( u ); - two_nu = 2.0F * DOT3(norm,u); - fx = f[i][0] = u[0] - norm[0] * two_nu; - fy = f[i][1] = u[1] - norm[1] * two_nu; - fz = f[i][2] = u[2] - norm[2] * two_nu; - m[i] = fx * fx + fy * fy + (fz + 1.0F) * (fz + 1.0F); - if (m[i] != 0.0F) { - m[i] = 0.5F * _mesa_inv_sqrtf(m[i]); - } - } -} - - - -static void build_m2( GLfloat f[][3], GLfloat m[], - const GLvector4f *normal, - const GLvector4f *eye ) -{ - GLuint stride = eye->stride; - GLfloat *coord = eye->start; - GLuint count = eye->count; - - GLfloat *norm = normal->start; - GLuint i; - - for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(norm,normal->stride)) { - GLfloat u[3], two_nu, fx, fy, fz; - COPY_2V( u, coord ); - u[2] = 0; - NORMALIZE_3FV( u ); - two_nu = 2.0F * DOT3(norm,u); - fx = f[i][0] = u[0] - norm[0] * two_nu; - fy = f[i][1] = u[1] - norm[1] * two_nu; - fz = f[i][2] = u[2] - norm[2] * two_nu; - m[i] = fx * fx + fy * fy + (fz + 1.0F) * (fz + 1.0F); - if (m[i] != 0.0F) { - m[i] = 0.5F * _mesa_inv_sqrtf(m[i]); - } - } -} - - - -typedef void (*build_m_func)( GLfloat f[][3], - GLfloat m[], - const GLvector4f *normal, - const GLvector4f *eye ); - - -static build_m_func build_m_tab[5] = { - NULL, - NULL, - build_m2, - build_m3, - build_m3 -}; - - -/* This is unusual in that we respect the stride of the output vector - * (f). This allows us to pass in either a texcoord vector4f, or a - * temporary vector3f. - */ -static void build_f3( GLfloat *f, - GLuint fstride, - const GLvector4f *normal, - const GLvector4f *eye ) -{ - GLuint stride = eye->stride; - GLfloat *coord = eye->start; - GLuint count = eye->count; - - GLfloat *norm = normal->start; - GLuint i; - - for (i=0;i<count;i++) { - GLfloat u[3], two_nu; - COPY_3V( u, coord ); - NORMALIZE_3FV( u ); - two_nu = 2.0F * DOT3(norm,u); - f[0] = u[0] - norm[0] * two_nu; - f[1] = u[1] - norm[1] * two_nu; - f[2] = u[2] - norm[2] * two_nu; - STRIDE_F(coord,stride); - STRIDE_F(f,fstride); - STRIDE_F(norm, normal->stride); - } -} - - -static void build_f2( GLfloat *f, - GLuint fstride, - const GLvector4f *normal, - const GLvector4f *eye ) -{ - GLuint stride = eye->stride; - GLfloat *coord = eye->start; - GLuint count = eye->count; - GLfloat *norm = normal->start; - GLuint i; - - for (i=0;i<count;i++) { - - GLfloat u[3], two_nu; - COPY_2V( u, coord ); - u[2] = 0; - NORMALIZE_3FV( u ); - two_nu = 2.0F * DOT3(norm,u); - f[0] = u[0] - norm[0] * two_nu; - f[1] = u[1] - norm[1] * two_nu; - f[2] = u[2] - norm[2] * two_nu; - - STRIDE_F(coord,stride); - STRIDE_F(f,fstride); - STRIDE_F(norm, normal->stride); - } -} - -typedef void (*build_f_func)( GLfloat *f, - GLuint fstride, - const GLvector4f *normal_vec, - const GLvector4f *eye ); - - - -/* Just treat 4-vectors as 3-vectors. - */ -static build_f_func build_f_tab[5] = { - NULL, - NULL, - build_f2, - build_f3, - build_f3 -}; - - - -/* Special case texgen functions. - */ -static void texgen_reflection_map_nv( GLcontext *ctx, - struct texgen_stage_data *store, - GLuint unit ) -{ - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; - GLvector4f *in = VB->AttribPtr[VERT_ATTRIB_TEX0 + unit]; - GLvector4f *out = &store->texcoord[unit]; - - build_f_tab[VB->EyePtr->size]( out->start, - out->stride, - VB->AttribPtr[_TNL_ATTRIB_NORMAL], - VB->EyePtr ); - - out->flags |= (in->flags & VEC_SIZE_FLAGS) | VEC_SIZE_3; - out->count = VB->Count; - out->size = MAX2(in->size, 3); - if (in->size == 4) - _mesa_copy_tab[0x8]( out, in ); -} - - - -static void texgen_normal_map_nv( GLcontext *ctx, - struct texgen_stage_data *store, - GLuint unit ) -{ - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; - GLvector4f *in = VB->AttribPtr[VERT_ATTRIB_TEX0 + unit]; - GLvector4f *out = &store->texcoord[unit]; - GLvector4f *normal = VB->AttribPtr[_TNL_ATTRIB_NORMAL]; - GLfloat (*texcoord)[4] = (GLfloat (*)[4])out->start; - GLuint count = VB->Count; - GLuint i; - const GLfloat *norm = normal->start; - - for (i=0;i<count;i++, STRIDE_F(norm, normal->stride)) { - texcoord[i][0] = norm[0]; - texcoord[i][1] = norm[1]; - texcoord[i][2] = norm[2]; - } - - - out->flags |= (in->flags & VEC_SIZE_FLAGS) | VEC_SIZE_3; - out->count = count; - out->size = MAX2(in->size, 3); - if (in->size == 4) - _mesa_copy_tab[0x8]( out, in ); -} - - -static void texgen_sphere_map( GLcontext *ctx, - struct texgen_stage_data *store, - GLuint unit ) -{ - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; - GLvector4f *in = VB->AttribPtr[VERT_ATTRIB_TEX0 + unit]; - GLvector4f *out = &store->texcoord[unit]; - GLfloat (*texcoord)[4] = (GLfloat (*)[4]) out->start; - GLuint count = VB->Count; - GLuint i; - GLfloat (*f)[3] = store->tmp_f; - GLfloat *m = store->tmp_m; - - (build_m_tab[VB->EyePtr->size])( store->tmp_f, - store->tmp_m, - VB->AttribPtr[_TNL_ATTRIB_NORMAL], - VB->EyePtr ); - - out->size = MAX2(in->size,2); - - for (i=0;i<count;i++) { - texcoord[i][0] = f[i][0] * m[i] + 0.5F; - texcoord[i][1] = f[i][1] * m[i] + 0.5F; - } - - out->count = count; - out->flags |= (in->flags & VEC_SIZE_FLAGS) | VEC_SIZE_2; - if (in->size > 2) - _mesa_copy_tab[all_bits[in->size] & ~0x3]( out, in ); -} - - - -static void texgen( GLcontext *ctx, - struct texgen_stage_data *store, - GLuint unit ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - GLvector4f *in = VB->AttribPtr[VERT_ATTRIB_TEX0 + unit]; - GLvector4f *out = &store->texcoord[unit]; - const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; - const GLvector4f *obj = VB->AttribPtr[_TNL_ATTRIB_POS]; - const GLvector4f *eye = VB->EyePtr; - const GLvector4f *normal = VB->AttribPtr[_TNL_ATTRIB_NORMAL]; - const GLfloat *m = store->tmp_m; - const GLuint count = VB->Count; - GLfloat (*texcoord)[4] = (GLfloat (*)[4])out->data; - GLfloat (*f)[3] = store->tmp_f; - GLuint copy; - - if (texUnit->_GenFlags & TEXGEN_NEED_M) { - build_m_tab[eye->size]( store->tmp_f, store->tmp_m, normal, eye ); - } else if (texUnit->_GenFlags & TEXGEN_NEED_F) { - build_f_tab[eye->size]( (GLfloat *)store->tmp_f, 3, normal, eye ); - } - - - out->size = MAX2(in->size, store->TexgenSize[unit]); - out->flags |= (in->flags & VEC_SIZE_FLAGS) | texUnit->TexGenEnabled; - out->count = count; - - copy = (all_bits[in->size] & ~texUnit->TexGenEnabled); - if (copy) - _mesa_copy_tab[copy]( out, in ); - - if (texUnit->TexGenEnabled & S_BIT) { - GLuint i; - switch (texUnit->GenS.Mode) { - case GL_OBJECT_LINEAR: - _mesa_dotprod_tab[obj->size]( (GLfloat *)out->data, - sizeof(out->data[0]), obj, - texUnit->GenS.ObjectPlane ); - break; - case GL_EYE_LINEAR: - _mesa_dotprod_tab[eye->size]( (GLfloat *)out->data, - sizeof(out->data[0]), eye, - texUnit->GenS.EyePlane ); - break; - case GL_SPHERE_MAP: - for (i = 0; i < count; i++) - texcoord[i][0] = f[i][0] * m[i] + 0.5F; - break; - case GL_REFLECTION_MAP_NV: - for (i=0;i<count;i++) - texcoord[i][0] = f[i][0]; - break; - case GL_NORMAL_MAP_NV: { - const GLfloat *norm = normal->start; - for (i=0;i<count;i++, STRIDE_F(norm, normal->stride)) { - texcoord[i][0] = norm[0]; - } - break; - } - default: - _mesa_problem(ctx, "Bad S texgen"); - } - } - - if (texUnit->TexGenEnabled & T_BIT) { - GLuint i; - switch (texUnit->GenT.Mode) { - case GL_OBJECT_LINEAR: - _mesa_dotprod_tab[obj->size]( &(out->data[0][1]), - sizeof(out->data[0]), obj, - texUnit->GenT.ObjectPlane ); - break; - case GL_EYE_LINEAR: - _mesa_dotprod_tab[eye->size]( &(out->data[0][1]), - sizeof(out->data[0]), eye, - texUnit->GenT.EyePlane ); - break; - case GL_SPHERE_MAP: - for (i = 0; i < count; i++) - texcoord[i][1] = f[i][1] * m[i] + 0.5F; - break; - case GL_REFLECTION_MAP_NV: - for (i=0;i<count;i++) - texcoord[i][1] = f[i][1]; - break; - case GL_NORMAL_MAP_NV: { - const GLfloat *norm = normal->start; - for (i=0;i<count;i++, STRIDE_F(norm, normal->stride)) { - texcoord[i][1] = norm[1]; - } - break; - } - default: - _mesa_problem(ctx, "Bad T texgen"); - } - } - - if (texUnit->TexGenEnabled & R_BIT) { - GLuint i; - switch (texUnit->GenR.Mode) { - case GL_OBJECT_LINEAR: - _mesa_dotprod_tab[obj->size]( &(out->data[0][2]), - sizeof(out->data[0]), obj, - texUnit->GenR.ObjectPlane ); - break; - case GL_EYE_LINEAR: - _mesa_dotprod_tab[eye->size]( &(out->data[0][2]), - sizeof(out->data[0]), eye, - texUnit->GenR.EyePlane ); - break; - case GL_REFLECTION_MAP_NV: - for (i=0;i<count;i++) - texcoord[i][2] = f[i][2]; - break; - case GL_NORMAL_MAP_NV: { - const GLfloat *norm = normal->start; - for (i=0;i<count;i++,STRIDE_F(norm, normal->stride)) { - texcoord[i][2] = norm[2]; - } - break; - } - default: - _mesa_problem(ctx, "Bad R texgen"); - } - } - - if (texUnit->TexGenEnabled & Q_BIT) { - switch (texUnit->GenQ.Mode) { - case GL_OBJECT_LINEAR: - _mesa_dotprod_tab[obj->size]( &(out->data[0][3]), - sizeof(out->data[0]), obj, - texUnit->GenQ.ObjectPlane ); - break; - case GL_EYE_LINEAR: - _mesa_dotprod_tab[eye->size]( &(out->data[0][3]), - sizeof(out->data[0]), eye, - texUnit->GenQ.EyePlane ); - break; - default: - _mesa_problem(ctx, "Bad Q texgen"); - } - } -} - - - - -static GLboolean run_texgen_stage( GLcontext *ctx, - struct tnl_pipeline_stage *stage ) -{ - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; - struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage); - GLuint i; - - if (!ctx->Texture._TexGenEnabled || ctx->VertexProgram._Current) - return GL_TRUE; - - for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) { - struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i]; - - if (texUnit->TexGenEnabled) { - - store->TexgenFunc[i]( ctx, store, i ); - - VB->AttribPtr[VERT_ATTRIB_TEX0 + i] = &store->texcoord[i]; - } - } - - return GL_TRUE; -} - - -static void validate_texgen_stage( GLcontext *ctx, - struct tnl_pipeline_stage *stage ) -{ - struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage); - GLuint i; - - if (!ctx->Texture._TexGenEnabled || ctx->VertexProgram._Current) - return; - - for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) { - struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i]; - - if (texUnit->TexGenEnabled) { - GLuint sz; - - if (texUnit->TexGenEnabled & Q_BIT) - sz = 4; - else if (texUnit->TexGenEnabled & R_BIT) - sz = 3; - else if (texUnit->TexGenEnabled & T_BIT) - sz = 2; - else - sz = 1; - - store->TexgenSize[i] = sz; - store->TexgenFunc[i] = texgen; /* general solution */ - - /* look for special texgen cases */ - if (texUnit->TexGenEnabled == (S_BIT|T_BIT|R_BIT)) { - if (texUnit->_GenFlags == TEXGEN_REFLECTION_MAP_NV) { - store->TexgenFunc[i] = texgen_reflection_map_nv; - } - else if (texUnit->_GenFlags == TEXGEN_NORMAL_MAP_NV) { - store->TexgenFunc[i] = texgen_normal_map_nv; - } - } - else if (texUnit->TexGenEnabled == (S_BIT|T_BIT) && - texUnit->_GenFlags == TEXGEN_SPHERE_MAP) { - store->TexgenFunc[i] = texgen_sphere_map; - } - } - } -} - - - - - -/* Called the first time stage->run() is invoked. - */ -static GLboolean alloc_texgen_data( GLcontext *ctx, - struct tnl_pipeline_stage *stage ) -{ - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; - struct texgen_stage_data *store; - GLuint i; - - stage->privatePtr = CALLOC(sizeof(*store)); - store = TEXGEN_STAGE_DATA(stage); - if (!store) - return GL_FALSE; - - for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) - _mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 ); - - store->tmp_f = (GLfloat (*)[3]) MALLOC(VB->Size * sizeof(GLfloat) * 3); - store->tmp_m = (GLfloat *) MALLOC(VB->Size * sizeof(GLfloat)); - - return GL_TRUE; -} - - -static void free_texgen_data( struct tnl_pipeline_stage *stage ) - -{ - struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage); - GLuint i; - - if (store) { - for (i = 0 ; i < MAX_TEXTURE_COORD_UNITS ; i++) - if (store->texcoord[i].data) - _mesa_vector4f_free( &store->texcoord[i] ); - - - if (store->tmp_f) FREE( store->tmp_f ); - if (store->tmp_m) FREE( store->tmp_m ); - FREE( store ); - stage->privatePtr = NULL; - } -} - - - -const struct tnl_pipeline_stage _tnl_texgen_stage = -{ - "texgen", /* name */ - NULL, /* private data */ - alloc_texgen_data, /* destructor */ - free_texgen_data, /* destructor */ - validate_texgen_stage, /* check */ - run_texgen_stage /* run -- initially set to alloc data */ -}; +/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 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:
+ * Brian Paul
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+/*
+ * Regarding GL_NV_texgen_reflection:
+ *
+ * Portions of this software may use or implement intellectual
+ * property owned and licensed by NVIDIA Corporation. NVIDIA disclaims
+ * any and all warranties with respect to such intellectual property,
+ * including any use thereof or modifications thereto.
+ */
+
+#include "main/glheader.h"
+#include "main/colormac.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+
+#include "math/m_xform.h"
+
+#include "t_context.h"
+#include "t_pipeline.h"
+
+
+/***********************************************************************
+ * Automatic texture coordinate generation (texgen) code.
+ */
+
+
+struct texgen_stage_data;
+
+typedef void (*texgen_func)( struct gl_context *ctx,
+ struct texgen_stage_data *store,
+ GLuint unit);
+
+
+struct texgen_stage_data {
+
+ /* Per-texunit derived state.
+ */
+ GLuint TexgenSize[MAX_TEXTURE_COORD_UNITS];
+ texgen_func TexgenFunc[MAX_TEXTURE_COORD_UNITS];
+
+ /* Temporary values used in texgen.
+ */
+ GLfloat (*tmp_f)[3];
+ GLfloat *tmp_m;
+
+ /* Buffered outputs of the stage.
+ */
+ GLvector4f texcoord[MAX_TEXTURE_COORD_UNITS];
+};
+
+
+#define TEXGEN_STAGE_DATA(stage) ((struct texgen_stage_data *)stage->privatePtr)
+
+
+
+static GLuint all_bits[5] = {
+ 0,
+ VEC_SIZE_1,
+ VEC_SIZE_2,
+ VEC_SIZE_3,
+ VEC_SIZE_4,
+};
+
+#define VEC_SIZE_FLAGS (VEC_SIZE_1|VEC_SIZE_2|VEC_SIZE_3|VEC_SIZE_4)
+
+#define TEXGEN_NEED_M (TEXGEN_SPHERE_MAP)
+#define TEXGEN_NEED_F (TEXGEN_SPHERE_MAP | \
+ TEXGEN_REFLECTION_MAP_NV)
+
+
+
+static void build_m3( GLfloat f[][3], GLfloat m[],
+ const GLvector4f *normal,
+ const GLvector4f *eye )
+{
+ GLuint stride = eye->stride;
+ GLfloat *coord = (GLfloat *)eye->start;
+ GLuint count = eye->count;
+ const GLfloat *norm = normal->start;
+ GLuint i;
+
+ for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(norm,normal->stride)) {
+ GLfloat u[3], two_nu, fx, fy, fz;
+ COPY_3V( u, coord );
+ NORMALIZE_3FV( u );
+ two_nu = 2.0F * DOT3(norm,u);
+ fx = f[i][0] = u[0] - norm[0] * two_nu;
+ fy = f[i][1] = u[1] - norm[1] * two_nu;
+ fz = f[i][2] = u[2] - norm[2] * two_nu;
+ m[i] = fx * fx + fy * fy + (fz + 1.0F) * (fz + 1.0F);
+ if (m[i] != 0.0F) {
+ m[i] = 0.5F * _mesa_inv_sqrtf(m[i]);
+ }
+ }
+}
+
+
+
+static void build_m2( GLfloat f[][3], GLfloat m[],
+ const GLvector4f *normal,
+ const GLvector4f *eye )
+{
+ GLuint stride = eye->stride;
+ GLfloat *coord = eye->start;
+ GLuint count = eye->count;
+
+ GLfloat *norm = normal->start;
+ GLuint i;
+
+ for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(norm,normal->stride)) {
+ GLfloat u[3], two_nu, fx, fy, fz;
+ COPY_2V( u, coord );
+ u[2] = 0;
+ NORMALIZE_3FV( u );
+ two_nu = 2.0F * DOT3(norm,u);
+ fx = f[i][0] = u[0] - norm[0] * two_nu;
+ fy = f[i][1] = u[1] - norm[1] * two_nu;
+ fz = f[i][2] = u[2] - norm[2] * two_nu;
+ m[i] = fx * fx + fy * fy + (fz + 1.0F) * (fz + 1.0F);
+ if (m[i] != 0.0F) {
+ m[i] = 0.5F * _mesa_inv_sqrtf(m[i]);
+ }
+ }
+}
+
+
+
+typedef void (*build_m_func)( GLfloat f[][3],
+ GLfloat m[],
+ const GLvector4f *normal,
+ const GLvector4f *eye );
+
+
+static build_m_func build_m_tab[5] = {
+ NULL,
+ NULL,
+ build_m2,
+ build_m3,
+ build_m3
+};
+
+
+/* This is unusual in that we respect the stride of the output vector
+ * (f). This allows us to pass in either a texcoord vector4f, or a
+ * temporary vector3f.
+ */
+static void build_f3( GLfloat *f,
+ GLuint fstride,
+ const GLvector4f *normal,
+ const GLvector4f *eye )
+{
+ GLuint stride = eye->stride;
+ GLfloat *coord = eye->start;
+ GLuint count = eye->count;
+
+ GLfloat *norm = normal->start;
+ GLuint i;
+
+ for (i=0;i<count;i++) {
+ GLfloat u[3], two_nu;
+ COPY_3V( u, coord );
+ NORMALIZE_3FV( u );
+ two_nu = 2.0F * DOT3(norm,u);
+ f[0] = u[0] - norm[0] * two_nu;
+ f[1] = u[1] - norm[1] * two_nu;
+ f[2] = u[2] - norm[2] * two_nu;
+ STRIDE_F(coord,stride);
+ STRIDE_F(f,fstride);
+ STRIDE_F(norm, normal->stride);
+ }
+}
+
+
+static void build_f2( GLfloat *f,
+ GLuint fstride,
+ const GLvector4f *normal,
+ const GLvector4f *eye )
+{
+ GLuint stride = eye->stride;
+ GLfloat *coord = eye->start;
+ GLuint count = eye->count;
+ GLfloat *norm = normal->start;
+ GLuint i;
+
+ for (i=0;i<count;i++) {
+
+ GLfloat u[3], two_nu;
+ COPY_2V( u, coord );
+ u[2] = 0;
+ NORMALIZE_3FV( u );
+ two_nu = 2.0F * DOT3(norm,u);
+ f[0] = u[0] - norm[0] * two_nu;
+ f[1] = u[1] - norm[1] * two_nu;
+ f[2] = u[2] - norm[2] * two_nu;
+
+ STRIDE_F(coord,stride);
+ STRIDE_F(f,fstride);
+ STRIDE_F(norm, normal->stride);
+ }
+}
+
+typedef void (*build_f_func)( GLfloat *f,
+ GLuint fstride,
+ const GLvector4f *normal_vec,
+ const GLvector4f *eye );
+
+
+
+/* Just treat 4-vectors as 3-vectors.
+ */
+static build_f_func build_f_tab[5] = {
+ NULL,
+ NULL,
+ build_f2,
+ build_f3,
+ build_f3
+};
+
+
+
+/* Special case texgen functions.
+ */
+static void texgen_reflection_map_nv( struct gl_context *ctx,
+ struct texgen_stage_data *store,
+ GLuint unit )
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ GLvector4f *in = VB->AttribPtr[VERT_ATTRIB_TEX0 + unit];
+ GLvector4f *out = &store->texcoord[unit];
+
+ build_f_tab[VB->EyePtr->size]( out->start,
+ out->stride,
+ VB->AttribPtr[_TNL_ATTRIB_NORMAL],
+ VB->EyePtr );
+
+ out->flags |= (in->flags & VEC_SIZE_FLAGS) | VEC_SIZE_3;
+ out->count = VB->Count;
+ out->size = MAX2(in->size, 3);
+ if (in->size == 4)
+ _mesa_copy_tab[0x8]( out, in );
+}
+
+
+
+static void texgen_normal_map_nv( struct gl_context *ctx,
+ struct texgen_stage_data *store,
+ GLuint unit )
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ GLvector4f *in = VB->AttribPtr[VERT_ATTRIB_TEX0 + unit];
+ GLvector4f *out = &store->texcoord[unit];
+ GLvector4f *normal = VB->AttribPtr[_TNL_ATTRIB_NORMAL];
+ GLfloat (*texcoord)[4] = (GLfloat (*)[4])out->start;
+ GLuint count = VB->Count;
+ GLuint i;
+ const GLfloat *norm = normal->start;
+
+ for (i=0;i<count;i++, STRIDE_F(norm, normal->stride)) {
+ texcoord[i][0] = norm[0];
+ texcoord[i][1] = norm[1];
+ texcoord[i][2] = norm[2];
+ }
+
+
+ out->flags |= (in->flags & VEC_SIZE_FLAGS) | VEC_SIZE_3;
+ out->count = count;
+ out->size = MAX2(in->size, 3);
+ if (in->size == 4)
+ _mesa_copy_tab[0x8]( out, in );
+}
+
+
+static void texgen_sphere_map( struct gl_context *ctx,
+ struct texgen_stage_data *store,
+ GLuint unit )
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ GLvector4f *in = VB->AttribPtr[VERT_ATTRIB_TEX0 + unit];
+ GLvector4f *out = &store->texcoord[unit];
+ GLfloat (*texcoord)[4] = (GLfloat (*)[4]) out->start;
+ GLuint count = VB->Count;
+ GLuint i;
+ GLfloat (*f)[3] = store->tmp_f;
+ GLfloat *m = store->tmp_m;
+
+ (build_m_tab[VB->EyePtr->size])( store->tmp_f,
+ store->tmp_m,
+ VB->AttribPtr[_TNL_ATTRIB_NORMAL],
+ VB->EyePtr );
+
+ out->size = MAX2(in->size,2);
+
+ for (i=0;i<count;i++) {
+ texcoord[i][0] = f[i][0] * m[i] + 0.5F;
+ texcoord[i][1] = f[i][1] * m[i] + 0.5F;
+ }
+
+ out->count = count;
+ out->flags |= (in->flags & VEC_SIZE_FLAGS) | VEC_SIZE_2;
+ if (in->size > 2)
+ _mesa_copy_tab[all_bits[in->size] & ~0x3]( out, in );
+}
+
+
+
+static void texgen( struct gl_context *ctx,
+ struct texgen_stage_data *store,
+ GLuint unit )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ GLvector4f *in = VB->AttribPtr[VERT_ATTRIB_TEX0 + unit];
+ GLvector4f *out = &store->texcoord[unit];
+ const struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit];
+ const GLvector4f *obj = VB->AttribPtr[_TNL_ATTRIB_POS];
+ const GLvector4f *eye = VB->EyePtr;
+ const GLvector4f *normal = VB->AttribPtr[_TNL_ATTRIB_NORMAL];
+ const GLfloat *m = store->tmp_m;
+ const GLuint count = VB->Count;
+ GLfloat (*texcoord)[4] = (GLfloat (*)[4])out->data;
+ GLfloat (*f)[3] = store->tmp_f;
+ GLuint copy;
+
+ if (texUnit->_GenFlags & TEXGEN_NEED_M) {
+ build_m_tab[eye->size]( store->tmp_f, store->tmp_m, normal, eye );
+ } else if (texUnit->_GenFlags & TEXGEN_NEED_F) {
+ build_f_tab[eye->size]( (GLfloat *)store->tmp_f, 3, normal, eye );
+ }
+
+
+ out->size = MAX2(in->size, store->TexgenSize[unit]);
+ out->flags |= (in->flags & VEC_SIZE_FLAGS) | texUnit->TexGenEnabled;
+ out->count = count;
+
+ copy = (all_bits[in->size] & ~texUnit->TexGenEnabled);
+ if (copy)
+ _mesa_copy_tab[copy]( out, in );
+
+ if (texUnit->TexGenEnabled & S_BIT) {
+ GLuint i;
+ switch (texUnit->GenS.Mode) {
+ case GL_OBJECT_LINEAR:
+ _mesa_dotprod_tab[obj->size]( (GLfloat *)out->data,
+ sizeof(out->data[0]), obj,
+ texUnit->GenS.ObjectPlane );
+ break;
+ case GL_EYE_LINEAR:
+ _mesa_dotprod_tab[eye->size]( (GLfloat *)out->data,
+ sizeof(out->data[0]), eye,
+ texUnit->GenS.EyePlane );
+ break;
+ case GL_SPHERE_MAP:
+ for (i = 0; i < count; i++)
+ texcoord[i][0] = f[i][0] * m[i] + 0.5F;
+ break;
+ case GL_REFLECTION_MAP_NV:
+ for (i=0;i<count;i++)
+ texcoord[i][0] = f[i][0];
+ break;
+ case GL_NORMAL_MAP_NV: {
+ const GLfloat *norm = normal->start;
+ for (i=0;i<count;i++, STRIDE_F(norm, normal->stride)) {
+ texcoord[i][0] = norm[0];
+ }
+ break;
+ }
+ default:
+ _mesa_problem(ctx, "Bad S texgen");
+ }
+ }
+
+ if (texUnit->TexGenEnabled & T_BIT) {
+ GLuint i;
+ switch (texUnit->GenT.Mode) {
+ case GL_OBJECT_LINEAR:
+ _mesa_dotprod_tab[obj->size]( &(out->data[0][1]),
+ sizeof(out->data[0]), obj,
+ texUnit->GenT.ObjectPlane );
+ break;
+ case GL_EYE_LINEAR:
+ _mesa_dotprod_tab[eye->size]( &(out->data[0][1]),
+ sizeof(out->data[0]), eye,
+ texUnit->GenT.EyePlane );
+ break;
+ case GL_SPHERE_MAP:
+ for (i = 0; i < count; i++)
+ texcoord[i][1] = f[i][1] * m[i] + 0.5F;
+ break;
+ case GL_REFLECTION_MAP_NV:
+ for (i=0;i<count;i++)
+ texcoord[i][1] = f[i][1];
+ break;
+ case GL_NORMAL_MAP_NV: {
+ const GLfloat *norm = normal->start;
+ for (i=0;i<count;i++, STRIDE_F(norm, normal->stride)) {
+ texcoord[i][1] = norm[1];
+ }
+ break;
+ }
+ default:
+ _mesa_problem(ctx, "Bad T texgen");
+ }
+ }
+
+ if (texUnit->TexGenEnabled & R_BIT) {
+ GLuint i;
+ switch (texUnit->GenR.Mode) {
+ case GL_OBJECT_LINEAR:
+ _mesa_dotprod_tab[obj->size]( &(out->data[0][2]),
+ sizeof(out->data[0]), obj,
+ texUnit->GenR.ObjectPlane );
+ break;
+ case GL_EYE_LINEAR:
+ _mesa_dotprod_tab[eye->size]( &(out->data[0][2]),
+ sizeof(out->data[0]), eye,
+ texUnit->GenR.EyePlane );
+ break;
+ case GL_REFLECTION_MAP_NV:
+ for (i=0;i<count;i++)
+ texcoord[i][2] = f[i][2];
+ break;
+ case GL_NORMAL_MAP_NV: {
+ const GLfloat *norm = normal->start;
+ for (i=0;i<count;i++,STRIDE_F(norm, normal->stride)) {
+ texcoord[i][2] = norm[2];
+ }
+ break;
+ }
+ default:
+ _mesa_problem(ctx, "Bad R texgen");
+ }
+ }
+
+ if (texUnit->TexGenEnabled & Q_BIT) {
+ switch (texUnit->GenQ.Mode) {
+ case GL_OBJECT_LINEAR:
+ _mesa_dotprod_tab[obj->size]( &(out->data[0][3]),
+ sizeof(out->data[0]), obj,
+ texUnit->GenQ.ObjectPlane );
+ break;
+ case GL_EYE_LINEAR:
+ _mesa_dotprod_tab[eye->size]( &(out->data[0][3]),
+ sizeof(out->data[0]), eye,
+ texUnit->GenQ.EyePlane );
+ break;
+ default:
+ _mesa_problem(ctx, "Bad Q texgen");
+ }
+ }
+}
+
+
+
+
+static GLboolean run_texgen_stage( struct gl_context *ctx,
+ struct tnl_pipeline_stage *stage )
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage);
+ GLuint i;
+
+ if (!ctx->Texture._TexGenEnabled || ctx->VertexProgram._Current)
+ return GL_TRUE;
+
+ for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) {
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
+
+ if (texUnit->TexGenEnabled) {
+
+ store->TexgenFunc[i]( ctx, store, i );
+
+ VB->AttribPtr[VERT_ATTRIB_TEX0 + i] = &store->texcoord[i];
+ }
+ }
+
+ return GL_TRUE;
+}
+
+
+static void validate_texgen_stage( struct gl_context *ctx,
+ struct tnl_pipeline_stage *stage )
+{
+ struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage);
+ GLuint i;
+
+ if (!ctx->Texture._TexGenEnabled || ctx->VertexProgram._Current)
+ return;
+
+ for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) {
+ struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i];
+
+ if (texUnit->TexGenEnabled) {
+ GLuint sz;
+
+ if (texUnit->TexGenEnabled & Q_BIT)
+ sz = 4;
+ else if (texUnit->TexGenEnabled & R_BIT)
+ sz = 3;
+ else if (texUnit->TexGenEnabled & T_BIT)
+ sz = 2;
+ else
+ sz = 1;
+
+ store->TexgenSize[i] = sz;
+ store->TexgenFunc[i] = texgen; /* general solution */
+
+ /* look for special texgen cases */
+ if (texUnit->TexGenEnabled == (S_BIT|T_BIT|R_BIT)) {
+ if (texUnit->_GenFlags == TEXGEN_REFLECTION_MAP_NV) {
+ store->TexgenFunc[i] = texgen_reflection_map_nv;
+ }
+ else if (texUnit->_GenFlags == TEXGEN_NORMAL_MAP_NV) {
+ store->TexgenFunc[i] = texgen_normal_map_nv;
+ }
+ }
+ else if (texUnit->TexGenEnabled == (S_BIT|T_BIT) &&
+ texUnit->_GenFlags == TEXGEN_SPHERE_MAP) {
+ store->TexgenFunc[i] = texgen_sphere_map;
+ }
+ }
+ }
+}
+
+
+
+
+
+/* Called the first time stage->run() is invoked.
+ */
+static GLboolean alloc_texgen_data( struct gl_context *ctx,
+ struct tnl_pipeline_stage *stage )
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ struct texgen_stage_data *store;
+ GLuint i;
+
+ stage->privatePtr = CALLOC(sizeof(*store));
+ store = TEXGEN_STAGE_DATA(stage);
+ if (!store)
+ return GL_FALSE;
+
+ for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
+ _mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 );
+
+ store->tmp_f = (GLfloat (*)[3]) MALLOC(VB->Size * sizeof(GLfloat) * 3);
+ store->tmp_m = (GLfloat *) MALLOC(VB->Size * sizeof(GLfloat));
+
+ return GL_TRUE;
+}
+
+
+static void free_texgen_data( struct tnl_pipeline_stage *stage )
+
+{
+ struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage);
+ GLuint i;
+
+ if (store) {
+ for (i = 0 ; i < MAX_TEXTURE_COORD_UNITS ; i++)
+ if (store->texcoord[i].data)
+ _mesa_vector4f_free( &store->texcoord[i] );
+
+
+ if (store->tmp_f) FREE( store->tmp_f );
+ if (store->tmp_m) FREE( store->tmp_m );
+ FREE( store );
+ stage->privatePtr = NULL;
+ }
+}
+
+
+
+const struct tnl_pipeline_stage _tnl_texgen_stage =
+{
+ "texgen", /* name */
+ NULL, /* private data */
+ alloc_texgen_data, /* destructor */
+ free_texgen_data, /* destructor */
+ validate_texgen_stage, /* check */
+ run_texgen_stage /* run -- initially set to alloc data */
+};
diff --git a/mesalib/src/mesa/tnl/t_vb_texmat.c b/mesalib/src/mesa/tnl/t_vb_texmat.c index 985d137e5..7b30946c8 100644 --- a/mesalib/src/mesa/tnl/t_vb_texmat.c +++ b/mesalib/src/mesa/tnl/t_vb_texmat.c @@ -1,128 +1,128 @@ -/* - * Mesa 3-D graphics library - * Version: 6.5 - * - * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Keith Whitwell <keith@tungstengraphics.com> - */ - - -#include "main/glheader.h" -#include "main/colormac.h" -#include "main/macros.h" -#include "main/imports.h" -#include "main/mtypes.h" - -#include "math/m_xform.h" - -#include "t_context.h" -#include "t_pipeline.h" - -/* Is there any real benefit seperating texmat from texgen? It means - * we need two lots of intermediate storage. Any changes to - * _NEW_TEXTURE will invalidate both sets -- it's only on changes to - * *only* _NEW_TEXTURE_MATRIX that texgen survives but texmat doesn't. - * - * However, the seperation of this code from the complex texgen stuff - * is very appealing. - */ -struct texmat_stage_data { - GLvector4f texcoord[MAX_TEXTURE_COORD_UNITS]; -}; - -#define TEXMAT_STAGE_DATA(stage) ((struct texmat_stage_data *)stage->privatePtr) - - - -static GLboolean run_texmat_stage( GLcontext *ctx, - struct tnl_pipeline_stage *stage ) -{ - struct texmat_stage_data *store = TEXMAT_STAGE_DATA(stage); - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; - GLuint i; - - if (!ctx->Texture._TexMatEnabled || ctx->VertexProgram._Current) - return GL_TRUE; - - /* ENABLE_TEXMAT implies that the texture matrix is not the - * identity, so we don't have to check that here. - */ - for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) { - if (ctx->Texture._TexMatEnabled & ENABLE_TEXMAT(i)) { - (void) TransformRaw( &store->texcoord[i], - ctx->TextureMatrixStack[i].Top, - VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]); - - VB->AttribPtr[VERT_ATTRIB_TEX0+i] = &store->texcoord[i]; - } - } - - return GL_TRUE; -} - - -/* Called the first time stage->run() is invoked. - */ -static GLboolean alloc_texmat_data( GLcontext *ctx, - struct tnl_pipeline_stage *stage ) -{ - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; - struct texmat_stage_data *store; - GLuint i; - - stage->privatePtr = CALLOC(sizeof(*store)); - store = TEXMAT_STAGE_DATA(stage); - if (!store) - return GL_FALSE; - - for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) - _mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 ); - - return GL_TRUE; -} - - -static void free_texmat_data( struct tnl_pipeline_stage *stage ) -{ - struct texmat_stage_data *store = TEXMAT_STAGE_DATA(stage); - GLuint i; - - if (store) { - for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++) - if (store->texcoord[i].data) - _mesa_vector4f_free( &store->texcoord[i] ); - FREE( store ); - stage->privatePtr = NULL; - } -} - - - -const struct tnl_pipeline_stage _tnl_texture_transform_stage = -{ - "texture transform", /* name */ - NULL, /* private data */ - alloc_texmat_data, - free_texmat_data, /* destructor */ - NULL, - run_texmat_stage, -}; +/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "main/glheader.h"
+#include "main/colormac.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+
+#include "math/m_xform.h"
+
+#include "t_context.h"
+#include "t_pipeline.h"
+
+/* Is there any real benefit seperating texmat from texgen? It means
+ * we need two lots of intermediate storage. Any changes to
+ * _NEW_TEXTURE will invalidate both sets -- it's only on changes to
+ * *only* _NEW_TEXTURE_MATRIX that texgen survives but texmat doesn't.
+ *
+ * However, the seperation of this code from the complex texgen stuff
+ * is very appealing.
+ */
+struct texmat_stage_data {
+ GLvector4f texcoord[MAX_TEXTURE_COORD_UNITS];
+};
+
+#define TEXMAT_STAGE_DATA(stage) ((struct texmat_stage_data *)stage->privatePtr)
+
+
+
+static GLboolean run_texmat_stage( struct gl_context *ctx,
+ struct tnl_pipeline_stage *stage )
+{
+ struct texmat_stage_data *store = TEXMAT_STAGE_DATA(stage);
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ GLuint i;
+
+ if (!ctx->Texture._TexMatEnabled || ctx->VertexProgram._Current)
+ return GL_TRUE;
+
+ /* ENABLE_TEXMAT implies that the texture matrix is not the
+ * identity, so we don't have to check that here.
+ */
+ for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++) {
+ if (ctx->Texture._TexMatEnabled & ENABLE_TEXMAT(i)) {
+ (void) TransformRaw( &store->texcoord[i],
+ ctx->TextureMatrixStack[i].Top,
+ VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]);
+
+ VB->AttribPtr[VERT_ATTRIB_TEX0+i] = &store->texcoord[i];
+ }
+ }
+
+ return GL_TRUE;
+}
+
+
+/* Called the first time stage->run() is invoked.
+ */
+static GLboolean alloc_texmat_data( struct gl_context *ctx,
+ struct tnl_pipeline_stage *stage )
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ struct texmat_stage_data *store;
+ GLuint i;
+
+ stage->privatePtr = CALLOC(sizeof(*store));
+ store = TEXMAT_STAGE_DATA(stage);
+ if (!store)
+ return GL_FALSE;
+
+ for (i = 0 ; i < ctx->Const.MaxTextureCoordUnits ; i++)
+ _mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 );
+
+ return GL_TRUE;
+}
+
+
+static void free_texmat_data( struct tnl_pipeline_stage *stage )
+{
+ struct texmat_stage_data *store = TEXMAT_STAGE_DATA(stage);
+ GLuint i;
+
+ if (store) {
+ for (i = 0; i < MAX_TEXTURE_COORD_UNITS; i++)
+ if (store->texcoord[i].data)
+ _mesa_vector4f_free( &store->texcoord[i] );
+ FREE( store );
+ stage->privatePtr = NULL;
+ }
+}
+
+
+
+const struct tnl_pipeline_stage _tnl_texture_transform_stage =
+{
+ "texture transform", /* name */
+ NULL, /* private data */
+ alloc_texmat_data,
+ free_texmat_data, /* destructor */
+ NULL,
+ run_texmat_stage,
+};
diff --git a/mesalib/src/mesa/tnl/t_vb_vertex.c b/mesalib/src/mesa/tnl/t_vb_vertex.c index 453479227..a77959410 100644 --- a/mesalib/src/mesa/tnl/t_vb_vertex.c +++ b/mesalib/src/mesa/tnl/t_vb_vertex.c @@ -1,283 +1,283 @@ -/* - * Mesa 3-D graphics library - * Version: 6.5 - * - * Copyright (C) 1999-2006 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Keith Whitwell <keith@tungstengraphics.com> - */ - - -#include "main/glheader.h" -#include "main/colormac.h" -#include "main/macros.h" -#include "main/imports.h" -#include "main/mtypes.h" - -#include "math/m_xform.h" - -#include "t_context.h" -#include "t_pipeline.h" - - - -struct vertex_stage_data { - GLvector4f eye; - GLvector4f clip; - GLvector4f proj; - GLubyte *clipmask; - GLubyte ormask; - GLubyte andmask; -}; - -#define VERTEX_STAGE_DATA(stage) ((struct vertex_stage_data *)stage->privatePtr) - - - - -/* This function implements cliptesting for user-defined clip planes. - * The clipping of primitives to these planes is implemented in - * t_render_clip.h. - */ -#define USER_CLIPTEST(NAME, SZ) \ -static void NAME( GLcontext *ctx, \ - GLvector4f *clip, \ - GLubyte *clipmask, \ - GLubyte *clipormask, \ - GLubyte *clipandmask ) \ -{ \ - GLuint p; \ - \ - for (p = 0; p < ctx->Const.MaxClipPlanes; p++) \ - if (ctx->Transform.ClipPlanesEnabled & (1 << p)) { \ - GLuint nr, i; \ - const GLfloat a = ctx->Transform._ClipUserPlane[p][0]; \ - const GLfloat b = ctx->Transform._ClipUserPlane[p][1]; \ - const GLfloat c = ctx->Transform._ClipUserPlane[p][2]; \ - const GLfloat d = ctx->Transform._ClipUserPlane[p][3]; \ - GLfloat *coord = (GLfloat *)clip->data; \ - GLuint stride = clip->stride; \ - GLuint count = clip->count; \ - \ - for (nr = 0, i = 0 ; i < count ; i++) { \ - GLfloat dp = coord[0] * a + coord[1] * b; \ - if (SZ > 2) dp += coord[2] * c; \ - if (SZ > 3) dp += coord[3] * d; else dp += d; \ - \ - if (dp < 0) { \ - nr++; \ - clipmask[i] |= CLIP_USER_BIT; \ - } \ - \ - STRIDE_F(coord, stride); \ - } \ - \ - if (nr > 0) { \ - *clipormask |= CLIP_USER_BIT; \ - if (nr == count) { \ - *clipandmask |= CLIP_USER_BIT; \ - return; \ - } \ - } \ - } \ -} - - -USER_CLIPTEST(userclip2, 2) -USER_CLIPTEST(userclip3, 3) -USER_CLIPTEST(userclip4, 4) - -static void (*(usercliptab[5]))( GLcontext *, - GLvector4f *, GLubyte *, - GLubyte *, GLubyte * ) = -{ - NULL, - NULL, - userclip2, - userclip3, - userclip4 -}; - - -void -tnl_clip_prepare(GLcontext *ctx) -{ - /* Neither the x86 nor sparc asm cliptest functions have been updated - * for ARB_depth_clamp, so force the C paths. - */ - if (ctx->Transform.DepthClamp) { - static GLboolean c_funcs_installed = GL_FALSE; - if (!c_funcs_installed) { - init_c_cliptest(); - c_funcs_installed = GL_TRUE; - } - } -} - - - -static GLboolean run_vertex_stage( GLcontext *ctx, - struct tnl_pipeline_stage *stage ) -{ - struct vertex_stage_data *store = (struct vertex_stage_data *)stage->privatePtr; - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - - if (ctx->VertexProgram._Current) - return GL_TRUE; - - tnl_clip_prepare(ctx); - - if (ctx->_NeedEyeCoords) { - /* Separate modelview transformation: - * Use combined ModelProject to avoid some depth artifacts - */ - if (ctx->ModelviewMatrixStack.Top->type == MATRIX_IDENTITY) - VB->EyePtr = VB->AttribPtr[_TNL_ATTRIB_POS]; - else - VB->EyePtr = TransformRaw( &store->eye, - ctx->ModelviewMatrixStack.Top, - VB->AttribPtr[_TNL_ATTRIB_POS]); - } - - VB->ClipPtr = TransformRaw( &store->clip, - &ctx->_ModelProjectMatrix, - VB->AttribPtr[_TNL_ATTRIB_POS] ); - - /* Drivers expect this to be clean to element 4... - */ - switch (VB->ClipPtr->size) { - case 1: - /* impossible */ - case 2: - _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 2 ); - /* fall-through */ - case 3: - _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 3 ); - /* fall-through */ - case 4: - break; - } - - - /* Cliptest and perspective divide. Clip functions must clear - * the clipmask. - */ - store->ormask = 0; - store->andmask = CLIP_FRUSTUM_BITS; - - if (tnl->NeedNdcCoords) { - VB->NdcPtr = - _mesa_clip_tab[VB->ClipPtr->size]( VB->ClipPtr, - &store->proj, - store->clipmask, - &store->ormask, - &store->andmask, - !ctx->Transform.DepthClamp ); - } - else { - VB->NdcPtr = NULL; - _mesa_clip_np_tab[VB->ClipPtr->size]( VB->ClipPtr, - NULL, - store->clipmask, - &store->ormask, - &store->andmask, - !ctx->Transform.DepthClamp ); - } - - if (store->andmask) - return GL_FALSE; - - - /* Test userclip planes. This contributes to VB->ClipMask, so - * is essentially required to be in this stage. - */ - if (ctx->Transform.ClipPlanesEnabled) { - usercliptab[VB->ClipPtr->size]( ctx, - VB->ClipPtr, - store->clipmask, - &store->ormask, - &store->andmask ); - - if (store->andmask) - return GL_FALSE; - } - - VB->ClipAndMask = store->andmask; - VB->ClipOrMask = store->ormask; - VB->ClipMask = store->clipmask; - - return GL_TRUE; -} - - -static GLboolean init_vertex_stage( GLcontext *ctx, - struct tnl_pipeline_stage *stage ) -{ - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; - struct vertex_stage_data *store; - GLuint size = VB->Size; - - stage->privatePtr = CALLOC(sizeof(*store)); - store = VERTEX_STAGE_DATA(stage); - if (!store) - return GL_FALSE; - - _mesa_vector4f_alloc( &store->eye, 0, size, 32 ); - _mesa_vector4f_alloc( &store->clip, 0, size, 32 ); - _mesa_vector4f_alloc( &store->proj, 0, size, 32 ); - - store->clipmask = (GLubyte *) _mesa_align_malloc(sizeof(GLubyte)*size, 32 ); - - if (!store->clipmask || - !store->eye.data || - !store->clip.data || - !store->proj.data) - return GL_FALSE; - - return GL_TRUE; -} - -static void dtr( struct tnl_pipeline_stage *stage ) -{ - struct vertex_stage_data *store = VERTEX_STAGE_DATA(stage); - - if (store) { - _mesa_vector4f_free( &store->eye ); - _mesa_vector4f_free( &store->clip ); - _mesa_vector4f_free( &store->proj ); - _mesa_align_free( store->clipmask ); - FREE(store); - stage->privatePtr = NULL; - stage->run = init_vertex_stage; - } -} - - -const struct tnl_pipeline_stage _tnl_vertex_transform_stage = -{ - "modelview/project/cliptest/divide", - NULL, /* private data */ - init_vertex_stage, - dtr, /* destructor */ - NULL, - run_vertex_stage /* run -- initially set to init */ -}; +/*
+ * Mesa 3-D graphics library
+ * Version: 6.5
+ *
+ * Copyright (C) 1999-2006 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+
+#include "main/glheader.h"
+#include "main/colormac.h"
+#include "main/macros.h"
+#include "main/imports.h"
+#include "main/mtypes.h"
+
+#include "math/m_xform.h"
+
+#include "t_context.h"
+#include "t_pipeline.h"
+
+
+
+struct vertex_stage_data {
+ GLvector4f eye;
+ GLvector4f clip;
+ GLvector4f proj;
+ GLubyte *clipmask;
+ GLubyte ormask;
+ GLubyte andmask;
+};
+
+#define VERTEX_STAGE_DATA(stage) ((struct vertex_stage_data *)stage->privatePtr)
+
+
+
+
+/* This function implements cliptesting for user-defined clip planes.
+ * The clipping of primitives to these planes is implemented in
+ * t_render_clip.h.
+ */
+#define USER_CLIPTEST(NAME, SZ) \
+static void NAME( struct gl_context *ctx, \
+ GLvector4f *clip, \
+ GLubyte *clipmask, \
+ GLubyte *clipormask, \
+ GLubyte *clipandmask ) \
+{ \
+ GLuint p; \
+ \
+ for (p = 0; p < ctx->Const.MaxClipPlanes; p++) \
+ if (ctx->Transform.ClipPlanesEnabled & (1 << p)) { \
+ GLuint nr, i; \
+ const GLfloat a = ctx->Transform._ClipUserPlane[p][0]; \
+ const GLfloat b = ctx->Transform._ClipUserPlane[p][1]; \
+ const GLfloat c = ctx->Transform._ClipUserPlane[p][2]; \
+ const GLfloat d = ctx->Transform._ClipUserPlane[p][3]; \
+ GLfloat *coord = (GLfloat *)clip->data; \
+ GLuint stride = clip->stride; \
+ GLuint count = clip->count; \
+ \
+ for (nr = 0, i = 0 ; i < count ; i++) { \
+ GLfloat dp = coord[0] * a + coord[1] * b; \
+ if (SZ > 2) dp += coord[2] * c; \
+ if (SZ > 3) dp += coord[3] * d; else dp += d; \
+ \
+ if (dp < 0) { \
+ nr++; \
+ clipmask[i] |= CLIP_USER_BIT; \
+ } \
+ \
+ STRIDE_F(coord, stride); \
+ } \
+ \
+ if (nr > 0) { \
+ *clipormask |= CLIP_USER_BIT; \
+ if (nr == count) { \
+ *clipandmask |= CLIP_USER_BIT; \
+ return; \
+ } \
+ } \
+ } \
+}
+
+
+USER_CLIPTEST(userclip2, 2)
+USER_CLIPTEST(userclip3, 3)
+USER_CLIPTEST(userclip4, 4)
+
+static void (*(usercliptab[5]))( struct gl_context *,
+ GLvector4f *, GLubyte *,
+ GLubyte *, GLubyte * ) =
+{
+ NULL,
+ NULL,
+ userclip2,
+ userclip3,
+ userclip4
+};
+
+
+void
+tnl_clip_prepare(struct gl_context *ctx)
+{
+ /* Neither the x86 nor sparc asm cliptest functions have been updated
+ * for ARB_depth_clamp, so force the C paths.
+ */
+ if (ctx->Transform.DepthClamp) {
+ static GLboolean c_funcs_installed = GL_FALSE;
+ if (!c_funcs_installed) {
+ init_c_cliptest();
+ c_funcs_installed = GL_TRUE;
+ }
+ }
+}
+
+
+
+static GLboolean run_vertex_stage( struct gl_context *ctx,
+ struct tnl_pipeline_stage *stage )
+{
+ struct vertex_stage_data *store = (struct vertex_stage_data *)stage->privatePtr;
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+
+ if (ctx->VertexProgram._Current)
+ return GL_TRUE;
+
+ tnl_clip_prepare(ctx);
+
+ if (ctx->_NeedEyeCoords) {
+ /* Separate modelview transformation:
+ * Use combined ModelProject to avoid some depth artifacts
+ */
+ if (ctx->ModelviewMatrixStack.Top->type == MATRIX_IDENTITY)
+ VB->EyePtr = VB->AttribPtr[_TNL_ATTRIB_POS];
+ else
+ VB->EyePtr = TransformRaw( &store->eye,
+ ctx->ModelviewMatrixStack.Top,
+ VB->AttribPtr[_TNL_ATTRIB_POS]);
+ }
+
+ VB->ClipPtr = TransformRaw( &store->clip,
+ &ctx->_ModelProjectMatrix,
+ VB->AttribPtr[_TNL_ATTRIB_POS] );
+
+ /* Drivers expect this to be clean to element 4...
+ */
+ switch (VB->ClipPtr->size) {
+ case 1:
+ /* impossible */
+ case 2:
+ _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 2 );
+ /* fall-through */
+ case 3:
+ _mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 3 );
+ /* fall-through */
+ case 4:
+ break;
+ }
+
+
+ /* Cliptest and perspective divide. Clip functions must clear
+ * the clipmask.
+ */
+ store->ormask = 0;
+ store->andmask = CLIP_FRUSTUM_BITS;
+
+ if (tnl->NeedNdcCoords) {
+ VB->NdcPtr =
+ _mesa_clip_tab[VB->ClipPtr->size]( VB->ClipPtr,
+ &store->proj,
+ store->clipmask,
+ &store->ormask,
+ &store->andmask,
+ !ctx->Transform.DepthClamp );
+ }
+ else {
+ VB->NdcPtr = NULL;
+ _mesa_clip_np_tab[VB->ClipPtr->size]( VB->ClipPtr,
+ NULL,
+ store->clipmask,
+ &store->ormask,
+ &store->andmask,
+ !ctx->Transform.DepthClamp );
+ }
+
+ if (store->andmask)
+ return GL_FALSE;
+
+
+ /* Test userclip planes. This contributes to VB->ClipMask, so
+ * is essentially required to be in this stage.
+ */
+ if (ctx->Transform.ClipPlanesEnabled) {
+ usercliptab[VB->ClipPtr->size]( ctx,
+ VB->ClipPtr,
+ store->clipmask,
+ &store->ormask,
+ &store->andmask );
+
+ if (store->andmask)
+ return GL_FALSE;
+ }
+
+ VB->ClipAndMask = store->andmask;
+ VB->ClipOrMask = store->ormask;
+ VB->ClipMask = store->clipmask;
+
+ return GL_TRUE;
+}
+
+
+static GLboolean init_vertex_stage( struct gl_context *ctx,
+ struct tnl_pipeline_stage *stage )
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ struct vertex_stage_data *store;
+ GLuint size = VB->Size;
+
+ stage->privatePtr = CALLOC(sizeof(*store));
+ store = VERTEX_STAGE_DATA(stage);
+ if (!store)
+ return GL_FALSE;
+
+ _mesa_vector4f_alloc( &store->eye, 0, size, 32 );
+ _mesa_vector4f_alloc( &store->clip, 0, size, 32 );
+ _mesa_vector4f_alloc( &store->proj, 0, size, 32 );
+
+ store->clipmask = (GLubyte *) _mesa_align_malloc(sizeof(GLubyte)*size, 32 );
+
+ if (!store->clipmask ||
+ !store->eye.data ||
+ !store->clip.data ||
+ !store->proj.data)
+ return GL_FALSE;
+
+ return GL_TRUE;
+}
+
+static void dtr( struct tnl_pipeline_stage *stage )
+{
+ struct vertex_stage_data *store = VERTEX_STAGE_DATA(stage);
+
+ if (store) {
+ _mesa_vector4f_free( &store->eye );
+ _mesa_vector4f_free( &store->clip );
+ _mesa_vector4f_free( &store->proj );
+ _mesa_align_free( store->clipmask );
+ FREE(store);
+ stage->privatePtr = NULL;
+ stage->run = init_vertex_stage;
+ }
+}
+
+
+const struct tnl_pipeline_stage _tnl_vertex_transform_stage =
+{
+ "modelview/project/cliptest/divide",
+ NULL, /* private data */
+ init_vertex_stage,
+ dtr, /* destructor */
+ NULL,
+ run_vertex_stage /* run -- initially set to init */
+};
diff --git a/mesalib/src/mesa/tnl/t_vertex.c b/mesalib/src/mesa/tnl/t_vertex.c index c1b157023..0ca324402 100644 --- a/mesalib/src/mesa/tnl/t_vertex.c +++ b/mesalib/src/mesa/tnl/t_vertex.c @@ -1,564 +1,564 @@ -/* - * Copyright 2003 Tungsten Graphics, inc. - * 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 <keithw@tungstengraphics.com> - */ - -#include "main/glheader.h" -#include "main/context.h" -#include "main/colormac.h" - -#include "t_context.h" -#include "t_vertex.h" - -#define DBG 0 - -/* Build and manage clipspace/ndc/window vertices. - */ - -static GLboolean match_fastpath( struct tnl_clipspace *vtx, - const struct tnl_clipspace_fastpath *fp) -{ - GLuint j; - - if (vtx->attr_count != fp->attr_count) - return GL_FALSE; - - for (j = 0; j < vtx->attr_count; j++) - if (vtx->attr[j].format != fp->attr[j].format || - vtx->attr[j].inputsize != fp->attr[j].size || - vtx->attr[j].vertoffset != fp->attr[j].offset) - return GL_FALSE; - - if (fp->match_strides) { - if (vtx->vertex_size != fp->vertex_size) - return GL_FALSE; - - for (j = 0; j < vtx->attr_count; j++) - if (vtx->attr[j].inputstride != fp->attr[j].stride) - return GL_FALSE; - } - - return GL_TRUE; -} - -static GLboolean search_fastpath_emit( struct tnl_clipspace *vtx ) -{ - struct tnl_clipspace_fastpath *fp = vtx->fastpath; - - for ( ; fp ; fp = fp->next) { - if (match_fastpath(vtx, fp)) { - vtx->emit = fp->func; - return GL_TRUE; - } - } - - return GL_FALSE; -} - -void _tnl_register_fastpath( struct tnl_clipspace *vtx, - GLboolean match_strides ) -{ - struct tnl_clipspace_fastpath *fastpath = CALLOC_STRUCT(tnl_clipspace_fastpath); - GLuint i; - - fastpath->vertex_size = vtx->vertex_size; - fastpath->attr_count = vtx->attr_count; - fastpath->match_strides = match_strides; - fastpath->func = vtx->emit; - fastpath->attr = (struct tnl_attr_type *) - malloc(vtx->attr_count * sizeof(fastpath->attr[0])); - - for (i = 0; i < vtx->attr_count; i++) { - fastpath->attr[i].format = vtx->attr[i].format; - fastpath->attr[i].stride = vtx->attr[i].inputstride; - fastpath->attr[i].size = vtx->attr[i].inputsize; - fastpath->attr[i].offset = vtx->attr[i].vertoffset; - } - - fastpath->next = vtx->fastpath; - vtx->fastpath = fastpath; -} - - - -/*********************************************************************** - * Build codegen functions or return generic ones: - */ -static void choose_emit_func( GLcontext *ctx, GLuint count, GLubyte *dest) -{ - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); - struct tnl_clipspace_attr *a = vtx->attr; - const GLuint attr_count = vtx->attr_count; - GLuint j; - - for (j = 0; j < attr_count; j++) { - GLvector4f *vptr = VB->AttribPtr[a[j].attrib]; - a[j].inputstride = vptr->stride; - a[j].inputsize = vptr->size; - a[j].emit = a[j].insert[vptr->size - 1]; /* not always used */ - } - - vtx->emit = NULL; - - /* Does this match an existing (hardwired, codegen or known-bad) - * fastpath? - */ - if (search_fastpath_emit(vtx)) { - /* Use this result. If it is null, then it is already known - * that the current state will fail for codegen and there is no - * point trying again. - */ - } - else if (vtx->codegen_emit) { - vtx->codegen_emit(ctx); - } - - if (!vtx->emit) { - _tnl_generate_hardwired_emit(ctx); - } - - /* Otherwise use the generic version: - */ - if (!vtx->emit) - vtx->emit = _tnl_generic_emit; - - vtx->emit( ctx, count, dest ); -} - - - -static void choose_interp_func( GLcontext *ctx, - GLfloat t, - GLuint edst, GLuint eout, GLuint ein, - GLboolean force_boundary ) -{ - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); - - if (vtx->need_extras && - (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) { - vtx->interp = _tnl_generic_interp_extras; - } else { - vtx->interp = _tnl_generic_interp; - } - - vtx->interp( ctx, t, edst, eout, ein, force_boundary ); -} - - -static void choose_copy_pv_func( GLcontext *ctx, GLuint edst, GLuint esrc ) -{ - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); - - if (vtx->need_extras && - (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) { - vtx->copy_pv = _tnl_generic_copy_pv_extras; - } else { - vtx->copy_pv = _tnl_generic_copy_pv; - } - - vtx->copy_pv( ctx, edst, esrc ); -} - - -/*********************************************************************** - * Public entrypoints, mostly dispatch to the above: - */ - - -/* Interpolate between two vertices to produce a third: - */ -void _tnl_interp( GLcontext *ctx, - GLfloat t, - GLuint edst, GLuint eout, GLuint ein, - GLboolean force_boundary ) -{ - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); - vtx->interp( ctx, t, edst, eout, ein, force_boundary ); -} - -/* Copy colors from one vertex to another: - */ -void _tnl_copy_pv( GLcontext *ctx, GLuint edst, GLuint esrc ) -{ - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); - vtx->copy_pv( ctx, edst, esrc ); -} - - -/* Extract a named attribute from a hardware vertex. Will have to - * reverse any viewport transformation, swizzling or other conversions - * which may have been applied: - */ -void _tnl_get_attr( GLcontext *ctx, const void *vin, - GLenum attr, GLfloat *dest ) -{ - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); - const struct tnl_clipspace_attr *a = vtx->attr; - const GLuint attr_count = vtx->attr_count; - GLuint j; - - for (j = 0; j < attr_count; j++) { - if (a[j].attrib == attr) { - a[j].extract( &a[j], dest, (GLubyte *)vin + a[j].vertoffset ); - return; - } - } - - /* Else return the value from ctx->Current. - */ - if (attr == _TNL_ATTRIB_POINTSIZE) { - /* If the hardware vertex doesn't have point size then use size from - * GLcontext. XXX this will be wrong if drawing attenuated points! - */ - dest[0] = ctx->Point.Size; - } - else { - memcpy( dest, ctx->Current.Attrib[attr], 4*sizeof(GLfloat)); - } -} - - -/* Complementary operation to the above. - */ -void _tnl_set_attr( GLcontext *ctx, void *vout, - GLenum attr, const GLfloat *src ) -{ - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); - const struct tnl_clipspace_attr *a = vtx->attr; - const GLuint attr_count = vtx->attr_count; - GLuint j; - - for (j = 0; j < attr_count; j++) { - if (a[j].attrib == attr) { - a[j].insert[4-1]( &a[j], (GLubyte *)vout + a[j].vertoffset, src ); - return; - } - } -} - - -void *_tnl_get_vertex( GLcontext *ctx, GLuint nr ) -{ - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); - - return vtx->vertex_buf + nr * vtx->vertex_size; -} - -void _tnl_invalidate_vertex_state( GLcontext *ctx, GLuint new_state ) -{ - if (new_state & (_DD_NEW_TRI_LIGHT_TWOSIDE|_DD_NEW_TRI_UNFILLED) ) { - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); - vtx->new_inputs = ~0; - vtx->interp = choose_interp_func; - vtx->copy_pv = choose_copy_pv_func; - } -} - -static void invalidate_funcs( struct tnl_clipspace *vtx ) -{ - vtx->emit = choose_emit_func; - vtx->interp = choose_interp_func; - vtx->copy_pv = choose_copy_pv_func; - vtx->new_inputs = ~0; -} - -GLuint _tnl_install_attrs( GLcontext *ctx, const struct tnl_attr_map *map, - GLuint nr, const GLfloat *vp, - GLuint unpacked_size ) -{ - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); - GLuint offset = 0; - GLuint i, j; - - assert(nr < _TNL_ATTRIB_MAX); - assert(nr == 0 || map[0].attrib == VERT_ATTRIB_POS); - - vtx->new_inputs = ~0; - vtx->need_viewport = GL_FALSE; - - if (vp) { - vtx->need_viewport = GL_TRUE; - } - - for (j = 0, i = 0; i < nr; i++) { - const GLuint format = map[i].format; - if (format == EMIT_PAD) { - if (DBG) - printf("%d: pad %d, offset %d\n", i, - map[i].offset, offset); - - offset += map[i].offset; - - } - else { - GLuint tmpoffset; - - if (unpacked_size) - tmpoffset = map[i].offset; - else - tmpoffset = offset; - - if (vtx->attr_count != j || - vtx->attr[j].attrib != map[i].attrib || - vtx->attr[j].format != format || - vtx->attr[j].vertoffset != tmpoffset) { - invalidate_funcs(vtx); - - vtx->attr[j].attrib = map[i].attrib; - vtx->attr[j].format = format; - vtx->attr[j].vp = vp; - vtx->attr[j].insert = _tnl_format_info[format].insert; - vtx->attr[j].extract = _tnl_format_info[format].extract; - vtx->attr[j].vertattrsize = _tnl_format_info[format].attrsize; - vtx->attr[j].vertoffset = tmpoffset; - } - - - if (DBG) - printf("%d: %s, vp %p, offset %d\n", i, - _tnl_format_info[format].name, (void *)vp, - vtx->attr[j].vertoffset); - - offset += _tnl_format_info[format].attrsize; - j++; - } - } - - vtx->attr_count = j; - - if (unpacked_size) - vtx->vertex_size = unpacked_size; - else - vtx->vertex_size = offset; - - assert(vtx->vertex_size <= vtx->max_vertex_size); - return vtx->vertex_size; -} - - - -void _tnl_invalidate_vertices( GLcontext *ctx, GLuint newinputs ) -{ - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); - vtx->new_inputs |= newinputs; -} - - -/* This event has broader use beyond this file - will move elsewhere - * and probably invoke a driver callback. - */ -void _tnl_notify_pipeline_output_change( GLcontext *ctx ) -{ - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); - invalidate_funcs(vtx); -} - - -static void adjust_input_ptrs( GLcontext *ctx, GLint diff) -{ - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); - struct tnl_clipspace_attr *a = vtx->attr; - const GLuint count = vtx->attr_count; - GLuint j; - - diff -= 1; - for (j=0; j<count; ++j) { - register GLvector4f *vptr = VB->AttribPtr[a->attrib]; - (a++)->inputptr += diff*vptr->stride; - } -} - -static void update_input_ptrs( GLcontext *ctx, GLuint start ) -{ - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); - struct tnl_clipspace_attr *a = vtx->attr; - const GLuint count = vtx->attr_count; - GLuint j; - - for (j = 0; j < count; j++) { - GLvector4f *vptr = VB->AttribPtr[a[j].attrib]; - - if (vtx->emit != choose_emit_func) { - assert(a[j].inputstride == vptr->stride); - assert(a[j].inputsize == vptr->size); - } - - a[j].inputptr = ((GLubyte *)vptr->data) + start * vptr->stride; - } - - if (a->vp) { - vtx->vp_scale[0] = a->vp[MAT_SX]; - vtx->vp_scale[1] = a->vp[MAT_SY]; - vtx->vp_scale[2] = a->vp[MAT_SZ]; - vtx->vp_scale[3] = 1.0; - vtx->vp_xlate[0] = a->vp[MAT_TX]; - vtx->vp_xlate[1] = a->vp[MAT_TY]; - vtx->vp_xlate[2] = a->vp[MAT_TZ]; - vtx->vp_xlate[3] = 0.0; - } -} - - -void _tnl_build_vertices( GLcontext *ctx, - GLuint start, - GLuint end, - GLuint newinputs ) -{ - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); - update_input_ptrs( ctx, start ); - vtx->emit( ctx, end - start, - (GLubyte *)(vtx->vertex_buf + - start * vtx->vertex_size)); -} - -/* Emit VB vertices start..end to dest. Note that VB vertex at - * postion start will be emitted to dest at position zero. - */ -void *_tnl_emit_vertices_to_buffer( GLcontext *ctx, - GLuint start, - GLuint end, - void *dest ) -{ - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); - - update_input_ptrs(ctx, start); - /* Note: dest should not be adjusted for non-zero 'start' values: - */ - vtx->emit( ctx, end - start, (GLubyte*) dest ); - return (void *)((GLubyte *)dest + vtx->vertex_size * (end - start)); -} - -/* Emit indexed VB vertices start..end to dest. Note that VB vertex at - * postion start will be emitted to dest at position zero. - */ - -void *_tnl_emit_indexed_vertices_to_buffer( GLcontext *ctx, - const GLuint *elts, - GLuint start, - GLuint end, - void *dest ) -{ - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); - GLuint oldIndex; - GLubyte *cdest = dest; - - update_input_ptrs(ctx, oldIndex = elts[start++]); - vtx->emit( ctx, 1, cdest ); - cdest += vtx->vertex_size; - - for (; start < end; ++start) { - adjust_input_ptrs(ctx, elts[start] - oldIndex); - oldIndex = elts[start]; - vtx->emit( ctx, 1, cdest); - cdest += vtx->vertex_size; - } - - return (void *) cdest; -} - - -void _tnl_init_vertices( GLcontext *ctx, - GLuint vb_size, - GLuint max_vertex_size ) -{ - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); - - _tnl_install_attrs( ctx, NULL, 0, NULL, 0 ); - - vtx->need_extras = GL_TRUE; - if (max_vertex_size > vtx->max_vertex_size) { - _tnl_free_vertices( ctx ); - vtx->max_vertex_size = max_vertex_size; - vtx->vertex_buf = (GLubyte *)_mesa_align_calloc(vb_size * max_vertex_size, 32 ); - invalidate_funcs(vtx); - } - - switch(CHAN_TYPE) { - case GL_UNSIGNED_BYTE: - vtx->chan_scale[0] = 255.0; - vtx->chan_scale[1] = 255.0; - vtx->chan_scale[2] = 255.0; - vtx->chan_scale[3] = 255.0; - break; - case GL_UNSIGNED_SHORT: - vtx->chan_scale[0] = 65535.0; - vtx->chan_scale[1] = 65535.0; - vtx->chan_scale[2] = 65535.0; - vtx->chan_scale[3] = 65535.0; - break; - default: - vtx->chan_scale[0] = 1.0; - vtx->chan_scale[1] = 1.0; - vtx->chan_scale[2] = 1.0; - vtx->chan_scale[3] = 1.0; - break; - } - - vtx->identity[0] = 0.0; - vtx->identity[1] = 0.0; - vtx->identity[2] = 0.0; - vtx->identity[3] = 1.0; - - vtx->codegen_emit = NULL; - -#ifdef USE_SSE_ASM - if (!_mesa_getenv("MESA_NO_CODEGEN")) - vtx->codegen_emit = _tnl_generate_sse_emit; -#endif -} - - -void _tnl_free_vertices( GLcontext *ctx ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - if (tnl) { - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); - struct tnl_clipspace_fastpath *fp, *tmp; - - if (vtx->vertex_buf) { - _mesa_align_free(vtx->vertex_buf); - vtx->vertex_buf = NULL; - } - - for (fp = vtx->fastpath ; fp ; fp = tmp) { - tmp = fp->next; - FREE(fp->attr); - - /* KW: At the moment, fp->func is constrained to be allocated by - * _mesa_exec_alloc(), as the hardwired fastpaths in - * t_vertex_generic.c are handled specially. It would be nice - * to unify them, but this probably won't change until this - * module gets another overhaul. - */ - _mesa_exec_free((void *) fp->func); - FREE(fp); - } - - vtx->fastpath = NULL; - } -} +/*
+ * Copyright 2003 Tungsten Graphics, inc.
+ * 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 <keithw@tungstengraphics.com>
+ */
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/colormac.h"
+
+#include "t_context.h"
+#include "t_vertex.h"
+
+#define DBG 0
+
+/* Build and manage clipspace/ndc/window vertices.
+ */
+
+static GLboolean match_fastpath( struct tnl_clipspace *vtx,
+ const struct tnl_clipspace_fastpath *fp)
+{
+ GLuint j;
+
+ if (vtx->attr_count != fp->attr_count)
+ return GL_FALSE;
+
+ for (j = 0; j < vtx->attr_count; j++)
+ if (vtx->attr[j].format != fp->attr[j].format ||
+ vtx->attr[j].inputsize != fp->attr[j].size ||
+ vtx->attr[j].vertoffset != fp->attr[j].offset)
+ return GL_FALSE;
+
+ if (fp->match_strides) {
+ if (vtx->vertex_size != fp->vertex_size)
+ return GL_FALSE;
+
+ for (j = 0; j < vtx->attr_count; j++)
+ if (vtx->attr[j].inputstride != fp->attr[j].stride)
+ return GL_FALSE;
+ }
+
+ return GL_TRUE;
+}
+
+static GLboolean search_fastpath_emit( struct tnl_clipspace *vtx )
+{
+ struct tnl_clipspace_fastpath *fp = vtx->fastpath;
+
+ for ( ; fp ; fp = fp->next) {
+ if (match_fastpath(vtx, fp)) {
+ vtx->emit = fp->func;
+ return GL_TRUE;
+ }
+ }
+
+ return GL_FALSE;
+}
+
+void _tnl_register_fastpath( struct tnl_clipspace *vtx,
+ GLboolean match_strides )
+{
+ struct tnl_clipspace_fastpath *fastpath = CALLOC_STRUCT(tnl_clipspace_fastpath);
+ GLuint i;
+
+ fastpath->vertex_size = vtx->vertex_size;
+ fastpath->attr_count = vtx->attr_count;
+ fastpath->match_strides = match_strides;
+ fastpath->func = vtx->emit;
+ fastpath->attr = (struct tnl_attr_type *)
+ malloc(vtx->attr_count * sizeof(fastpath->attr[0]));
+
+ for (i = 0; i < vtx->attr_count; i++) {
+ fastpath->attr[i].format = vtx->attr[i].format;
+ fastpath->attr[i].stride = vtx->attr[i].inputstride;
+ fastpath->attr[i].size = vtx->attr[i].inputsize;
+ fastpath->attr[i].offset = vtx->attr[i].vertoffset;
+ }
+
+ fastpath->next = vtx->fastpath;
+ vtx->fastpath = fastpath;
+}
+
+
+
+/***********************************************************************
+ * Build codegen functions or return generic ones:
+ */
+static void choose_emit_func( struct gl_context *ctx, GLuint count, GLubyte *dest)
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ struct tnl_clipspace_attr *a = vtx->attr;
+ const GLuint attr_count = vtx->attr_count;
+ GLuint j;
+
+ for (j = 0; j < attr_count; j++) {
+ GLvector4f *vptr = VB->AttribPtr[a[j].attrib];
+ a[j].inputstride = vptr->stride;
+ a[j].inputsize = vptr->size;
+ a[j].emit = a[j].insert[vptr->size - 1]; /* not always used */
+ }
+
+ vtx->emit = NULL;
+
+ /* Does this match an existing (hardwired, codegen or known-bad)
+ * fastpath?
+ */
+ if (search_fastpath_emit(vtx)) {
+ /* Use this result. If it is null, then it is already known
+ * that the current state will fail for codegen and there is no
+ * point trying again.
+ */
+ }
+ else if (vtx->codegen_emit) {
+ vtx->codegen_emit(ctx);
+ }
+
+ if (!vtx->emit) {
+ _tnl_generate_hardwired_emit(ctx);
+ }
+
+ /* Otherwise use the generic version:
+ */
+ if (!vtx->emit)
+ vtx->emit = _tnl_generic_emit;
+
+ vtx->emit( ctx, count, dest );
+}
+
+
+
+static void choose_interp_func( struct gl_context *ctx,
+ GLfloat t,
+ GLuint edst, GLuint eout, GLuint ein,
+ GLboolean force_boundary )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+
+ if (vtx->need_extras &&
+ (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
+ vtx->interp = _tnl_generic_interp_extras;
+ } else {
+ vtx->interp = _tnl_generic_interp;
+ }
+
+ vtx->interp( ctx, t, edst, eout, ein, force_boundary );
+}
+
+
+static void choose_copy_pv_func( struct gl_context *ctx, GLuint edst, GLuint esrc )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+
+ if (vtx->need_extras &&
+ (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED))) {
+ vtx->copy_pv = _tnl_generic_copy_pv_extras;
+ } else {
+ vtx->copy_pv = _tnl_generic_copy_pv;
+ }
+
+ vtx->copy_pv( ctx, edst, esrc );
+}
+
+
+/***********************************************************************
+ * Public entrypoints, mostly dispatch to the above:
+ */
+
+
+/* Interpolate between two vertices to produce a third:
+ */
+void _tnl_interp( struct gl_context *ctx,
+ GLfloat t,
+ GLuint edst, GLuint eout, GLuint ein,
+ GLboolean force_boundary )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ vtx->interp( ctx, t, edst, eout, ein, force_boundary );
+}
+
+/* Copy colors from one vertex to another:
+ */
+void _tnl_copy_pv( struct gl_context *ctx, GLuint edst, GLuint esrc )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ vtx->copy_pv( ctx, edst, esrc );
+}
+
+
+/* Extract a named attribute from a hardware vertex. Will have to
+ * reverse any viewport transformation, swizzling or other conversions
+ * which may have been applied:
+ */
+void _tnl_get_attr( struct gl_context *ctx, const void *vin,
+ GLenum attr, GLfloat *dest )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ const struct tnl_clipspace_attr *a = vtx->attr;
+ const GLuint attr_count = vtx->attr_count;
+ GLuint j;
+
+ for (j = 0; j < attr_count; j++) {
+ if (a[j].attrib == attr) {
+ a[j].extract( &a[j], dest, (GLubyte *)vin + a[j].vertoffset );
+ return;
+ }
+ }
+
+ /* Else return the value from ctx->Current.
+ */
+ if (attr == _TNL_ATTRIB_POINTSIZE) {
+ /* If the hardware vertex doesn't have point size then use size from
+ * struct gl_context. XXX this will be wrong if drawing attenuated points!
+ */
+ dest[0] = ctx->Point.Size;
+ }
+ else {
+ memcpy( dest, ctx->Current.Attrib[attr], 4*sizeof(GLfloat));
+ }
+}
+
+
+/* Complementary operation to the above.
+ */
+void _tnl_set_attr( struct gl_context *ctx, void *vout,
+ GLenum attr, const GLfloat *src )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ const struct tnl_clipspace_attr *a = vtx->attr;
+ const GLuint attr_count = vtx->attr_count;
+ GLuint j;
+
+ for (j = 0; j < attr_count; j++) {
+ if (a[j].attrib == attr) {
+ a[j].insert[4-1]( &a[j], (GLubyte *)vout + a[j].vertoffset, src );
+ return;
+ }
+ }
+}
+
+
+void *_tnl_get_vertex( struct gl_context *ctx, GLuint nr )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+
+ return vtx->vertex_buf + nr * vtx->vertex_size;
+}
+
+void _tnl_invalidate_vertex_state( struct gl_context *ctx, GLuint new_state )
+{
+ if (new_state & (_DD_NEW_TRI_LIGHT_TWOSIDE|_DD_NEW_TRI_UNFILLED) ) {
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ vtx->new_inputs = ~0;
+ vtx->interp = choose_interp_func;
+ vtx->copy_pv = choose_copy_pv_func;
+ }
+}
+
+static void invalidate_funcs( struct tnl_clipspace *vtx )
+{
+ vtx->emit = choose_emit_func;
+ vtx->interp = choose_interp_func;
+ vtx->copy_pv = choose_copy_pv_func;
+ vtx->new_inputs = ~0;
+}
+
+GLuint _tnl_install_attrs( struct gl_context *ctx, const struct tnl_attr_map *map,
+ GLuint nr, const GLfloat *vp,
+ GLuint unpacked_size )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ GLuint offset = 0;
+ GLuint i, j;
+
+ assert(nr < _TNL_ATTRIB_MAX);
+ assert(nr == 0 || map[0].attrib == VERT_ATTRIB_POS);
+
+ vtx->new_inputs = ~0;
+ vtx->need_viewport = GL_FALSE;
+
+ if (vp) {
+ vtx->need_viewport = GL_TRUE;
+ }
+
+ for (j = 0, i = 0; i < nr; i++) {
+ const GLuint format = map[i].format;
+ if (format == EMIT_PAD) {
+ if (DBG)
+ printf("%d: pad %d, offset %d\n", i,
+ map[i].offset, offset);
+
+ offset += map[i].offset;
+
+ }
+ else {
+ GLuint tmpoffset;
+
+ if (unpacked_size)
+ tmpoffset = map[i].offset;
+ else
+ tmpoffset = offset;
+
+ if (vtx->attr_count != j ||
+ vtx->attr[j].attrib != map[i].attrib ||
+ vtx->attr[j].format != format ||
+ vtx->attr[j].vertoffset != tmpoffset) {
+ invalidate_funcs(vtx);
+
+ vtx->attr[j].attrib = map[i].attrib;
+ vtx->attr[j].format = format;
+ vtx->attr[j].vp = vp;
+ vtx->attr[j].insert = _tnl_format_info[format].insert;
+ vtx->attr[j].extract = _tnl_format_info[format].extract;
+ vtx->attr[j].vertattrsize = _tnl_format_info[format].attrsize;
+ vtx->attr[j].vertoffset = tmpoffset;
+ }
+
+
+ if (DBG)
+ printf("%d: %s, vp %p, offset %d\n", i,
+ _tnl_format_info[format].name, (void *)vp,
+ vtx->attr[j].vertoffset);
+
+ offset += _tnl_format_info[format].attrsize;
+ j++;
+ }
+ }
+
+ vtx->attr_count = j;
+
+ if (unpacked_size)
+ vtx->vertex_size = unpacked_size;
+ else
+ vtx->vertex_size = offset;
+
+ assert(vtx->vertex_size <= vtx->max_vertex_size);
+ return vtx->vertex_size;
+}
+
+
+
+void _tnl_invalidate_vertices( struct gl_context *ctx, GLuint newinputs )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ vtx->new_inputs |= newinputs;
+}
+
+
+/* This event has broader use beyond this file - will move elsewhere
+ * and probably invoke a driver callback.
+ */
+void _tnl_notify_pipeline_output_change( struct gl_context *ctx )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ invalidate_funcs(vtx);
+}
+
+
+static void adjust_input_ptrs( struct gl_context *ctx, GLint diff)
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ struct tnl_clipspace_attr *a = vtx->attr;
+ const GLuint count = vtx->attr_count;
+ GLuint j;
+
+ diff -= 1;
+ for (j=0; j<count; ++j) {
+ register GLvector4f *vptr = VB->AttribPtr[a->attrib];
+ (a++)->inputptr += diff*vptr->stride;
+ }
+}
+
+static void update_input_ptrs( struct gl_context *ctx, GLuint start )
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ struct tnl_clipspace_attr *a = vtx->attr;
+ const GLuint count = vtx->attr_count;
+ GLuint j;
+
+ for (j = 0; j < count; j++) {
+ GLvector4f *vptr = VB->AttribPtr[a[j].attrib];
+
+ if (vtx->emit != choose_emit_func) {
+ assert(a[j].inputstride == vptr->stride);
+ assert(a[j].inputsize == vptr->size);
+ }
+
+ a[j].inputptr = ((GLubyte *)vptr->data) + start * vptr->stride;
+ }
+
+ if (a->vp) {
+ vtx->vp_scale[0] = a->vp[MAT_SX];
+ vtx->vp_scale[1] = a->vp[MAT_SY];
+ vtx->vp_scale[2] = a->vp[MAT_SZ];
+ vtx->vp_scale[3] = 1.0;
+ vtx->vp_xlate[0] = a->vp[MAT_TX];
+ vtx->vp_xlate[1] = a->vp[MAT_TY];
+ vtx->vp_xlate[2] = a->vp[MAT_TZ];
+ vtx->vp_xlate[3] = 0.0;
+ }
+}
+
+
+void _tnl_build_vertices( struct gl_context *ctx,
+ GLuint start,
+ GLuint end,
+ GLuint newinputs )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ update_input_ptrs( ctx, start );
+ vtx->emit( ctx, end - start,
+ (GLubyte *)(vtx->vertex_buf +
+ start * vtx->vertex_size));
+}
+
+/* Emit VB vertices start..end to dest. Note that VB vertex at
+ * postion start will be emitted to dest at position zero.
+ */
+void *_tnl_emit_vertices_to_buffer( struct gl_context *ctx,
+ GLuint start,
+ GLuint end,
+ void *dest )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+
+ update_input_ptrs(ctx, start);
+ /* Note: dest should not be adjusted for non-zero 'start' values:
+ */
+ vtx->emit( ctx, end - start, (GLubyte*) dest );
+ return (void *)((GLubyte *)dest + vtx->vertex_size * (end - start));
+}
+
+/* Emit indexed VB vertices start..end to dest. Note that VB vertex at
+ * postion start will be emitted to dest at position zero.
+ */
+
+void *_tnl_emit_indexed_vertices_to_buffer( struct gl_context *ctx,
+ const GLuint *elts,
+ GLuint start,
+ GLuint end,
+ void *dest )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ GLuint oldIndex;
+ GLubyte *cdest = dest;
+
+ update_input_ptrs(ctx, oldIndex = elts[start++]);
+ vtx->emit( ctx, 1, cdest );
+ cdest += vtx->vertex_size;
+
+ for (; start < end; ++start) {
+ adjust_input_ptrs(ctx, elts[start] - oldIndex);
+ oldIndex = elts[start];
+ vtx->emit( ctx, 1, cdest);
+ cdest += vtx->vertex_size;
+ }
+
+ return (void *) cdest;
+}
+
+
+void _tnl_init_vertices( struct gl_context *ctx,
+ GLuint vb_size,
+ GLuint max_vertex_size )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+
+ _tnl_install_attrs( ctx, NULL, 0, NULL, 0 );
+
+ vtx->need_extras = GL_TRUE;
+ if (max_vertex_size > vtx->max_vertex_size) {
+ _tnl_free_vertices( ctx );
+ vtx->max_vertex_size = max_vertex_size;
+ vtx->vertex_buf = (GLubyte *)_mesa_align_calloc(vb_size * max_vertex_size, 32 );
+ invalidate_funcs(vtx);
+ }
+
+ switch(CHAN_TYPE) {
+ case GL_UNSIGNED_BYTE:
+ vtx->chan_scale[0] = 255.0;
+ vtx->chan_scale[1] = 255.0;
+ vtx->chan_scale[2] = 255.0;
+ vtx->chan_scale[3] = 255.0;
+ break;
+ case GL_UNSIGNED_SHORT:
+ vtx->chan_scale[0] = 65535.0;
+ vtx->chan_scale[1] = 65535.0;
+ vtx->chan_scale[2] = 65535.0;
+ vtx->chan_scale[3] = 65535.0;
+ break;
+ default:
+ vtx->chan_scale[0] = 1.0;
+ vtx->chan_scale[1] = 1.0;
+ vtx->chan_scale[2] = 1.0;
+ vtx->chan_scale[3] = 1.0;
+ break;
+ }
+
+ vtx->identity[0] = 0.0;
+ vtx->identity[1] = 0.0;
+ vtx->identity[2] = 0.0;
+ vtx->identity[3] = 1.0;
+
+ vtx->codegen_emit = NULL;
+
+#ifdef USE_SSE_ASM
+ if (!_mesa_getenv("MESA_NO_CODEGEN"))
+ vtx->codegen_emit = _tnl_generate_sse_emit;
+#endif
+}
+
+
+void _tnl_free_vertices( struct gl_context *ctx )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ if (tnl) {
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ struct tnl_clipspace_fastpath *fp, *tmp;
+
+ if (vtx->vertex_buf) {
+ _mesa_align_free(vtx->vertex_buf);
+ vtx->vertex_buf = NULL;
+ }
+
+ for (fp = vtx->fastpath ; fp ; fp = tmp) {
+ tmp = fp->next;
+ FREE(fp->attr);
+
+ /* KW: At the moment, fp->func is constrained to be allocated by
+ * _mesa_exec_alloc(), as the hardwired fastpaths in
+ * t_vertex_generic.c are handled specially. It would be nice
+ * to unify them, but this probably won't change until this
+ * module gets another overhaul.
+ */
+ _mesa_exec_free((void *) fp->func);
+ FREE(fp);
+ }
+
+ vtx->fastpath = NULL;
+ }
+}
diff --git a/mesalib/src/mesa/tnl/t_vertex.h b/mesalib/src/mesa/tnl/t_vertex.h index 2dfd7b57f..580961037 100644 --- a/mesalib/src/mesa/tnl/t_vertex.h +++ b/mesalib/src/mesa/tnl/t_vertex.h @@ -1,181 +1,181 @@ -/* - * Copyright 2003 Tungsten Graphics, inc. - * 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 <keithw@tungstengraphics.com> - */ - -#ifndef _TNL_VERTEX_H -#define _TNL_VERTEX_H - -#include "main/mtypes.h" -#include "t_context.h" - -/* New mechanism to specify hardware vertices so that tnl can build - * and manipulate them directly. - */ - - -/* It will probably be necessary to allow drivers to specify new - * emit-styles to cover all the wierd and wacky things out there. - */ -enum tnl_attr_format { - EMIT_1F, - EMIT_2F, - EMIT_3F, - EMIT_4F, - EMIT_2F_VIEWPORT, /* do viewport transform and emit */ - EMIT_3F_VIEWPORT, /* do viewport transform and emit */ - EMIT_4F_VIEWPORT, /* do viewport transform and emit */ - EMIT_3F_XYW, /* for projective texture */ - EMIT_1UB_1F, /* for fog coordinate */ - EMIT_3UB_3F_RGB, /* for specular color */ - EMIT_3UB_3F_BGR, /* for specular color */ - EMIT_4UB_4F_RGBA, /* for color */ - EMIT_4UB_4F_BGRA, /* for color */ - EMIT_4UB_4F_ARGB, /* for color */ - EMIT_4UB_4F_ABGR, /* for color */ - EMIT_4CHAN_4F_RGBA, /* for swrast color */ - EMIT_PAD, /* leave a hole of 'offset' bytes */ - EMIT_MAX -}; - -struct tnl_attr_map { - GLuint attrib; /* _TNL_ATTRIB_ enum */ - enum tnl_attr_format format; - GLuint offset; -}; - -struct tnl_format_info { - const char *name; - tnl_extract_func extract; - tnl_insert_func insert[4]; - const GLuint attrsize; -}; - -extern const struct tnl_format_info _tnl_format_info[EMIT_MAX]; - - -/* Interpolate between two vertices to produce a third: - */ -extern void _tnl_interp( GLcontext *ctx, - GLfloat t, - GLuint edst, GLuint eout, GLuint ein, - GLboolean force_boundary ); - -/* Copy colors from one vertex to another: - */ -extern void _tnl_copy_pv( GLcontext *ctx, GLuint edst, GLuint esrc ); - - -/* Extract a named attribute from a hardware vertex. Will have to - * reverse any viewport transformation, swizzling or other conversions - * which may have been applied: - */ -extern void _tnl_get_attr( GLcontext *ctx, const void *vertex, GLenum attrib, - GLfloat *dest ); - -/* Complementary to the above. - */ -extern void _tnl_set_attr( GLcontext *ctx, void *vout, GLenum attrib, - const GLfloat *src ); - - -extern void *_tnl_get_vertex( GLcontext *ctx, GLuint nr ); - -extern GLuint _tnl_install_attrs( GLcontext *ctx, - const struct tnl_attr_map *map, - GLuint nr, const GLfloat *vp, - GLuint unpacked_size ); - -extern void _tnl_free_vertices( GLcontext *ctx ); - -extern void _tnl_init_vertices( GLcontext *ctx, - GLuint vb_size, - GLuint max_vertex_size ); - -extern void *_tnl_emit_vertices_to_buffer( GLcontext *ctx, - GLuint start, - GLuint end, - void *dest ); - -/* This function isn't optimal. Check out - * gallium/auxilary/translate for a more comprehensive implementation of - * the same functionality. - */ - -extern void *_tnl_emit_indexed_vertices_to_buffer( GLcontext *ctx, - const GLuint *elts, - GLuint start, - GLuint end, - void *dest ); - - -extern void _tnl_build_vertices( GLcontext *ctx, - GLuint start, - GLuint end, - GLuint newinputs ); - -extern void _tnl_invalidate_vertices( GLcontext *ctx, GLuint newinputs ); - -extern void _tnl_invalidate_vertex_state( GLcontext *ctx, GLuint new_state ); - -extern void _tnl_notify_pipeline_output_change( GLcontext *ctx ); - - -#define GET_VERTEX_STATE(ctx) &(TNL_CONTEXT(ctx)->clipspace) - -/* Internal function: - */ -void _tnl_register_fastpath( struct tnl_clipspace *vtx, - GLboolean match_strides ); - - -/* t_vertex_generic.c -- Internal functions for t_vertex.c - */ -void _tnl_generic_copy_pv_extras( GLcontext *ctx, - GLuint dst, GLuint src ); - -void _tnl_generic_interp_extras( GLcontext *ctx, - GLfloat t, - GLuint dst, GLuint out, GLuint in, - GLboolean force_boundary ); - -void _tnl_generic_copy_pv( GLcontext *ctx, GLuint edst, GLuint esrc ); - -void _tnl_generic_interp( GLcontext *ctx, - GLfloat t, - GLuint edst, GLuint eout, GLuint ein, - GLboolean force_boundary ); - -void _tnl_generic_emit( GLcontext *ctx, - GLuint count, - GLubyte *v ); - -void _tnl_generate_hardwired_emit( GLcontext *ctx ); - -/* t_vertex_sse.c -- Internal functions for t_vertex.c - */ -void _tnl_generate_sse_emit( GLcontext *ctx ); - -#endif +/*
+ * Copyright 2003 Tungsten Graphics, inc.
+ * 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 <keithw@tungstengraphics.com>
+ */
+
+#ifndef _TNL_VERTEX_H
+#define _TNL_VERTEX_H
+
+#include "main/mtypes.h"
+#include "t_context.h"
+
+/* New mechanism to specify hardware vertices so that tnl can build
+ * and manipulate them directly.
+ */
+
+
+/* It will probably be necessary to allow drivers to specify new
+ * emit-styles to cover all the wierd and wacky things out there.
+ */
+enum tnl_attr_format {
+ EMIT_1F,
+ EMIT_2F,
+ EMIT_3F,
+ EMIT_4F,
+ EMIT_2F_VIEWPORT, /* do viewport transform and emit */
+ EMIT_3F_VIEWPORT, /* do viewport transform and emit */
+ EMIT_4F_VIEWPORT, /* do viewport transform and emit */
+ EMIT_3F_XYW, /* for projective texture */
+ EMIT_1UB_1F, /* for fog coordinate */
+ EMIT_3UB_3F_RGB, /* for specular color */
+ EMIT_3UB_3F_BGR, /* for specular color */
+ EMIT_4UB_4F_RGBA, /* for color */
+ EMIT_4UB_4F_BGRA, /* for color */
+ EMIT_4UB_4F_ARGB, /* for color */
+ EMIT_4UB_4F_ABGR, /* for color */
+ EMIT_4CHAN_4F_RGBA, /* for swrast color */
+ EMIT_PAD, /* leave a hole of 'offset' bytes */
+ EMIT_MAX
+};
+
+struct tnl_attr_map {
+ GLuint attrib; /* _TNL_ATTRIB_ enum */
+ enum tnl_attr_format format;
+ GLuint offset;
+};
+
+struct tnl_format_info {
+ const char *name;
+ tnl_extract_func extract;
+ tnl_insert_func insert[4];
+ const GLuint attrsize;
+};
+
+extern const struct tnl_format_info _tnl_format_info[EMIT_MAX];
+
+
+/* Interpolate between two vertices to produce a third:
+ */
+extern void _tnl_interp( struct gl_context *ctx,
+ GLfloat t,
+ GLuint edst, GLuint eout, GLuint ein,
+ GLboolean force_boundary );
+
+/* Copy colors from one vertex to another:
+ */
+extern void _tnl_copy_pv( struct gl_context *ctx, GLuint edst, GLuint esrc );
+
+
+/* Extract a named attribute from a hardware vertex. Will have to
+ * reverse any viewport transformation, swizzling or other conversions
+ * which may have been applied:
+ */
+extern void _tnl_get_attr( struct gl_context *ctx, const void *vertex, GLenum attrib,
+ GLfloat *dest );
+
+/* Complementary to the above.
+ */
+extern void _tnl_set_attr( struct gl_context *ctx, void *vout, GLenum attrib,
+ const GLfloat *src );
+
+
+extern void *_tnl_get_vertex( struct gl_context *ctx, GLuint nr );
+
+extern GLuint _tnl_install_attrs( struct gl_context *ctx,
+ const struct tnl_attr_map *map,
+ GLuint nr, const GLfloat *vp,
+ GLuint unpacked_size );
+
+extern void _tnl_free_vertices( struct gl_context *ctx );
+
+extern void _tnl_init_vertices( struct gl_context *ctx,
+ GLuint vb_size,
+ GLuint max_vertex_size );
+
+extern void *_tnl_emit_vertices_to_buffer( struct gl_context *ctx,
+ GLuint start,
+ GLuint end,
+ void *dest );
+
+/* This function isn't optimal. Check out
+ * gallium/auxilary/translate for a more comprehensive implementation of
+ * the same functionality.
+ */
+
+extern void *_tnl_emit_indexed_vertices_to_buffer( struct gl_context *ctx,
+ const GLuint *elts,
+ GLuint start,
+ GLuint end,
+ void *dest );
+
+
+extern void _tnl_build_vertices( struct gl_context *ctx,
+ GLuint start,
+ GLuint end,
+ GLuint newinputs );
+
+extern void _tnl_invalidate_vertices( struct gl_context *ctx, GLuint newinputs );
+
+extern void _tnl_invalidate_vertex_state( struct gl_context *ctx, GLuint new_state );
+
+extern void _tnl_notify_pipeline_output_change( struct gl_context *ctx );
+
+
+#define GET_VERTEX_STATE(ctx) &(TNL_CONTEXT(ctx)->clipspace)
+
+/* Internal function:
+ */
+void _tnl_register_fastpath( struct tnl_clipspace *vtx,
+ GLboolean match_strides );
+
+
+/* t_vertex_generic.c -- Internal functions for t_vertex.c
+ */
+void _tnl_generic_copy_pv_extras( struct gl_context *ctx,
+ GLuint dst, GLuint src );
+
+void _tnl_generic_interp_extras( struct gl_context *ctx,
+ GLfloat t,
+ GLuint dst, GLuint out, GLuint in,
+ GLboolean force_boundary );
+
+void _tnl_generic_copy_pv( struct gl_context *ctx, GLuint edst, GLuint esrc );
+
+void _tnl_generic_interp( struct gl_context *ctx,
+ GLfloat t,
+ GLuint edst, GLuint eout, GLuint ein,
+ GLboolean force_boundary );
+
+void _tnl_generic_emit( struct gl_context *ctx,
+ GLuint count,
+ GLubyte *v );
+
+void _tnl_generate_hardwired_emit( struct gl_context *ctx );
+
+/* t_vertex_sse.c -- Internal functions for t_vertex.c
+ */
+void _tnl_generate_sse_emit( struct gl_context *ctx );
+
+#endif
diff --git a/mesalib/src/mesa/tnl/t_vertex_generic.c b/mesalib/src/mesa/tnl/t_vertex_generic.c index b1ea14246..144b3669d 100644 --- a/mesalib/src/mesa/tnl/t_vertex_generic.c +++ b/mesalib/src/mesa/tnl/t_vertex_generic.c @@ -1,1155 +1,1155 @@ - -/* - * Copyright 2003 Tungsten Graphics, inc. - * 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 <keithw@tungstengraphics.com> - */ - -#include "main/glheader.h" -#include "main/context.h" -#include "main/colormac.h" -#include "main/simple_list.h" -#include "t_context.h" -#include "t_vertex.h" - - -#if 0 -#define DEBUG_INSERT printf("%s\n", __FUNCTION__) -#else -#define DEBUG_INSERT -#endif - - -/* - * These functions take the NDC coordinates pointed to by 'in', apply the - * NDC->Viewport mapping and store the results at 'v'. - */ - -static INLINE void insert_4f_viewport_4( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - GLfloat *out = (GLfloat *)v; - const GLfloat * const vp = a->vp; - DEBUG_INSERT; - out[0] = vp[0] * in[0] + vp[12]; - out[1] = vp[5] * in[1] + vp[13]; - out[2] = vp[10] * in[2] + vp[14]; - out[3] = in[3]; -} - -static INLINE void insert_4f_viewport_3( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - GLfloat *out = (GLfloat *)v; - const GLfloat * const vp = a->vp; - DEBUG_INSERT; - out[0] = vp[0] * in[0] + vp[12]; - out[1] = vp[5] * in[1] + vp[13]; - out[2] = vp[10] * in[2] + vp[14]; - out[3] = 1; -} - -static INLINE void insert_4f_viewport_2( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - GLfloat *out = (GLfloat *)v; - const GLfloat * const vp = a->vp; - DEBUG_INSERT; - out[0] = vp[0] * in[0] + vp[12]; - out[1] = vp[5] * in[1] + vp[13]; - out[2] = vp[14]; - out[3] = 1; -} - -static INLINE void insert_4f_viewport_1( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - GLfloat *out = (GLfloat *)v; - const GLfloat * const vp = a->vp; - DEBUG_INSERT; - out[0] = vp[0] * in[0] + vp[12]; - out[1] = vp[13]; - out[2] = vp[14]; - out[3] = 1; -} - -static INLINE void insert_3f_viewport_3( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - GLfloat *out = (GLfloat *)v; - const GLfloat * const vp = a->vp; - DEBUG_INSERT; - out[0] = vp[0] * in[0] + vp[12]; - out[1] = vp[5] * in[1] + vp[13]; - out[2] = vp[10] * in[2] + vp[14]; -} - -static INLINE void insert_3f_viewport_2( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - GLfloat *out = (GLfloat *)v; - const GLfloat * const vp = a->vp; - DEBUG_INSERT; - out[0] = vp[0] * in[0] + vp[12]; - out[1] = vp[5] * in[1] + vp[13]; - out[2] = vp[14]; -} - -static INLINE void insert_3f_viewport_1( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - GLfloat *out = (GLfloat *)v; - const GLfloat * const vp = a->vp; - DEBUG_INSERT; - out[0] = vp[0] * in[0] + vp[12]; - out[1] = vp[13]; - out[2] = vp[14]; -} - -static INLINE void insert_2f_viewport_2( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - GLfloat *out = (GLfloat *)v; - const GLfloat * const vp = a->vp; - DEBUG_INSERT; - out[0] = vp[0] * in[0] + vp[12]; - out[1] = vp[5] * in[1] + vp[13]; -} - -static INLINE void insert_2f_viewport_1( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - GLfloat *out = (GLfloat *)v; - const GLfloat * const vp = a->vp; - DEBUG_INSERT; - out[0] = vp[0] * in[0] + vp[12]; - out[1] = vp[13]; -} - - -/* - * These functions do the same as above, except for the viewport mapping. - */ - -static INLINE void insert_4f_4( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in ) -{ - GLfloat *out = (GLfloat *)(v); - (void) a; - DEBUG_INSERT; - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -static INLINE void insert_4f_3( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in ) -{ - GLfloat *out = (GLfloat *)(v); - (void) a; - DEBUG_INSERT; - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = 1; -} - -static INLINE void insert_4f_2( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in ) -{ - GLfloat *out = (GLfloat *)(v); - (void) a; - DEBUG_INSERT; - out[0] = in[0]; - out[1] = in[1]; - out[2] = 0; - out[3] = 1; -} - -static INLINE void insert_4f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in ) -{ - GLfloat *out = (GLfloat *)(v); - (void) a; - DEBUG_INSERT; - out[0] = in[0]; - out[1] = 0; - out[2] = 0; - out[3] = 1; -} - -static INLINE void insert_3f_xyw_4( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in ) -{ - GLfloat *out = (GLfloat *)(v); - (void) a; - DEBUG_INSERT; - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[3]; -} - -static INLINE void insert_3f_xyw_err( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in ) -{ - (void) a; (void) v; (void) in; - DEBUG_INSERT; - exit(1); -} - -static INLINE void insert_3f_3( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in ) -{ - GLfloat *out = (GLfloat *)(v); - (void) a; - DEBUG_INSERT; - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; -} - -static INLINE void insert_3f_2( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in ) -{ - GLfloat *out = (GLfloat *)(v); - (void) a; - DEBUG_INSERT; - out[0] = in[0]; - out[1] = in[1]; - out[2] = 0; -} - -static INLINE void insert_3f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in ) -{ - GLfloat *out = (GLfloat *)(v); - (void) a; - DEBUG_INSERT; - out[0] = in[0]; - out[1] = 0; - out[2] = 0; -} - - -static INLINE void insert_2f_2( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in ) -{ - GLfloat *out = (GLfloat *)(v); - (void) a; - DEBUG_INSERT; - out[0] = in[0]; - out[1] = in[1]; -} - -static INLINE void insert_2f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in ) -{ - GLfloat *out = (GLfloat *)(v); - (void) a; - DEBUG_INSERT; - out[0] = in[0]; - out[1] = 0; -} - -static INLINE void insert_1f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in ) -{ - GLfloat *out = (GLfloat *)(v); - (void) a; - DEBUG_INSERT; - out[0] = in[0]; -} - -static INLINE void insert_null( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in ) -{ - DEBUG_INSERT; - (void) a; (void) v; (void) in; -} - -static INLINE void insert_4chan_4f_rgba_4( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - GLchan *c = (GLchan *)v; - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]); - UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]); - UNCLAMPED_FLOAT_TO_CHAN(c[2], in[2]); - UNCLAMPED_FLOAT_TO_CHAN(c[3], in[3]); -} - -static INLINE void insert_4chan_4f_rgba_3( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - GLchan *c = (GLchan *)v; - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]); - UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]); - UNCLAMPED_FLOAT_TO_CHAN(c[2], in[2]); - c[3] = CHAN_MAX; -} - -static INLINE void insert_4chan_4f_rgba_2( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - GLchan *c = (GLchan *)v; - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]); - UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]); - c[2] = 0; - c[3] = CHAN_MAX; -} - -static INLINE void insert_4chan_4f_rgba_1( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - GLchan *c = (GLchan *)v; - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]); - c[1] = 0; - c[2] = 0; - c[3] = CHAN_MAX; -} - -static INLINE void insert_4ub_4f_rgba_4( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]); - UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]); - UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]); - UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[3]); -} - -static INLINE void insert_4ub_4f_rgba_3( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]); - UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]); - UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]); - v[3] = 0xff; -} - -static INLINE void insert_4ub_4f_rgba_2( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]); - UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]); - v[2] = 0; - v[3] = 0xff; -} - -static INLINE void insert_4ub_4f_rgba_1( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]); - v[1] = 0; - v[2] = 0; - v[3] = 0xff; -} - -static INLINE void insert_4ub_4f_bgra_4( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]); - UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]); - UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]); - UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[3]); -} - -static INLINE void insert_4ub_4f_bgra_3( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]); - UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]); - UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]); - v[3] = 0xff; -} - -static INLINE void insert_4ub_4f_bgra_2( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]); - UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]); - v[0] = 0; - v[3] = 0xff; -} - -static INLINE void insert_4ub_4f_bgra_1( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]); - v[1] = 0; - v[0] = 0; - v[3] = 0xff; -} - -static INLINE void insert_4ub_4f_argb_4( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]); - UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]); - UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[2]); - UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[3]); -} - -static INLINE void insert_4ub_4f_argb_3( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]); - UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]); - UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[2]); - v[0] = 0xff; -} - -static INLINE void insert_4ub_4f_argb_2( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]); - UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]); - v[3] = 0x00; - v[0] = 0xff; -} - -static INLINE void insert_4ub_4f_argb_1( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]); - v[2] = 0x00; - v[3] = 0x00; - v[0] = 0xff; -} - -static INLINE void insert_4ub_4f_abgr_4( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]); - UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]); - UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[2]); - UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[3]); -} - -static INLINE void insert_4ub_4f_abgr_3( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]); - UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]); - UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[2]); - v[0] = 0xff; -} - -static INLINE void insert_4ub_4f_abgr_2( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]); - UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]); - v[1] = 0x00; - v[0] = 0xff; -} - -static INLINE void insert_4ub_4f_abgr_1( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]); - v[2] = 0x00; - v[1] = 0x00; - v[0] = 0xff; -} - -static INLINE void insert_3ub_3f_rgb_3( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]); - UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]); - UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]); -} - -static INLINE void insert_3ub_3f_rgb_2( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]); - UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]); - v[2] = 0; -} - -static INLINE void insert_3ub_3f_rgb_1( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]); - v[1] = 0; - v[2] = 0; -} - -static INLINE void insert_3ub_3f_bgr_3( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]); - UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]); - UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]); -} - -static INLINE void insert_3ub_3f_bgr_2( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]); - UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]); - v[0] = 0; -} - -static INLINE void insert_3ub_3f_bgr_1( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]); - v[1] = 0; - v[0] = 0; -} - - -static INLINE void insert_1ub_1f_1( const struct tnl_clipspace_attr *a, GLubyte *v, - const GLfloat *in ) -{ - DEBUG_INSERT; - (void) a; - UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]); -} - - -/*********************************************************************** - * Functions to perform the reverse operations to the above, for - * swrast translation and clip-interpolation. - * - * Currently always extracts a full 4 floats. - */ - -static void extract_4f_viewport( const struct tnl_clipspace_attr *a, GLfloat *out, - const GLubyte *v ) -{ - const GLfloat *in = (const GLfloat *)v; - const GLfloat * const vp = a->vp; - - /* Although included for completeness, the position coordinate is - * usually handled differently during clipping. - */ - DEBUG_INSERT; - out[0] = (in[0] - vp[12]) / vp[0]; - out[1] = (in[1] - vp[13]) / vp[5]; - out[2] = (in[2] - vp[14]) / vp[10]; - out[3] = in[3]; -} - -static void extract_3f_viewport( const struct tnl_clipspace_attr *a, GLfloat *out, - const GLubyte *v ) -{ - const GLfloat *in = (const GLfloat *)v; - const GLfloat * const vp = a->vp; - DEBUG_INSERT; - out[0] = (in[0] - vp[12]) / vp[0]; - out[1] = (in[1] - vp[13]) / vp[5]; - out[2] = (in[2] - vp[14]) / vp[10]; - out[3] = 1; -} - - -static void extract_2f_viewport( const struct tnl_clipspace_attr *a, GLfloat *out, - const GLubyte *v ) -{ - const GLfloat *in = (const GLfloat *)v; - const GLfloat * const vp = a->vp; - DEBUG_INSERT; - out[0] = (in[0] - vp[12]) / vp[0]; - out[1] = (in[1] - vp[13]) / vp[5]; - out[2] = 0; - out[3] = 1; -} - - -static void extract_4f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v ) -{ - const GLfloat *in = (const GLfloat *)v; - (void) a; - - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = in[3]; -} - -static void extract_3f_xyw( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v ) -{ - const GLfloat *in = (const GLfloat *)v; - (void) a; - - out[0] = in[0]; - out[1] = in[1]; - out[2] = 0; - out[3] = in[2]; -} - - -static void extract_3f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v ) -{ - const GLfloat *in = (const GLfloat *)v; - (void) a; - - out[0] = in[0]; - out[1] = in[1]; - out[2] = in[2]; - out[3] = 1; -} - - -static void extract_2f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v ) -{ - const GLfloat *in = (const GLfloat *)v; - (void) a; - - out[0] = in[0]; - out[1] = in[1]; - out[2] = 0; - out[3] = 1; -} - -static void extract_1f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v ) -{ - const GLfloat *in = (const GLfloat *)v; - (void) a; - - out[0] = in[0]; - out[1] = 0; - out[2] = 0; - out[3] = 1; -} - -static void extract_4chan_4f_rgba( const struct tnl_clipspace_attr *a, GLfloat *out, - const GLubyte *v ) -{ - GLchan *c = (GLchan *)v; - (void) a; - - out[0] = CHAN_TO_FLOAT(c[0]); - out[1] = CHAN_TO_FLOAT(c[1]); - out[2] = CHAN_TO_FLOAT(c[2]); - out[3] = CHAN_TO_FLOAT(c[3]); -} - -static void extract_4ub_4f_rgba( const struct tnl_clipspace_attr *a, GLfloat *out, - const GLubyte *v ) -{ - (void) a; - out[0] = UBYTE_TO_FLOAT(v[0]); - out[1] = UBYTE_TO_FLOAT(v[1]); - out[2] = UBYTE_TO_FLOAT(v[2]); - out[3] = UBYTE_TO_FLOAT(v[3]); -} - -static void extract_4ub_4f_bgra( const struct tnl_clipspace_attr *a, GLfloat *out, - const GLubyte *v ) -{ - (void) a; - out[2] = UBYTE_TO_FLOAT(v[0]); - out[1] = UBYTE_TO_FLOAT(v[1]); - out[0] = UBYTE_TO_FLOAT(v[2]); - out[3] = UBYTE_TO_FLOAT(v[3]); -} - -static void extract_4ub_4f_argb( const struct tnl_clipspace_attr *a, GLfloat *out, - const GLubyte *v ) -{ - (void) a; - out[3] = UBYTE_TO_FLOAT(v[0]); - out[0] = UBYTE_TO_FLOAT(v[1]); - out[1] = UBYTE_TO_FLOAT(v[2]); - out[2] = UBYTE_TO_FLOAT(v[3]); -} - -static void extract_4ub_4f_abgr( const struct tnl_clipspace_attr *a, GLfloat *out, - const GLubyte *v ) -{ - (void) a; - out[3] = UBYTE_TO_FLOAT(v[0]); - out[2] = UBYTE_TO_FLOAT(v[1]); - out[1] = UBYTE_TO_FLOAT(v[2]); - out[0] = UBYTE_TO_FLOAT(v[3]); -} - -static void extract_3ub_3f_rgb( const struct tnl_clipspace_attr *a, GLfloat *out, - const GLubyte *v ) -{ - (void) a; - out[0] = UBYTE_TO_FLOAT(v[0]); - out[1] = UBYTE_TO_FLOAT(v[1]); - out[2] = UBYTE_TO_FLOAT(v[2]); - out[3] = 1; -} - -static void extract_3ub_3f_bgr( const struct tnl_clipspace_attr *a, GLfloat *out, - const GLubyte *v ) -{ - (void) a; - out[2] = UBYTE_TO_FLOAT(v[0]); - out[1] = UBYTE_TO_FLOAT(v[1]); - out[0] = UBYTE_TO_FLOAT(v[2]); - out[3] = 1; -} - -static void extract_1ub_1f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v ) -{ - (void) a; - out[0] = UBYTE_TO_FLOAT(v[0]); - out[1] = 0; - out[2] = 0; - out[3] = 1; -} - - -const struct tnl_format_info _tnl_format_info[EMIT_MAX] = -{ - { "1f", - extract_1f, - { insert_1f_1, insert_1f_1, insert_1f_1, insert_1f_1 }, - sizeof(GLfloat) }, - - { "2f", - extract_2f, - { insert_2f_1, insert_2f_2, insert_2f_2, insert_2f_2 }, - 2 * sizeof(GLfloat) }, - - { "3f", - extract_3f, - { insert_3f_1, insert_3f_2, insert_3f_3, insert_3f_3 }, - 3 * sizeof(GLfloat) }, - - { "4f", - extract_4f, - { insert_4f_1, insert_4f_2, insert_4f_3, insert_4f_4 }, - 4 * sizeof(GLfloat) }, - - { "2f_viewport", - extract_2f_viewport, - { insert_2f_viewport_1, insert_2f_viewport_2, insert_2f_viewport_2, - insert_2f_viewport_2 }, - 2 * sizeof(GLfloat) }, - - { "3f_viewport", - extract_3f_viewport, - { insert_3f_viewport_1, insert_3f_viewport_2, insert_3f_viewport_3, - insert_3f_viewport_3 }, - 3 * sizeof(GLfloat) }, - - { "4f_viewport", - extract_4f_viewport, - { insert_4f_viewport_1, insert_4f_viewport_2, insert_4f_viewport_3, - insert_4f_viewport_4 }, - 4 * sizeof(GLfloat) }, - - { "3f_xyw", - extract_3f_xyw, - { insert_3f_xyw_err, insert_3f_xyw_err, insert_3f_xyw_err, - insert_3f_xyw_4 }, - 3 * sizeof(GLfloat) }, - - { "1ub_1f", - extract_1ub_1f, - { insert_1ub_1f_1, insert_1ub_1f_1, insert_1ub_1f_1, insert_1ub_1f_1 }, - sizeof(GLubyte) }, - - { "3ub_3f_rgb", - extract_3ub_3f_rgb, - { insert_3ub_3f_rgb_1, insert_3ub_3f_rgb_2, insert_3ub_3f_rgb_3, - insert_3ub_3f_rgb_3 }, - 3 * sizeof(GLubyte) }, - - { "3ub_3f_bgr", - extract_3ub_3f_bgr, - { insert_3ub_3f_bgr_1, insert_3ub_3f_bgr_2, insert_3ub_3f_bgr_3, - insert_3ub_3f_bgr_3 }, - 3 * sizeof(GLubyte) }, - - { "4ub_4f_rgba", - extract_4ub_4f_rgba, - { insert_4ub_4f_rgba_1, insert_4ub_4f_rgba_2, insert_4ub_4f_rgba_3, - insert_4ub_4f_rgba_4 }, - 4 * sizeof(GLubyte) }, - - { "4ub_4f_bgra", - extract_4ub_4f_bgra, - { insert_4ub_4f_bgra_1, insert_4ub_4f_bgra_2, insert_4ub_4f_bgra_3, - insert_4ub_4f_bgra_4 }, - 4 * sizeof(GLubyte) }, - - { "4ub_4f_argb", - extract_4ub_4f_argb, - { insert_4ub_4f_argb_1, insert_4ub_4f_argb_2, insert_4ub_4f_argb_3, - insert_4ub_4f_argb_4 }, - 4 * sizeof(GLubyte) }, - - { "4ub_4f_abgr", - extract_4ub_4f_abgr, - { insert_4ub_4f_abgr_1, insert_4ub_4f_abgr_2, insert_4ub_4f_abgr_3, - insert_4ub_4f_abgr_4 }, - 4 * sizeof(GLubyte) }, - - { "4chan_4f_rgba", - extract_4chan_4f_rgba, - { insert_4chan_4f_rgba_1, insert_4chan_4f_rgba_2, insert_4chan_4f_rgba_3, - insert_4chan_4f_rgba_4 }, - 4 * sizeof(GLchan) }, - - { "pad", - NULL, - { NULL, NULL, NULL, NULL }, - 0 } - -}; - - - - -/*********************************************************************** - * Hardwired fastpaths for emitting whole vertices or groups of - * vertices - */ -#define EMIT5(NR, F0, F1, F2, F3, F4, NAME) \ -static void NAME( GLcontext *ctx, \ - GLuint count, \ - GLubyte *v ) \ -{ \ - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); \ - struct tnl_clipspace_attr *a = vtx->attr; \ - GLuint i; \ - \ - for (i = 0 ; i < count ; i++, v += vtx->vertex_size) { \ - if (NR > 0) { \ - F0( &a[0], v + a[0].vertoffset, (GLfloat *)a[0].inputptr ); \ - a[0].inputptr += a[0].inputstride; \ - } \ - \ - if (NR > 1) { \ - F1( &a[1], v + a[1].vertoffset, (GLfloat *)a[1].inputptr ); \ - a[1].inputptr += a[1].inputstride; \ - } \ - \ - if (NR > 2) { \ - F2( &a[2], v + a[2].vertoffset, (GLfloat *)a[2].inputptr ); \ - a[2].inputptr += a[2].inputstride; \ - } \ - \ - if (NR > 3) { \ - F3( &a[3], v + a[3].vertoffset, (GLfloat *)a[3].inputptr ); \ - a[3].inputptr += a[3].inputstride; \ - } \ - \ - if (NR > 4) { \ - F4( &a[4], v + a[4].vertoffset, (GLfloat *)a[4].inputptr ); \ - a[4].inputptr += a[4].inputstride; \ - } \ - } \ -} - - -#define EMIT2(F0, F1, NAME) EMIT5(2, F0, F1, insert_null, \ - insert_null, insert_null, NAME) - -#define EMIT3(F0, F1, F2, NAME) EMIT5(3, F0, F1, F2, insert_null, \ - insert_null, NAME) - -#define EMIT4(F0, F1, F2, F3, NAME) EMIT5(4, F0, F1, F2, F3, \ - insert_null, NAME) - - -EMIT2(insert_3f_viewport_3, insert_4ub_4f_rgba_4, emit_viewport3_rgba4) -EMIT2(insert_3f_viewport_3, insert_4ub_4f_bgra_4, emit_viewport3_bgra4) -EMIT2(insert_3f_3, insert_4ub_4f_rgba_4, emit_xyz3_rgba4) - -EMIT3(insert_4f_viewport_4, insert_4ub_4f_rgba_4, insert_2f_2, emit_viewport4_rgba4_st2) -EMIT3(insert_4f_viewport_4, insert_4ub_4f_bgra_4, insert_2f_2, emit_viewport4_bgra4_st2) -EMIT3(insert_4f_4, insert_4ub_4f_rgba_4, insert_2f_2, emit_xyzw4_rgba4_st2) - -EMIT4(insert_4f_viewport_4, insert_4ub_4f_rgba_4, insert_2f_2, insert_2f_2, emit_viewport4_rgba4_st2_st2) -EMIT4(insert_4f_viewport_4, insert_4ub_4f_bgra_4, insert_2f_2, insert_2f_2, emit_viewport4_bgra4_st2_st2) -EMIT4(insert_4f_4, insert_4ub_4f_rgba_4, insert_2f_2, insert_2f_2, emit_xyzw4_rgba4_st2_st2) - - -/* Use the codegen paths to select one of a number of hardwired - * fastpaths. - */ -void _tnl_generate_hardwired_emit( GLcontext *ctx ) -{ - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); - tnl_emit_func func = NULL; - - /* Does it fit a hardwired fastpath? Help! this is growing out of - * control! - */ - switch (vtx->attr_count) { - case 2: - if (vtx->attr[0].emit == insert_3f_viewport_3) { - if (vtx->attr[1].emit == insert_4ub_4f_bgra_4) - func = emit_viewport3_bgra4; - else if (vtx->attr[1].emit == insert_4ub_4f_rgba_4) - func = emit_viewport3_rgba4; - } - else if (vtx->attr[0].emit == insert_3f_3 && - vtx->attr[1].emit == insert_4ub_4f_rgba_4) { - func = emit_xyz3_rgba4; - } - break; - case 3: - if (vtx->attr[2].emit == insert_2f_2) { - if (vtx->attr[1].emit == insert_4ub_4f_rgba_4) { - if (vtx->attr[0].emit == insert_4f_viewport_4) - func = emit_viewport4_rgba4_st2; - else if (vtx->attr[0].emit == insert_4f_4) - func = emit_xyzw4_rgba4_st2; - } - else if (vtx->attr[1].emit == insert_4ub_4f_bgra_4 && - vtx->attr[0].emit == insert_4f_viewport_4) - func = emit_viewport4_bgra4_st2; - } - break; - case 4: - if (vtx->attr[2].emit == insert_2f_2 && - vtx->attr[3].emit == insert_2f_2) { - if (vtx->attr[1].emit == insert_4ub_4f_rgba_4) { - if (vtx->attr[0].emit == insert_4f_viewport_4) - func = emit_viewport4_rgba4_st2_st2; - else if (vtx->attr[0].emit == insert_4f_4) - func = emit_xyzw4_rgba4_st2_st2; - } - else if (vtx->attr[1].emit == insert_4ub_4f_bgra_4 && - vtx->attr[0].emit == insert_4f_viewport_4) - func = emit_viewport4_bgra4_st2_st2; - } - break; - } - - vtx->emit = func; -} - -/*********************************************************************** - * Generic (non-codegen) functions for whole vertices or groups of - * vertices - */ - -void _tnl_generic_emit( GLcontext *ctx, - GLuint count, - GLubyte *v ) -{ - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); - struct tnl_clipspace_attr *a = vtx->attr; - const GLuint attr_count = vtx->attr_count; - const GLuint stride = vtx->vertex_size; - GLuint i, j; - - for (i = 0 ; i < count ; i++, v += stride) { - for (j = 0; j < attr_count; j++) { - GLfloat *in = (GLfloat *)a[j].inputptr; - a[j].inputptr += a[j].inputstride; - a[j].emit( &a[j], v + a[j].vertoffset, in ); - } - } -} - - -void _tnl_generic_interp( GLcontext *ctx, - GLfloat t, - GLuint edst, GLuint eout, GLuint ein, - GLboolean force_boundary ) -{ - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct vertex_buffer *VB = &tnl->vb; - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); - const GLubyte *vin = vtx->vertex_buf + ein * vtx->vertex_size; - const GLubyte *vout = vtx->vertex_buf + eout * vtx->vertex_size; - GLubyte *vdst = vtx->vertex_buf + edst * vtx->vertex_size; - const struct tnl_clipspace_attr *a = vtx->attr; - const GLuint attr_count = vtx->attr_count; - GLuint j; - (void) force_boundary; - - if (tnl->NeedNdcCoords) { - const GLfloat *dstclip = VB->ClipPtr->data[edst]; - if (dstclip[3] != 0.0) { - const GLfloat w = 1.0f / dstclip[3]; - GLfloat pos[4]; - - pos[0] = dstclip[0] * w; - pos[1] = dstclip[1] * w; - pos[2] = dstclip[2] * w; - pos[3] = w; - - a[0].insert[4-1]( &a[0], vdst, pos ); - } - } - else { - a[0].insert[4-1]( &a[0], vdst, VB->ClipPtr->data[edst] ); - } - - - for (j = 1; j < attr_count; j++) { - GLfloat fin[4], fout[4], fdst[4]; - - a[j].extract( &a[j], fin, vin + a[j].vertoffset ); - a[j].extract( &a[j], fout, vout + a[j].vertoffset ); - - INTERP_F( t, fdst[3], fout[3], fin[3] ); - INTERP_F( t, fdst[2], fout[2], fin[2] ); - INTERP_F( t, fdst[1], fout[1], fin[1] ); - INTERP_F( t, fdst[0], fout[0], fin[0] ); - - a[j].insert[4-1]( &a[j], vdst + a[j].vertoffset, fdst ); - } -} - - -/* Extract color attributes from one vertex and insert them into - * another. (Shortcircuit extract/insert with memcpy). - */ -void _tnl_generic_copy_pv( GLcontext *ctx, GLuint edst, GLuint esrc ) -{ - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); - GLubyte *vsrc = vtx->vertex_buf + esrc * vtx->vertex_size; - GLubyte *vdst = vtx->vertex_buf + edst * vtx->vertex_size; - const struct tnl_clipspace_attr *a = vtx->attr; - const GLuint attr_count = vtx->attr_count; - GLuint j; - - for (j = 0; j < attr_count; j++) { - if (a[j].attrib == VERT_ATTRIB_COLOR0 || - a[j].attrib == VERT_ATTRIB_COLOR1) { - - memcpy( vdst + a[j].vertoffset, - vsrc + a[j].vertoffset, - a[j].vertattrsize ); - } - } -} - - -/* Helper functions for hardware which doesn't put back colors and/or - * edgeflags into vertices. - */ -void _tnl_generic_interp_extras( GLcontext *ctx, - GLfloat t, - GLuint dst, GLuint out, GLuint in, - GLboolean force_boundary ) -{ - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; - - /* If stride is zero, BackfaceColorPtr is constant across the VB, so - * there is no point interpolating between two values as they will - * be identical. In all other cases, this value is generated by - * t_vb_lighttmp.h and has a stride of 4 dwords. - */ - if (VB->BackfaceColorPtr && VB->BackfaceColorPtr->stride) { - assert(VB->BackfaceColorPtr->stride == 4 * sizeof(GLfloat)); - - INTERP_4F( t, - VB->BackfaceColorPtr->data[dst], - VB->BackfaceColorPtr->data[out], - VB->BackfaceColorPtr->data[in] ); - } - - if (VB->BackfaceSecondaryColorPtr) { - assert(VB->BackfaceSecondaryColorPtr->stride == 4 * sizeof(GLfloat)); - - INTERP_3F( t, - VB->BackfaceSecondaryColorPtr->data[dst], - VB->BackfaceSecondaryColorPtr->data[out], - VB->BackfaceSecondaryColorPtr->data[in] ); - } - - if (VB->BackfaceIndexPtr) { - VB->BackfaceIndexPtr->data[dst][0] = LINTERP( t, - VB->BackfaceIndexPtr->data[out][0], - VB->BackfaceIndexPtr->data[in][0] ); - } - - if (VB->EdgeFlag) { - VB->EdgeFlag[dst] = VB->EdgeFlag[out] || force_boundary; - } - - _tnl_generic_interp(ctx, t, dst, out, in, force_boundary); -} - -void _tnl_generic_copy_pv_extras( GLcontext *ctx, - GLuint dst, GLuint src ) -{ - struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; - - /* See above comment: - */ - if (VB->BackfaceColorPtr && VB->BackfaceColorPtr->stride) { - COPY_4FV( VB->BackfaceColorPtr->data[dst], - VB->BackfaceColorPtr->data[src] ); - } - - if (VB->BackfaceSecondaryColorPtr) { - COPY_4FV( VB->BackfaceSecondaryColorPtr->data[dst], - VB->BackfaceSecondaryColorPtr->data[src] ); - } - - if (VB->BackfaceIndexPtr) { - VB->BackfaceIndexPtr->data[dst][0] = VB->BackfaceIndexPtr->data[src][0]; - } - - _tnl_generic_copy_pv(ctx, dst, src); -} - - +
+/*
+ * Copyright 2003 Tungsten Graphics, inc.
+ * 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 <keithw@tungstengraphics.com>
+ */
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/colormac.h"
+#include "main/simple_list.h"
+#include "t_context.h"
+#include "t_vertex.h"
+
+
+#if 0
+#define DEBUG_INSERT printf("%s\n", __FUNCTION__)
+#else
+#define DEBUG_INSERT
+#endif
+
+
+/*
+ * These functions take the NDC coordinates pointed to by 'in', apply the
+ * NDC->Viewport mapping and store the results at 'v'.
+ */
+
+static INLINE void insert_4f_viewport_4( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat * const vp = a->vp;
+ DEBUG_INSERT;
+ out[0] = vp[0] * in[0] + vp[12];
+ out[1] = vp[5] * in[1] + vp[13];
+ out[2] = vp[10] * in[2] + vp[14];
+ out[3] = in[3];
+}
+
+static INLINE void insert_4f_viewport_3( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat * const vp = a->vp;
+ DEBUG_INSERT;
+ out[0] = vp[0] * in[0] + vp[12];
+ out[1] = vp[5] * in[1] + vp[13];
+ out[2] = vp[10] * in[2] + vp[14];
+ out[3] = 1;
+}
+
+static INLINE void insert_4f_viewport_2( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat * const vp = a->vp;
+ DEBUG_INSERT;
+ out[0] = vp[0] * in[0] + vp[12];
+ out[1] = vp[5] * in[1] + vp[13];
+ out[2] = vp[14];
+ out[3] = 1;
+}
+
+static INLINE void insert_4f_viewport_1( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat * const vp = a->vp;
+ DEBUG_INSERT;
+ out[0] = vp[0] * in[0] + vp[12];
+ out[1] = vp[13];
+ out[2] = vp[14];
+ out[3] = 1;
+}
+
+static INLINE void insert_3f_viewport_3( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat * const vp = a->vp;
+ DEBUG_INSERT;
+ out[0] = vp[0] * in[0] + vp[12];
+ out[1] = vp[5] * in[1] + vp[13];
+ out[2] = vp[10] * in[2] + vp[14];
+}
+
+static INLINE void insert_3f_viewport_2( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat * const vp = a->vp;
+ DEBUG_INSERT;
+ out[0] = vp[0] * in[0] + vp[12];
+ out[1] = vp[5] * in[1] + vp[13];
+ out[2] = vp[14];
+}
+
+static INLINE void insert_3f_viewport_1( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat * const vp = a->vp;
+ DEBUG_INSERT;
+ out[0] = vp[0] * in[0] + vp[12];
+ out[1] = vp[13];
+ out[2] = vp[14];
+}
+
+static INLINE void insert_2f_viewport_2( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat * const vp = a->vp;
+ DEBUG_INSERT;
+ out[0] = vp[0] * in[0] + vp[12];
+ out[1] = vp[5] * in[1] + vp[13];
+}
+
+static INLINE void insert_2f_viewport_1( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)v;
+ const GLfloat * const vp = a->vp;
+ DEBUG_INSERT;
+ out[0] = vp[0] * in[0] + vp[12];
+ out[1] = vp[13];
+}
+
+
+/*
+ * These functions do the same as above, except for the viewport mapping.
+ */
+
+static INLINE void insert_4f_4( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+ DEBUG_INSERT;
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+ out[3] = in[3];
+}
+
+static INLINE void insert_4f_3( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+ DEBUG_INSERT;
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+ out[3] = 1;
+}
+
+static INLINE void insert_4f_2( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+ DEBUG_INSERT;
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = 0;
+ out[3] = 1;
+}
+
+static INLINE void insert_4f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+ DEBUG_INSERT;
+ out[0] = in[0];
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+}
+
+static INLINE void insert_3f_xyw_4( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+ DEBUG_INSERT;
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[3];
+}
+
+static INLINE void insert_3f_xyw_err( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
+{
+ (void) a; (void) v; (void) in;
+ DEBUG_INSERT;
+ exit(1);
+}
+
+static INLINE void insert_3f_3( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+ DEBUG_INSERT;
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+}
+
+static INLINE void insert_3f_2( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+ DEBUG_INSERT;
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = 0;
+}
+
+static INLINE void insert_3f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+ DEBUG_INSERT;
+ out[0] = in[0];
+ out[1] = 0;
+ out[2] = 0;
+}
+
+
+static INLINE void insert_2f_2( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+ DEBUG_INSERT;
+ out[0] = in[0];
+ out[1] = in[1];
+}
+
+static INLINE void insert_2f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+ DEBUG_INSERT;
+ out[0] = in[0];
+ out[1] = 0;
+}
+
+static INLINE void insert_1f_1( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
+{
+ GLfloat *out = (GLfloat *)(v);
+ (void) a;
+ DEBUG_INSERT;
+ out[0] = in[0];
+}
+
+static INLINE void insert_null( const struct tnl_clipspace_attr *a, GLubyte *v, const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a; (void) v; (void) in;
+}
+
+static INLINE void insert_4chan_4f_rgba_4( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLchan *c = (GLchan *)v;
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
+ UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]);
+ UNCLAMPED_FLOAT_TO_CHAN(c[2], in[2]);
+ UNCLAMPED_FLOAT_TO_CHAN(c[3], in[3]);
+}
+
+static INLINE void insert_4chan_4f_rgba_3( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLchan *c = (GLchan *)v;
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
+ UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]);
+ UNCLAMPED_FLOAT_TO_CHAN(c[2], in[2]);
+ c[3] = CHAN_MAX;
+}
+
+static INLINE void insert_4chan_4f_rgba_2( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLchan *c = (GLchan *)v;
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
+ UNCLAMPED_FLOAT_TO_CHAN(c[1], in[1]);
+ c[2] = 0;
+ c[3] = CHAN_MAX;
+}
+
+static INLINE void insert_4chan_4f_rgba_1( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ GLchan *c = (GLchan *)v;
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_CHAN(c[0], in[0]);
+ c[1] = 0;
+ c[2] = 0;
+ c[3] = CHAN_MAX;
+}
+
+static INLINE void insert_4ub_4f_rgba_4( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[3]);
+}
+
+static INLINE void insert_4ub_4f_rgba_3( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
+ v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_rgba_2( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ v[2] = 0;
+ v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_rgba_1( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ v[1] = 0;
+ v[2] = 0;
+ v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_bgra_4( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[3]);
+}
+
+static INLINE void insert_4ub_4f_bgra_3( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
+ v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_bgra_2( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ v[0] = 0;
+ v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_bgra_1( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ v[1] = 0;
+ v[0] = 0;
+ v[3] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_argb_4( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[2]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[3]);
+}
+
+static INLINE void insert_4ub_4f_argb_3( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[2]);
+ v[0] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_argb_2( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+ v[3] = 0x00;
+ v[0] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_argb_1( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[0]);
+ v[2] = 0x00;
+ v[3] = 0x00;
+ v[0] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_abgr_4( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[2]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[3]);
+}
+
+static INLINE void insert_4ub_4f_abgr_3( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[2]);
+ v[0] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_abgr_2( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[1]);
+ v[1] = 0x00;
+ v[0] = 0xff;
+}
+
+static INLINE void insert_4ub_4f_abgr_1( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[3], in[0]);
+ v[2] = 0x00;
+ v[1] = 0x00;
+ v[0] = 0xff;
+}
+
+static INLINE void insert_3ub_3f_rgb_3( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[2]);
+}
+
+static INLINE void insert_3ub_3f_rgb_2( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ v[2] = 0;
+}
+
+static INLINE void insert_3ub_3f_rgb_1( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+ v[1] = 0;
+ v[2] = 0;
+}
+
+static INLINE void insert_3ub_3f_bgr_3( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[2]);
+}
+
+static INLINE void insert_3ub_3f_bgr_2( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ UNCLAMPED_FLOAT_TO_UBYTE(v[1], in[1]);
+ v[0] = 0;
+}
+
+static INLINE void insert_3ub_3f_bgr_1( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[2], in[0]);
+ v[1] = 0;
+ v[0] = 0;
+}
+
+
+static INLINE void insert_1ub_1f_1( const struct tnl_clipspace_attr *a, GLubyte *v,
+ const GLfloat *in )
+{
+ DEBUG_INSERT;
+ (void) a;
+ UNCLAMPED_FLOAT_TO_UBYTE(v[0], in[0]);
+}
+
+
+/***********************************************************************
+ * Functions to perform the reverse operations to the above, for
+ * swrast translation and clip-interpolation.
+ *
+ * Currently always extracts a full 4 floats.
+ */
+
+static void extract_4f_viewport( const struct tnl_clipspace_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ const GLfloat * const vp = a->vp;
+
+ /* Although included for completeness, the position coordinate is
+ * usually handled differently during clipping.
+ */
+ DEBUG_INSERT;
+ out[0] = (in[0] - vp[12]) / vp[0];
+ out[1] = (in[1] - vp[13]) / vp[5];
+ out[2] = (in[2] - vp[14]) / vp[10];
+ out[3] = in[3];
+}
+
+static void extract_3f_viewport( const struct tnl_clipspace_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ const GLfloat * const vp = a->vp;
+ DEBUG_INSERT;
+ out[0] = (in[0] - vp[12]) / vp[0];
+ out[1] = (in[1] - vp[13]) / vp[5];
+ out[2] = (in[2] - vp[14]) / vp[10];
+ out[3] = 1;
+}
+
+
+static void extract_2f_viewport( const struct tnl_clipspace_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ const GLfloat * const vp = a->vp;
+ DEBUG_INSERT;
+ out[0] = (in[0] - vp[12]) / vp[0];
+ out[1] = (in[1] - vp[13]) / vp[5];
+ out[2] = 0;
+ out[3] = 1;
+}
+
+
+static void extract_4f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+ out[3] = in[3];
+}
+
+static void extract_3f_xyw( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = 0;
+ out[3] = in[2];
+}
+
+
+static void extract_3f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = in[2];
+ out[3] = 1;
+}
+
+
+static void extract_2f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = in[1];
+ out[2] = 0;
+ out[3] = 1;
+}
+
+static void extract_1f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
+{
+ const GLfloat *in = (const GLfloat *)v;
+ (void) a;
+
+ out[0] = in[0];
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+}
+
+static void extract_4chan_4f_rgba( const struct tnl_clipspace_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ GLchan *c = (GLchan *)v;
+ (void) a;
+
+ out[0] = CHAN_TO_FLOAT(c[0]);
+ out[1] = CHAN_TO_FLOAT(c[1]);
+ out[2] = CHAN_TO_FLOAT(c[2]);
+ out[3] = CHAN_TO_FLOAT(c[3]);
+}
+
+static void extract_4ub_4f_rgba( const struct tnl_clipspace_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ (void) a;
+ out[0] = UBYTE_TO_FLOAT(v[0]);
+ out[1] = UBYTE_TO_FLOAT(v[1]);
+ out[2] = UBYTE_TO_FLOAT(v[2]);
+ out[3] = UBYTE_TO_FLOAT(v[3]);
+}
+
+static void extract_4ub_4f_bgra( const struct tnl_clipspace_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ (void) a;
+ out[2] = UBYTE_TO_FLOAT(v[0]);
+ out[1] = UBYTE_TO_FLOAT(v[1]);
+ out[0] = UBYTE_TO_FLOAT(v[2]);
+ out[3] = UBYTE_TO_FLOAT(v[3]);
+}
+
+static void extract_4ub_4f_argb( const struct tnl_clipspace_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ (void) a;
+ out[3] = UBYTE_TO_FLOAT(v[0]);
+ out[0] = UBYTE_TO_FLOAT(v[1]);
+ out[1] = UBYTE_TO_FLOAT(v[2]);
+ out[2] = UBYTE_TO_FLOAT(v[3]);
+}
+
+static void extract_4ub_4f_abgr( const struct tnl_clipspace_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ (void) a;
+ out[3] = UBYTE_TO_FLOAT(v[0]);
+ out[2] = UBYTE_TO_FLOAT(v[1]);
+ out[1] = UBYTE_TO_FLOAT(v[2]);
+ out[0] = UBYTE_TO_FLOAT(v[3]);
+}
+
+static void extract_3ub_3f_rgb( const struct tnl_clipspace_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ (void) a;
+ out[0] = UBYTE_TO_FLOAT(v[0]);
+ out[1] = UBYTE_TO_FLOAT(v[1]);
+ out[2] = UBYTE_TO_FLOAT(v[2]);
+ out[3] = 1;
+}
+
+static void extract_3ub_3f_bgr( const struct tnl_clipspace_attr *a, GLfloat *out,
+ const GLubyte *v )
+{
+ (void) a;
+ out[2] = UBYTE_TO_FLOAT(v[0]);
+ out[1] = UBYTE_TO_FLOAT(v[1]);
+ out[0] = UBYTE_TO_FLOAT(v[2]);
+ out[3] = 1;
+}
+
+static void extract_1ub_1f( const struct tnl_clipspace_attr *a, GLfloat *out, const GLubyte *v )
+{
+ (void) a;
+ out[0] = UBYTE_TO_FLOAT(v[0]);
+ out[1] = 0;
+ out[2] = 0;
+ out[3] = 1;
+}
+
+
+const struct tnl_format_info _tnl_format_info[EMIT_MAX] =
+{
+ { "1f",
+ extract_1f,
+ { insert_1f_1, insert_1f_1, insert_1f_1, insert_1f_1 },
+ sizeof(GLfloat) },
+
+ { "2f",
+ extract_2f,
+ { insert_2f_1, insert_2f_2, insert_2f_2, insert_2f_2 },
+ 2 * sizeof(GLfloat) },
+
+ { "3f",
+ extract_3f,
+ { insert_3f_1, insert_3f_2, insert_3f_3, insert_3f_3 },
+ 3 * sizeof(GLfloat) },
+
+ { "4f",
+ extract_4f,
+ { insert_4f_1, insert_4f_2, insert_4f_3, insert_4f_4 },
+ 4 * sizeof(GLfloat) },
+
+ { "2f_viewport",
+ extract_2f_viewport,
+ { insert_2f_viewport_1, insert_2f_viewport_2, insert_2f_viewport_2,
+ insert_2f_viewport_2 },
+ 2 * sizeof(GLfloat) },
+
+ { "3f_viewport",
+ extract_3f_viewport,
+ { insert_3f_viewport_1, insert_3f_viewport_2, insert_3f_viewport_3,
+ insert_3f_viewport_3 },
+ 3 * sizeof(GLfloat) },
+
+ { "4f_viewport",
+ extract_4f_viewport,
+ { insert_4f_viewport_1, insert_4f_viewport_2, insert_4f_viewport_3,
+ insert_4f_viewport_4 },
+ 4 * sizeof(GLfloat) },
+
+ { "3f_xyw",
+ extract_3f_xyw,
+ { insert_3f_xyw_err, insert_3f_xyw_err, insert_3f_xyw_err,
+ insert_3f_xyw_4 },
+ 3 * sizeof(GLfloat) },
+
+ { "1ub_1f",
+ extract_1ub_1f,
+ { insert_1ub_1f_1, insert_1ub_1f_1, insert_1ub_1f_1, insert_1ub_1f_1 },
+ sizeof(GLubyte) },
+
+ { "3ub_3f_rgb",
+ extract_3ub_3f_rgb,
+ { insert_3ub_3f_rgb_1, insert_3ub_3f_rgb_2, insert_3ub_3f_rgb_3,
+ insert_3ub_3f_rgb_3 },
+ 3 * sizeof(GLubyte) },
+
+ { "3ub_3f_bgr",
+ extract_3ub_3f_bgr,
+ { insert_3ub_3f_bgr_1, insert_3ub_3f_bgr_2, insert_3ub_3f_bgr_3,
+ insert_3ub_3f_bgr_3 },
+ 3 * sizeof(GLubyte) },
+
+ { "4ub_4f_rgba",
+ extract_4ub_4f_rgba,
+ { insert_4ub_4f_rgba_1, insert_4ub_4f_rgba_2, insert_4ub_4f_rgba_3,
+ insert_4ub_4f_rgba_4 },
+ 4 * sizeof(GLubyte) },
+
+ { "4ub_4f_bgra",
+ extract_4ub_4f_bgra,
+ { insert_4ub_4f_bgra_1, insert_4ub_4f_bgra_2, insert_4ub_4f_bgra_3,
+ insert_4ub_4f_bgra_4 },
+ 4 * sizeof(GLubyte) },
+
+ { "4ub_4f_argb",
+ extract_4ub_4f_argb,
+ { insert_4ub_4f_argb_1, insert_4ub_4f_argb_2, insert_4ub_4f_argb_3,
+ insert_4ub_4f_argb_4 },
+ 4 * sizeof(GLubyte) },
+
+ { "4ub_4f_abgr",
+ extract_4ub_4f_abgr,
+ { insert_4ub_4f_abgr_1, insert_4ub_4f_abgr_2, insert_4ub_4f_abgr_3,
+ insert_4ub_4f_abgr_4 },
+ 4 * sizeof(GLubyte) },
+
+ { "4chan_4f_rgba",
+ extract_4chan_4f_rgba,
+ { insert_4chan_4f_rgba_1, insert_4chan_4f_rgba_2, insert_4chan_4f_rgba_3,
+ insert_4chan_4f_rgba_4 },
+ 4 * sizeof(GLchan) },
+
+ { "pad",
+ NULL,
+ { NULL, NULL, NULL, NULL },
+ 0 }
+
+};
+
+
+
+
+/***********************************************************************
+ * Hardwired fastpaths for emitting whole vertices or groups of
+ * vertices
+ */
+#define EMIT5(NR, F0, F1, F2, F3, F4, NAME) \
+static void NAME( struct gl_context *ctx, \
+ GLuint count, \
+ GLubyte *v ) \
+{ \
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); \
+ struct tnl_clipspace_attr *a = vtx->attr; \
+ GLuint i; \
+ \
+ for (i = 0 ; i < count ; i++, v += vtx->vertex_size) { \
+ if (NR > 0) { \
+ F0( &a[0], v + a[0].vertoffset, (GLfloat *)a[0].inputptr ); \
+ a[0].inputptr += a[0].inputstride; \
+ } \
+ \
+ if (NR > 1) { \
+ F1( &a[1], v + a[1].vertoffset, (GLfloat *)a[1].inputptr ); \
+ a[1].inputptr += a[1].inputstride; \
+ } \
+ \
+ if (NR > 2) { \
+ F2( &a[2], v + a[2].vertoffset, (GLfloat *)a[2].inputptr ); \
+ a[2].inputptr += a[2].inputstride; \
+ } \
+ \
+ if (NR > 3) { \
+ F3( &a[3], v + a[3].vertoffset, (GLfloat *)a[3].inputptr ); \
+ a[3].inputptr += a[3].inputstride; \
+ } \
+ \
+ if (NR > 4) { \
+ F4( &a[4], v + a[4].vertoffset, (GLfloat *)a[4].inputptr ); \
+ a[4].inputptr += a[4].inputstride; \
+ } \
+ } \
+}
+
+
+#define EMIT2(F0, F1, NAME) EMIT5(2, F0, F1, insert_null, \
+ insert_null, insert_null, NAME)
+
+#define EMIT3(F0, F1, F2, NAME) EMIT5(3, F0, F1, F2, insert_null, \
+ insert_null, NAME)
+
+#define EMIT4(F0, F1, F2, F3, NAME) EMIT5(4, F0, F1, F2, F3, \
+ insert_null, NAME)
+
+
+EMIT2(insert_3f_viewport_3, insert_4ub_4f_rgba_4, emit_viewport3_rgba4)
+EMIT2(insert_3f_viewport_3, insert_4ub_4f_bgra_4, emit_viewport3_bgra4)
+EMIT2(insert_3f_3, insert_4ub_4f_rgba_4, emit_xyz3_rgba4)
+
+EMIT3(insert_4f_viewport_4, insert_4ub_4f_rgba_4, insert_2f_2, emit_viewport4_rgba4_st2)
+EMIT3(insert_4f_viewport_4, insert_4ub_4f_bgra_4, insert_2f_2, emit_viewport4_bgra4_st2)
+EMIT3(insert_4f_4, insert_4ub_4f_rgba_4, insert_2f_2, emit_xyzw4_rgba4_st2)
+
+EMIT4(insert_4f_viewport_4, insert_4ub_4f_rgba_4, insert_2f_2, insert_2f_2, emit_viewport4_rgba4_st2_st2)
+EMIT4(insert_4f_viewport_4, insert_4ub_4f_bgra_4, insert_2f_2, insert_2f_2, emit_viewport4_bgra4_st2_st2)
+EMIT4(insert_4f_4, insert_4ub_4f_rgba_4, insert_2f_2, insert_2f_2, emit_xyzw4_rgba4_st2_st2)
+
+
+/* Use the codegen paths to select one of a number of hardwired
+ * fastpaths.
+ */
+void _tnl_generate_hardwired_emit( struct gl_context *ctx )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ tnl_emit_func func = NULL;
+
+ /* Does it fit a hardwired fastpath? Help! this is growing out of
+ * control!
+ */
+ switch (vtx->attr_count) {
+ case 2:
+ if (vtx->attr[0].emit == insert_3f_viewport_3) {
+ if (vtx->attr[1].emit == insert_4ub_4f_bgra_4)
+ func = emit_viewport3_bgra4;
+ else if (vtx->attr[1].emit == insert_4ub_4f_rgba_4)
+ func = emit_viewport3_rgba4;
+ }
+ else if (vtx->attr[0].emit == insert_3f_3 &&
+ vtx->attr[1].emit == insert_4ub_4f_rgba_4) {
+ func = emit_xyz3_rgba4;
+ }
+ break;
+ case 3:
+ if (vtx->attr[2].emit == insert_2f_2) {
+ if (vtx->attr[1].emit == insert_4ub_4f_rgba_4) {
+ if (vtx->attr[0].emit == insert_4f_viewport_4)
+ func = emit_viewport4_rgba4_st2;
+ else if (vtx->attr[0].emit == insert_4f_4)
+ func = emit_xyzw4_rgba4_st2;
+ }
+ else if (vtx->attr[1].emit == insert_4ub_4f_bgra_4 &&
+ vtx->attr[0].emit == insert_4f_viewport_4)
+ func = emit_viewport4_bgra4_st2;
+ }
+ break;
+ case 4:
+ if (vtx->attr[2].emit == insert_2f_2 &&
+ vtx->attr[3].emit == insert_2f_2) {
+ if (vtx->attr[1].emit == insert_4ub_4f_rgba_4) {
+ if (vtx->attr[0].emit == insert_4f_viewport_4)
+ func = emit_viewport4_rgba4_st2_st2;
+ else if (vtx->attr[0].emit == insert_4f_4)
+ func = emit_xyzw4_rgba4_st2_st2;
+ }
+ else if (vtx->attr[1].emit == insert_4ub_4f_bgra_4 &&
+ vtx->attr[0].emit == insert_4f_viewport_4)
+ func = emit_viewport4_bgra4_st2_st2;
+ }
+ break;
+ }
+
+ vtx->emit = func;
+}
+
+/***********************************************************************
+ * Generic (non-codegen) functions for whole vertices or groups of
+ * vertices
+ */
+
+void _tnl_generic_emit( struct gl_context *ctx,
+ GLuint count,
+ GLubyte *v )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ struct tnl_clipspace_attr *a = vtx->attr;
+ const GLuint attr_count = vtx->attr_count;
+ const GLuint stride = vtx->vertex_size;
+ GLuint i, j;
+
+ for (i = 0 ; i < count ; i++, v += stride) {
+ for (j = 0; j < attr_count; j++) {
+ GLfloat *in = (GLfloat *)a[j].inputptr;
+ a[j].inputptr += a[j].inputstride;
+ a[j].emit( &a[j], v + a[j].vertoffset, in );
+ }
+ }
+}
+
+
+void _tnl_generic_interp( struct gl_context *ctx,
+ GLfloat t,
+ GLuint edst, GLuint eout, GLuint ein,
+ GLboolean force_boundary )
+{
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct vertex_buffer *VB = &tnl->vb;
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ const GLubyte *vin = vtx->vertex_buf + ein * vtx->vertex_size;
+ const GLubyte *vout = vtx->vertex_buf + eout * vtx->vertex_size;
+ GLubyte *vdst = vtx->vertex_buf + edst * vtx->vertex_size;
+ const struct tnl_clipspace_attr *a = vtx->attr;
+ const GLuint attr_count = vtx->attr_count;
+ GLuint j;
+ (void) force_boundary;
+
+ if (tnl->NeedNdcCoords) {
+ const GLfloat *dstclip = VB->ClipPtr->data[edst];
+ if (dstclip[3] != 0.0) {
+ const GLfloat w = 1.0f / dstclip[3];
+ GLfloat pos[4];
+
+ pos[0] = dstclip[0] * w;
+ pos[1] = dstclip[1] * w;
+ pos[2] = dstclip[2] * w;
+ pos[3] = w;
+
+ a[0].insert[4-1]( &a[0], vdst, pos );
+ }
+ }
+ else {
+ a[0].insert[4-1]( &a[0], vdst, VB->ClipPtr->data[edst] );
+ }
+
+
+ for (j = 1; j < attr_count; j++) {
+ GLfloat fin[4], fout[4], fdst[4];
+
+ a[j].extract( &a[j], fin, vin + a[j].vertoffset );
+ a[j].extract( &a[j], fout, vout + a[j].vertoffset );
+
+ INTERP_F( t, fdst[3], fout[3], fin[3] );
+ INTERP_F( t, fdst[2], fout[2], fin[2] );
+ INTERP_F( t, fdst[1], fout[1], fin[1] );
+ INTERP_F( t, fdst[0], fout[0], fin[0] );
+
+ a[j].insert[4-1]( &a[j], vdst + a[j].vertoffset, fdst );
+ }
+}
+
+
+/* Extract color attributes from one vertex and insert them into
+ * another. (Shortcircuit extract/insert with memcpy).
+ */
+void _tnl_generic_copy_pv( struct gl_context *ctx, GLuint edst, GLuint esrc )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ GLubyte *vsrc = vtx->vertex_buf + esrc * vtx->vertex_size;
+ GLubyte *vdst = vtx->vertex_buf + edst * vtx->vertex_size;
+ const struct tnl_clipspace_attr *a = vtx->attr;
+ const GLuint attr_count = vtx->attr_count;
+ GLuint j;
+
+ for (j = 0; j < attr_count; j++) {
+ if (a[j].attrib == VERT_ATTRIB_COLOR0 ||
+ a[j].attrib == VERT_ATTRIB_COLOR1) {
+
+ memcpy( vdst + a[j].vertoffset,
+ vsrc + a[j].vertoffset,
+ a[j].vertattrsize );
+ }
+ }
+}
+
+
+/* Helper functions for hardware which doesn't put back colors and/or
+ * edgeflags into vertices.
+ */
+void _tnl_generic_interp_extras( struct gl_context *ctx,
+ GLfloat t,
+ GLuint dst, GLuint out, GLuint in,
+ GLboolean force_boundary )
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+ /* If stride is zero, BackfaceColorPtr is constant across the VB, so
+ * there is no point interpolating between two values as they will
+ * be identical. In all other cases, this value is generated by
+ * t_vb_lighttmp.h and has a stride of 4 dwords.
+ */
+ if (VB->BackfaceColorPtr && VB->BackfaceColorPtr->stride) {
+ assert(VB->BackfaceColorPtr->stride == 4 * sizeof(GLfloat));
+
+ INTERP_4F( t,
+ VB->BackfaceColorPtr->data[dst],
+ VB->BackfaceColorPtr->data[out],
+ VB->BackfaceColorPtr->data[in] );
+ }
+
+ if (VB->BackfaceSecondaryColorPtr) {
+ assert(VB->BackfaceSecondaryColorPtr->stride == 4 * sizeof(GLfloat));
+
+ INTERP_3F( t,
+ VB->BackfaceSecondaryColorPtr->data[dst],
+ VB->BackfaceSecondaryColorPtr->data[out],
+ VB->BackfaceSecondaryColorPtr->data[in] );
+ }
+
+ if (VB->BackfaceIndexPtr) {
+ VB->BackfaceIndexPtr->data[dst][0] = LINTERP( t,
+ VB->BackfaceIndexPtr->data[out][0],
+ VB->BackfaceIndexPtr->data[in][0] );
+ }
+
+ if (VB->EdgeFlag) {
+ VB->EdgeFlag[dst] = VB->EdgeFlag[out] || force_boundary;
+ }
+
+ _tnl_generic_interp(ctx, t, dst, out, in, force_boundary);
+}
+
+void _tnl_generic_copy_pv_extras( struct gl_context *ctx,
+ GLuint dst, GLuint src )
+{
+ struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
+
+ /* See above comment:
+ */
+ if (VB->BackfaceColorPtr && VB->BackfaceColorPtr->stride) {
+ COPY_4FV( VB->BackfaceColorPtr->data[dst],
+ VB->BackfaceColorPtr->data[src] );
+ }
+
+ if (VB->BackfaceSecondaryColorPtr) {
+ COPY_4FV( VB->BackfaceSecondaryColorPtr->data[dst],
+ VB->BackfaceSecondaryColorPtr->data[src] );
+ }
+
+ if (VB->BackfaceIndexPtr) {
+ VB->BackfaceIndexPtr->data[dst][0] = VB->BackfaceIndexPtr->data[src][0];
+ }
+
+ _tnl_generic_copy_pv(ctx, dst, src);
+}
+
+
diff --git a/mesalib/src/mesa/tnl/t_vertex_sse.c b/mesalib/src/mesa/tnl/t_vertex_sse.c index 98058f3bd..f164cd77e 100644 --- a/mesalib/src/mesa/tnl/t_vertex_sse.c +++ b/mesalib/src/mesa/tnl/t_vertex_sse.c @@ -1,684 +1,684 @@ -/* - * Copyright 2003 Tungsten Graphics, inc. - * 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 <keithw@tungstengraphics.com> - */ - -#include "main/glheader.h" -#include "main/context.h" -#include "main/colormac.h" -#include "main/simple_list.h" -#include "main/enums.h" -#include "t_context.h" -#include "t_vertex.h" - -#if defined(USE_SSE_ASM) - -#include "x86/rtasm/x86sse.h" -#include "x86/common_x86_asm.h" - - -/** - * Number of bytes to allocate for generated SSE functions - */ -#define MAX_SSE_CODE_SIZE 1024 - - -#define X 0 -#define Y 1 -#define Z 2 -#define W 3 - - -struct x86_program { - struct x86_function func; - - GLcontext *ctx; - GLboolean inputs_safe; - GLboolean outputs_safe; - GLboolean have_sse2; - - struct x86_reg identity; - struct x86_reg chan0; -}; - - -static struct x86_reg get_identity( struct x86_program *p ) -{ - return p->identity; -} - -static void emit_load4f_4( struct x86_program *p, - struct x86_reg dest, - struct x86_reg arg0 ) -{ - sse_movups(&p->func, dest, arg0); -} - -static void emit_load4f_3( struct x86_program *p, - struct x86_reg dest, - struct x86_reg arg0 ) -{ - /* Have to jump through some hoops: - * - * c 0 0 0 - * c 0 0 1 - * 0 0 c 1 - * a b c 1 - */ - sse_movss(&p->func, dest, x86_make_disp(arg0, 8)); - sse_shufps(&p->func, dest, get_identity(p), SHUF(X,Y,Z,W) ); - sse_shufps(&p->func, dest, dest, SHUF(Y,Z,X,W) ); - sse_movlps(&p->func, dest, arg0); -} - -static void emit_load4f_2( struct x86_program *p, - struct x86_reg dest, - struct x86_reg arg0 ) -{ - /* Initialize from identity, then pull in low two words: - */ - sse_movups(&p->func, dest, get_identity(p)); - sse_movlps(&p->func, dest, arg0); -} - -static void emit_load4f_1( struct x86_program *p, - struct x86_reg dest, - struct x86_reg arg0 ) -{ - /* Pull in low word, then swizzle in identity */ - sse_movss(&p->func, dest, arg0); - sse_shufps(&p->func, dest, get_identity(p), SHUF(X,Y,Z,W) ); -} - - - -static void emit_load3f_3( struct x86_program *p, - struct x86_reg dest, - struct x86_reg arg0 ) -{ - /* Over-reads by 1 dword - potential SEGV if input is a vertex - * array. - */ - if (p->inputs_safe) { - sse_movups(&p->func, dest, arg0); - } - else { - /* c 0 0 0 - * c c c c - * a b c c - */ - sse_movss(&p->func, dest, x86_make_disp(arg0, 8)); - sse_shufps(&p->func, dest, dest, SHUF(X,X,X,X)); - sse_movlps(&p->func, dest, arg0); - } -} - -static void emit_load3f_2( struct x86_program *p, - struct x86_reg dest, - struct x86_reg arg0 ) -{ - emit_load4f_2(p, dest, arg0); -} - -static void emit_load3f_1( struct x86_program *p, - struct x86_reg dest, - struct x86_reg arg0 ) -{ - /* Loading from memory erases the upper bits. */ - sse_movss(&p->func, dest, arg0); -} - -static void emit_load2f_2( struct x86_program *p, - struct x86_reg dest, - struct x86_reg arg0 ) -{ - sse_movlps(&p->func, dest, arg0); -} - -static void emit_load2f_1( struct x86_program *p, - struct x86_reg dest, - struct x86_reg arg0 ) -{ - /* Loading from memory erases the upper bits. */ - sse_movss(&p->func, dest, arg0); -} - -static void emit_load1f_1( struct x86_program *p, - struct x86_reg dest, - struct x86_reg arg0 ) -{ - sse_movss(&p->func, dest, arg0); -} - -static void (*load[4][4])( struct x86_program *p, - struct x86_reg dest, - struct x86_reg arg0 ) = { - { emit_load1f_1, - emit_load1f_1, - emit_load1f_1, - emit_load1f_1 }, - - { emit_load2f_1, - emit_load2f_2, - emit_load2f_2, - emit_load2f_2 }, - - { emit_load3f_1, - emit_load3f_2, - emit_load3f_3, - emit_load3f_3 }, - - { emit_load4f_1, - emit_load4f_2, - emit_load4f_3, - emit_load4f_4 } -}; - -static void emit_load( struct x86_program *p, - struct x86_reg dest, - GLuint sz, - struct x86_reg src, - GLuint src_sz) -{ - load[sz-1][src_sz-1](p, dest, src); -} - -static void emit_store4f( struct x86_program *p, - struct x86_reg dest, - struct x86_reg arg0 ) -{ - sse_movups(&p->func, dest, arg0); -} - -static void emit_store3f( struct x86_program *p, - struct x86_reg dest, - struct x86_reg arg0 ) -{ - if (p->outputs_safe) { - /* Emit the extra dword anyway. This may hurt writecombining, - * may cause other problems. - */ - sse_movups(&p->func, dest, arg0); - } - else { - /* Alternate strategy - emit two, shuffle, emit one. - */ - sse_movlps(&p->func, dest, arg0); - sse_shufps(&p->func, arg0, arg0, SHUF(Z,Z,Z,Z) ); /* NOTE! destructive */ - sse_movss(&p->func, x86_make_disp(dest,8), arg0); - } -} - -static void emit_store2f( struct x86_program *p, - struct x86_reg dest, - struct x86_reg arg0 ) -{ - sse_movlps(&p->func, dest, arg0); -} - -static void emit_store1f( struct x86_program *p, - struct x86_reg dest, - struct x86_reg arg0 ) -{ - sse_movss(&p->func, dest, arg0); -} - - -static void (*store[4])( struct x86_program *p, - struct x86_reg dest, - struct x86_reg arg0 ) = -{ - emit_store1f, - emit_store2f, - emit_store3f, - emit_store4f -}; - -static void emit_store( struct x86_program *p, - struct x86_reg dest, - GLuint sz, - struct x86_reg temp ) - -{ - store[sz-1](p, dest, temp); -} - -static void emit_pack_store_4ub( struct x86_program *p, - struct x86_reg dest, - struct x86_reg temp ) -{ - /* Scale by 255.0 - */ - sse_mulps(&p->func, temp, p->chan0); - - if (p->have_sse2) { - sse2_cvtps2dq(&p->func, temp, temp); - sse2_packssdw(&p->func, temp, temp); - sse2_packuswb(&p->func, temp, temp); - sse_movss(&p->func, dest, temp); - } - else { - struct x86_reg mmx0 = x86_make_reg(file_MMX, 0); - struct x86_reg mmx1 = x86_make_reg(file_MMX, 1); - sse_cvtps2pi(&p->func, mmx0, temp); - sse_movhlps(&p->func, temp, temp); - sse_cvtps2pi(&p->func, mmx1, temp); - mmx_packssdw(&p->func, mmx0, mmx1); - mmx_packuswb(&p->func, mmx0, mmx0); - mmx_movd(&p->func, dest, mmx0); - } -} - -static GLint get_offset( const void *a, const void *b ) -{ - return (const char *)b - (const char *)a; -} - -/* Not much happens here. Eventually use this function to try and - * avoid saving/reloading the source pointers each vertex (if some of - * them can fit in registers). - */ -static void get_src_ptr( struct x86_program *p, - struct x86_reg srcREG, - struct x86_reg vtxREG, - struct tnl_clipspace_attr *a ) -{ - struct tnl_clipspace *vtx = GET_VERTEX_STATE(p->ctx); - struct x86_reg ptr_to_src = x86_make_disp(vtxREG, get_offset(vtx, &a->inputptr)); - - /* Load current a[j].inputptr - */ - x86_mov(&p->func, srcREG, ptr_to_src); -} - -static void update_src_ptr( struct x86_program *p, - struct x86_reg srcREG, - struct x86_reg vtxREG, - struct tnl_clipspace_attr *a ) -{ - if (a->inputstride) { - struct tnl_clipspace *vtx = GET_VERTEX_STATE(p->ctx); - struct x86_reg ptr_to_src = x86_make_disp(vtxREG, get_offset(vtx, &a->inputptr)); - - /* add a[j].inputstride (hardcoded value - could just as easily - * pull the stride value from memory each time). - */ - x86_lea(&p->func, srcREG, x86_make_disp(srcREG, a->inputstride)); - - /* save new value of a[j].inputptr - */ - x86_mov(&p->func, ptr_to_src, srcREG); - } -} - - -/* Lots of hardcoding - * - * EAX -- pointer to current output vertex - * ECX -- pointer to current attribute - * - */ -static GLboolean build_vertex_emit( struct x86_program *p ) -{ - GLcontext *ctx = p->ctx; - TNLcontext *tnl = TNL_CONTEXT(ctx); - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); - GLuint j = 0; - - struct x86_reg vertexEAX = x86_make_reg(file_REG32, reg_AX); - struct x86_reg srcECX = x86_make_reg(file_REG32, reg_CX); - struct x86_reg countEBP = x86_make_reg(file_REG32, reg_BP); - struct x86_reg vtxESI = x86_make_reg(file_REG32, reg_SI); - struct x86_reg temp = x86_make_reg(file_XMM, 0); - struct x86_reg vp0 = x86_make_reg(file_XMM, 1); - struct x86_reg vp1 = x86_make_reg(file_XMM, 2); - struct x86_reg temp2 = x86_make_reg(file_XMM, 3); - GLubyte *fixup, *label; - - /* Push a few regs? - */ - x86_push(&p->func, countEBP); - x86_push(&p->func, vtxESI); - - - /* Get vertex count, compare to zero - */ - x86_xor(&p->func, srcECX, srcECX); - x86_mov(&p->func, countEBP, x86_fn_arg(&p->func, 2)); - x86_cmp(&p->func, countEBP, srcECX); - fixup = x86_jcc_forward(&p->func, cc_E); - - /* Initialize destination register. - */ - x86_mov(&p->func, vertexEAX, x86_fn_arg(&p->func, 3)); - - /* Dereference ctx to get tnl, then vtx: - */ - x86_mov(&p->func, vtxESI, x86_fn_arg(&p->func, 1)); - x86_mov(&p->func, vtxESI, x86_make_disp(vtxESI, get_offset(ctx, &ctx->swtnl_context))); - vtxESI = x86_make_disp(vtxESI, get_offset(tnl, &tnl->clipspace)); - - - /* Possibly load vp0, vp1 for viewport calcs: - */ - if (vtx->need_viewport) { - sse_movups(&p->func, vp0, x86_make_disp(vtxESI, get_offset(vtx, &vtx->vp_scale[0]))); - sse_movups(&p->func, vp1, x86_make_disp(vtxESI, get_offset(vtx, &vtx->vp_xlate[0]))); - } - - /* always load, needed or not: - */ - sse_movups(&p->func, p->chan0, x86_make_disp(vtxESI, get_offset(vtx, &vtx->chan_scale[0]))); - sse_movups(&p->func, p->identity, x86_make_disp(vtxESI, get_offset(vtx, &vtx->identity[0]))); - - /* Note address for loop jump */ - label = x86_get_label(&p->func); - - /* Emit code for each of the attributes. Currently routes - * everything through SSE registers, even when it might be more - * efficient to stick with regular old x86. No optimization or - * other tricks - enough new ground to cover here just getting - * things working. - */ - while (j < vtx->attr_count) { - struct tnl_clipspace_attr *a = &vtx->attr[j]; - struct x86_reg dest = x86_make_disp(vertexEAX, a->vertoffset); - - /* Now, load an XMM reg from src, perhaps transform, then save. - * Could be shortcircuited in specific cases: - */ - switch (a->format) { - case EMIT_1F: - get_src_ptr(p, srcECX, vtxESI, a); - emit_load(p, temp, 1, x86_deref(srcECX), a->inputsize); - emit_store(p, dest, 1, temp); - update_src_ptr(p, srcECX, vtxESI, a); - break; - case EMIT_2F: - get_src_ptr(p, srcECX, vtxESI, a); - emit_load(p, temp, 2, x86_deref(srcECX), a->inputsize); - emit_store(p, dest, 2, temp); - update_src_ptr(p, srcECX, vtxESI, a); - break; - case EMIT_3F: - /* Potentially the worst case - hardcode 2+1 copying: - */ - if (0) { - get_src_ptr(p, srcECX, vtxESI, a); - emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize); - emit_store(p, dest, 3, temp); - update_src_ptr(p, srcECX, vtxESI, a); - } - else { - get_src_ptr(p, srcECX, vtxESI, a); - emit_load(p, temp, 2, x86_deref(srcECX), a->inputsize); - emit_store(p, dest, 2, temp); - if (a->inputsize > 2) { - emit_load(p, temp, 1, x86_make_disp(srcECX, 8), 1); - emit_store(p, x86_make_disp(dest,8), 1, temp); - } - else { - sse_movss(&p->func, x86_make_disp(dest,8), get_identity(p)); - } - update_src_ptr(p, srcECX, vtxESI, a); - } - break; - case EMIT_4F: - get_src_ptr(p, srcECX, vtxESI, a); - emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize); - emit_store(p, dest, 4, temp); - update_src_ptr(p, srcECX, vtxESI, a); - break; - case EMIT_2F_VIEWPORT: - get_src_ptr(p, srcECX, vtxESI, a); - emit_load(p, temp, 2, x86_deref(srcECX), a->inputsize); - sse_mulps(&p->func, temp, vp0); - sse_addps(&p->func, temp, vp1); - emit_store(p, dest, 2, temp); - update_src_ptr(p, srcECX, vtxESI, a); - break; - case EMIT_3F_VIEWPORT: - get_src_ptr(p, srcECX, vtxESI, a); - emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize); - sse_mulps(&p->func, temp, vp0); - sse_addps(&p->func, temp, vp1); - emit_store(p, dest, 3, temp); - update_src_ptr(p, srcECX, vtxESI, a); - break; - case EMIT_4F_VIEWPORT: - get_src_ptr(p, srcECX, vtxESI, a); - emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize); - sse_mulps(&p->func, temp, vp0); - sse_addps(&p->func, temp, vp1); - emit_store(p, dest, 4, temp); - update_src_ptr(p, srcECX, vtxESI, a); - break; - case EMIT_3F_XYW: - get_src_ptr(p, srcECX, vtxESI, a); - emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize); - sse_shufps(&p->func, temp, temp, SHUF(X,Y,W,Z)); - emit_store(p, dest, 3, temp); - update_src_ptr(p, srcECX, vtxESI, a); - break; - - case EMIT_1UB_1F: - /* Test for PAD3 + 1UB: - */ - if (j > 0 && - a[-1].vertoffset + a[-1].vertattrsize <= a->vertoffset - 3) - { - get_src_ptr(p, srcECX, vtxESI, a); - emit_load(p, temp, 1, x86_deref(srcECX), a->inputsize); - sse_shufps(&p->func, temp, temp, SHUF(X,X,X,X)); - emit_pack_store_4ub(p, x86_make_disp(dest, -3), temp); /* overkill! */ - update_src_ptr(p, srcECX, vtxESI, a); - } - else { - printf("Can't emit 1ub %x %x %d\n", a->vertoffset, a[-1].vertoffset, a[-1].vertattrsize ); - return GL_FALSE; - } - break; - case EMIT_3UB_3F_RGB: - case EMIT_3UB_3F_BGR: - /* Test for 3UB + PAD1: - */ - if (j == vtx->attr_count - 1 || - a[1].vertoffset >= a->vertoffset + 4) { - get_src_ptr(p, srcECX, vtxESI, a); - emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize); - if (a->format == EMIT_3UB_3F_BGR) - sse_shufps(&p->func, temp, temp, SHUF(Z,Y,X,W)); - emit_pack_store_4ub(p, dest, temp); - update_src_ptr(p, srcECX, vtxESI, a); - } - /* Test for 3UB + 1UB: - */ - else if (j < vtx->attr_count - 1 && - a[1].format == EMIT_1UB_1F && - a[1].vertoffset == a->vertoffset + 3) { - get_src_ptr(p, srcECX, vtxESI, a); - emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize); - update_src_ptr(p, srcECX, vtxESI, a); - - /* Make room for incoming value: - */ - sse_shufps(&p->func, temp, temp, SHUF(W,X,Y,Z)); - - get_src_ptr(p, srcECX, vtxESI, &a[1]); - emit_load(p, temp2, 1, x86_deref(srcECX), a[1].inputsize); - sse_movss(&p->func, temp, temp2); - update_src_ptr(p, srcECX, vtxESI, &a[1]); - - /* Rearrange and possibly do BGR conversion: - */ - if (a->format == EMIT_3UB_3F_BGR) - sse_shufps(&p->func, temp, temp, SHUF(W,Z,Y,X)); - else - sse_shufps(&p->func, temp, temp, SHUF(Y,Z,W,X)); - - emit_pack_store_4ub(p, dest, temp); - j++; /* NOTE: two attrs consumed */ - } - else { - printf("Can't emit 3ub\n"); - return GL_FALSE; /* add this later */ - } - break; - - case EMIT_4UB_4F_RGBA: - get_src_ptr(p, srcECX, vtxESI, a); - emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize); - emit_pack_store_4ub(p, dest, temp); - update_src_ptr(p, srcECX, vtxESI, a); - break; - case EMIT_4UB_4F_BGRA: - get_src_ptr(p, srcECX, vtxESI, a); - emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize); - sse_shufps(&p->func, temp, temp, SHUF(Z,Y,X,W)); - emit_pack_store_4ub(p, dest, temp); - update_src_ptr(p, srcECX, vtxESI, a); - break; - case EMIT_4UB_4F_ARGB: - get_src_ptr(p, srcECX, vtxESI, a); - emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize); - sse_shufps(&p->func, temp, temp, SHUF(W,X,Y,Z)); - emit_pack_store_4ub(p, dest, temp); - update_src_ptr(p, srcECX, vtxESI, a); - break; - case EMIT_4UB_4F_ABGR: - get_src_ptr(p, srcECX, vtxESI, a); - emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize); - sse_shufps(&p->func, temp, temp, SHUF(W,Z,Y,X)); - emit_pack_store_4ub(p, dest, temp); - update_src_ptr(p, srcECX, vtxESI, a); - break; - case EMIT_4CHAN_4F_RGBA: - switch (CHAN_TYPE) { - case GL_UNSIGNED_BYTE: - get_src_ptr(p, srcECX, vtxESI, a); - emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize); - emit_pack_store_4ub(p, dest, temp); - update_src_ptr(p, srcECX, vtxESI, a); - break; - case GL_FLOAT: - get_src_ptr(p, srcECX, vtxESI, a); - emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize); - emit_store(p, dest, 4, temp); - update_src_ptr(p, srcECX, vtxESI, a); - break; - case GL_UNSIGNED_SHORT: - default: - printf("unknown CHAN_TYPE %s\n", _mesa_lookup_enum_by_nr(CHAN_TYPE)); - return GL_FALSE; - } - break; - default: - printf("unknown a[%d].format %d\n", j, a->format); - return GL_FALSE; /* catch any new opcodes */ - } - - /* Increment j by at least 1 - may have been incremented above also: - */ - j++; - } - - /* Next vertex: - */ - x86_lea(&p->func, vertexEAX, x86_make_disp(vertexEAX, vtx->vertex_size)); - - /* decr count, loop if not zero - */ - x86_dec(&p->func, countEBP); - x86_test(&p->func, countEBP, countEBP); - x86_jcc(&p->func, cc_NZ, label); - - /* Exit mmx state? - */ - if (p->func.need_emms) - mmx_emms(&p->func); - - /* Land forward jump here: - */ - x86_fixup_fwd_jump(&p->func, fixup); - - /* Pop regs and return - */ - x86_pop(&p->func, x86_get_base_reg(vtxESI)); - x86_pop(&p->func, countEBP); - x86_ret(&p->func); - - assert(!vtx->emit); - vtx->emit = (tnl_emit_func)x86_get_func(&p->func); - - assert( (char *) p->func.csr - (char *) p->func.store <= MAX_SSE_CODE_SIZE ); - return GL_TRUE; -} - - - -void _tnl_generate_sse_emit( GLcontext *ctx ) -{ - struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx); - struct x86_program p; - - if (!cpu_has_xmm) { - vtx->codegen_emit = NULL; - return; - } - - memset(&p, 0, sizeof(p)); - - p.ctx = ctx; - p.inputs_safe = 0; /* for now */ - p.outputs_safe = 0; /* for now */ - p.have_sse2 = cpu_has_xmm2; - p.identity = x86_make_reg(file_XMM, 6); - p.chan0 = x86_make_reg(file_XMM, 7); - - if (!x86_init_func_size(&p.func, MAX_SSE_CODE_SIZE)) { - vtx->emit = NULL; - return; - } - - if (build_vertex_emit(&p)) { - _tnl_register_fastpath( vtx, GL_TRUE ); - } - else { - /* Note the failure so that we don't keep trying to codegen an - * impossible state: - */ - _tnl_register_fastpath( vtx, GL_FALSE ); - x86_release_func(&p.func); - } -} - -#else - -void _tnl_generate_sse_emit( GLcontext *ctx ) -{ - /* Dummy version for when USE_SSE_ASM not defined */ -} - -#endif +/*
+ * Copyright 2003 Tungsten Graphics, inc.
+ * 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 <keithw@tungstengraphics.com>
+ */
+
+#include "main/glheader.h"
+#include "main/context.h"
+#include "main/colormac.h"
+#include "main/simple_list.h"
+#include "main/enums.h"
+#include "t_context.h"
+#include "t_vertex.h"
+
+#if defined(USE_SSE_ASM)
+
+#include "x86/rtasm/x86sse.h"
+#include "x86/common_x86_asm.h"
+
+
+/**
+ * Number of bytes to allocate for generated SSE functions
+ */
+#define MAX_SSE_CODE_SIZE 1024
+
+
+#define X 0
+#define Y 1
+#define Z 2
+#define W 3
+
+
+struct x86_program {
+ struct x86_function func;
+
+ struct gl_context *ctx;
+ GLboolean inputs_safe;
+ GLboolean outputs_safe;
+ GLboolean have_sse2;
+
+ struct x86_reg identity;
+ struct x86_reg chan0;
+};
+
+
+static struct x86_reg get_identity( struct x86_program *p )
+{
+ return p->identity;
+}
+
+static void emit_load4f_4( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ sse_movups(&p->func, dest, arg0);
+}
+
+static void emit_load4f_3( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ /* Have to jump through some hoops:
+ *
+ * c 0 0 0
+ * c 0 0 1
+ * 0 0 c 1
+ * a b c 1
+ */
+ sse_movss(&p->func, dest, x86_make_disp(arg0, 8));
+ sse_shufps(&p->func, dest, get_identity(p), SHUF(X,Y,Z,W) );
+ sse_shufps(&p->func, dest, dest, SHUF(Y,Z,X,W) );
+ sse_movlps(&p->func, dest, arg0);
+}
+
+static void emit_load4f_2( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ /* Initialize from identity, then pull in low two words:
+ */
+ sse_movups(&p->func, dest, get_identity(p));
+ sse_movlps(&p->func, dest, arg0);
+}
+
+static void emit_load4f_1( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ /* Pull in low word, then swizzle in identity */
+ sse_movss(&p->func, dest, arg0);
+ sse_shufps(&p->func, dest, get_identity(p), SHUF(X,Y,Z,W) );
+}
+
+
+
+static void emit_load3f_3( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ /* Over-reads by 1 dword - potential SEGV if input is a vertex
+ * array.
+ */
+ if (p->inputs_safe) {
+ sse_movups(&p->func, dest, arg0);
+ }
+ else {
+ /* c 0 0 0
+ * c c c c
+ * a b c c
+ */
+ sse_movss(&p->func, dest, x86_make_disp(arg0, 8));
+ sse_shufps(&p->func, dest, dest, SHUF(X,X,X,X));
+ sse_movlps(&p->func, dest, arg0);
+ }
+}
+
+static void emit_load3f_2( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ emit_load4f_2(p, dest, arg0);
+}
+
+static void emit_load3f_1( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ /* Loading from memory erases the upper bits. */
+ sse_movss(&p->func, dest, arg0);
+}
+
+static void emit_load2f_2( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ sse_movlps(&p->func, dest, arg0);
+}
+
+static void emit_load2f_1( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ /* Loading from memory erases the upper bits. */
+ sse_movss(&p->func, dest, arg0);
+}
+
+static void emit_load1f_1( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ sse_movss(&p->func, dest, arg0);
+}
+
+static void (*load[4][4])( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 ) = {
+ { emit_load1f_1,
+ emit_load1f_1,
+ emit_load1f_1,
+ emit_load1f_1 },
+
+ { emit_load2f_1,
+ emit_load2f_2,
+ emit_load2f_2,
+ emit_load2f_2 },
+
+ { emit_load3f_1,
+ emit_load3f_2,
+ emit_load3f_3,
+ emit_load3f_3 },
+
+ { emit_load4f_1,
+ emit_load4f_2,
+ emit_load4f_3,
+ emit_load4f_4 }
+};
+
+static void emit_load( struct x86_program *p,
+ struct x86_reg dest,
+ GLuint sz,
+ struct x86_reg src,
+ GLuint src_sz)
+{
+ load[sz-1][src_sz-1](p, dest, src);
+}
+
+static void emit_store4f( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ sse_movups(&p->func, dest, arg0);
+}
+
+static void emit_store3f( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ if (p->outputs_safe) {
+ /* Emit the extra dword anyway. This may hurt writecombining,
+ * may cause other problems.
+ */
+ sse_movups(&p->func, dest, arg0);
+ }
+ else {
+ /* Alternate strategy - emit two, shuffle, emit one.
+ */
+ sse_movlps(&p->func, dest, arg0);
+ sse_shufps(&p->func, arg0, arg0, SHUF(Z,Z,Z,Z) ); /* NOTE! destructive */
+ sse_movss(&p->func, x86_make_disp(dest,8), arg0);
+ }
+}
+
+static void emit_store2f( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ sse_movlps(&p->func, dest, arg0);
+}
+
+static void emit_store1f( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 )
+{
+ sse_movss(&p->func, dest, arg0);
+}
+
+
+static void (*store[4])( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg arg0 ) =
+{
+ emit_store1f,
+ emit_store2f,
+ emit_store3f,
+ emit_store4f
+};
+
+static void emit_store( struct x86_program *p,
+ struct x86_reg dest,
+ GLuint sz,
+ struct x86_reg temp )
+
+{
+ store[sz-1](p, dest, temp);
+}
+
+static void emit_pack_store_4ub( struct x86_program *p,
+ struct x86_reg dest,
+ struct x86_reg temp )
+{
+ /* Scale by 255.0
+ */
+ sse_mulps(&p->func, temp, p->chan0);
+
+ if (p->have_sse2) {
+ sse2_cvtps2dq(&p->func, temp, temp);
+ sse2_packssdw(&p->func, temp, temp);
+ sse2_packuswb(&p->func, temp, temp);
+ sse_movss(&p->func, dest, temp);
+ }
+ else {
+ struct x86_reg mmx0 = x86_make_reg(file_MMX, 0);
+ struct x86_reg mmx1 = x86_make_reg(file_MMX, 1);
+ sse_cvtps2pi(&p->func, mmx0, temp);
+ sse_movhlps(&p->func, temp, temp);
+ sse_cvtps2pi(&p->func, mmx1, temp);
+ mmx_packssdw(&p->func, mmx0, mmx1);
+ mmx_packuswb(&p->func, mmx0, mmx0);
+ mmx_movd(&p->func, dest, mmx0);
+ }
+}
+
+static GLint get_offset( const void *a, const void *b )
+{
+ return (const char *)b - (const char *)a;
+}
+
+/* Not much happens here. Eventually use this function to try and
+ * avoid saving/reloading the source pointers each vertex (if some of
+ * them can fit in registers).
+ */
+static void get_src_ptr( struct x86_program *p,
+ struct x86_reg srcREG,
+ struct x86_reg vtxREG,
+ struct tnl_clipspace_attr *a )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(p->ctx);
+ struct x86_reg ptr_to_src = x86_make_disp(vtxREG, get_offset(vtx, &a->inputptr));
+
+ /* Load current a[j].inputptr
+ */
+ x86_mov(&p->func, srcREG, ptr_to_src);
+}
+
+static void update_src_ptr( struct x86_program *p,
+ struct x86_reg srcREG,
+ struct x86_reg vtxREG,
+ struct tnl_clipspace_attr *a )
+{
+ if (a->inputstride) {
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(p->ctx);
+ struct x86_reg ptr_to_src = x86_make_disp(vtxREG, get_offset(vtx, &a->inputptr));
+
+ /* add a[j].inputstride (hardcoded value - could just as easily
+ * pull the stride value from memory each time).
+ */
+ x86_lea(&p->func, srcREG, x86_make_disp(srcREG, a->inputstride));
+
+ /* save new value of a[j].inputptr
+ */
+ x86_mov(&p->func, ptr_to_src, srcREG);
+ }
+}
+
+
+/* Lots of hardcoding
+ *
+ * EAX -- pointer to current output vertex
+ * ECX -- pointer to current attribute
+ *
+ */
+static GLboolean build_vertex_emit( struct x86_program *p )
+{
+ struct gl_context *ctx = p->ctx;
+ TNLcontext *tnl = TNL_CONTEXT(ctx);
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ GLuint j = 0;
+
+ struct x86_reg vertexEAX = x86_make_reg(file_REG32, reg_AX);
+ struct x86_reg srcECX = x86_make_reg(file_REG32, reg_CX);
+ struct x86_reg countEBP = x86_make_reg(file_REG32, reg_BP);
+ struct x86_reg vtxESI = x86_make_reg(file_REG32, reg_SI);
+ struct x86_reg temp = x86_make_reg(file_XMM, 0);
+ struct x86_reg vp0 = x86_make_reg(file_XMM, 1);
+ struct x86_reg vp1 = x86_make_reg(file_XMM, 2);
+ struct x86_reg temp2 = x86_make_reg(file_XMM, 3);
+ GLubyte *fixup, *label;
+
+ /* Push a few regs?
+ */
+ x86_push(&p->func, countEBP);
+ x86_push(&p->func, vtxESI);
+
+
+ /* Get vertex count, compare to zero
+ */
+ x86_xor(&p->func, srcECX, srcECX);
+ x86_mov(&p->func, countEBP, x86_fn_arg(&p->func, 2));
+ x86_cmp(&p->func, countEBP, srcECX);
+ fixup = x86_jcc_forward(&p->func, cc_E);
+
+ /* Initialize destination register.
+ */
+ x86_mov(&p->func, vertexEAX, x86_fn_arg(&p->func, 3));
+
+ /* Dereference ctx to get tnl, then vtx:
+ */
+ x86_mov(&p->func, vtxESI, x86_fn_arg(&p->func, 1));
+ x86_mov(&p->func, vtxESI, x86_make_disp(vtxESI, get_offset(ctx, &ctx->swtnl_context)));
+ vtxESI = x86_make_disp(vtxESI, get_offset(tnl, &tnl->clipspace));
+
+
+ /* Possibly load vp0, vp1 for viewport calcs:
+ */
+ if (vtx->need_viewport) {
+ sse_movups(&p->func, vp0, x86_make_disp(vtxESI, get_offset(vtx, &vtx->vp_scale[0])));
+ sse_movups(&p->func, vp1, x86_make_disp(vtxESI, get_offset(vtx, &vtx->vp_xlate[0])));
+ }
+
+ /* always load, needed or not:
+ */
+ sse_movups(&p->func, p->chan0, x86_make_disp(vtxESI, get_offset(vtx, &vtx->chan_scale[0])));
+ sse_movups(&p->func, p->identity, x86_make_disp(vtxESI, get_offset(vtx, &vtx->identity[0])));
+
+ /* Note address for loop jump */
+ label = x86_get_label(&p->func);
+
+ /* Emit code for each of the attributes. Currently routes
+ * everything through SSE registers, even when it might be more
+ * efficient to stick with regular old x86. No optimization or
+ * other tricks - enough new ground to cover here just getting
+ * things working.
+ */
+ while (j < vtx->attr_count) {
+ struct tnl_clipspace_attr *a = &vtx->attr[j];
+ struct x86_reg dest = x86_make_disp(vertexEAX, a->vertoffset);
+
+ /* Now, load an XMM reg from src, perhaps transform, then save.
+ * Could be shortcircuited in specific cases:
+ */
+ switch (a->format) {
+ case EMIT_1F:
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 1, x86_deref(srcECX), a->inputsize);
+ emit_store(p, dest, 1, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ break;
+ case EMIT_2F:
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 2, x86_deref(srcECX), a->inputsize);
+ emit_store(p, dest, 2, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ break;
+ case EMIT_3F:
+ /* Potentially the worst case - hardcode 2+1 copying:
+ */
+ if (0) {
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize);
+ emit_store(p, dest, 3, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ }
+ else {
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 2, x86_deref(srcECX), a->inputsize);
+ emit_store(p, dest, 2, temp);
+ if (a->inputsize > 2) {
+ emit_load(p, temp, 1, x86_make_disp(srcECX, 8), 1);
+ emit_store(p, x86_make_disp(dest,8), 1, temp);
+ }
+ else {
+ sse_movss(&p->func, x86_make_disp(dest,8), get_identity(p));
+ }
+ update_src_ptr(p, srcECX, vtxESI, a);
+ }
+ break;
+ case EMIT_4F:
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ emit_store(p, dest, 4, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ break;
+ case EMIT_2F_VIEWPORT:
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 2, x86_deref(srcECX), a->inputsize);
+ sse_mulps(&p->func, temp, vp0);
+ sse_addps(&p->func, temp, vp1);
+ emit_store(p, dest, 2, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ break;
+ case EMIT_3F_VIEWPORT:
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize);
+ sse_mulps(&p->func, temp, vp0);
+ sse_addps(&p->func, temp, vp1);
+ emit_store(p, dest, 3, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ break;
+ case EMIT_4F_VIEWPORT:
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ sse_mulps(&p->func, temp, vp0);
+ sse_addps(&p->func, temp, vp1);
+ emit_store(p, dest, 4, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ break;
+ case EMIT_3F_XYW:
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ sse_shufps(&p->func, temp, temp, SHUF(X,Y,W,Z));
+ emit_store(p, dest, 3, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ break;
+
+ case EMIT_1UB_1F:
+ /* Test for PAD3 + 1UB:
+ */
+ if (j > 0 &&
+ a[-1].vertoffset + a[-1].vertattrsize <= a->vertoffset - 3)
+ {
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 1, x86_deref(srcECX), a->inputsize);
+ sse_shufps(&p->func, temp, temp, SHUF(X,X,X,X));
+ emit_pack_store_4ub(p, x86_make_disp(dest, -3), temp); /* overkill! */
+ update_src_ptr(p, srcECX, vtxESI, a);
+ }
+ else {
+ printf("Can't emit 1ub %x %x %d\n", a->vertoffset, a[-1].vertoffset, a[-1].vertattrsize );
+ return GL_FALSE;
+ }
+ break;
+ case EMIT_3UB_3F_RGB:
+ case EMIT_3UB_3F_BGR:
+ /* Test for 3UB + PAD1:
+ */
+ if (j == vtx->attr_count - 1 ||
+ a[1].vertoffset >= a->vertoffset + 4) {
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize);
+ if (a->format == EMIT_3UB_3F_BGR)
+ sse_shufps(&p->func, temp, temp, SHUF(Z,Y,X,W));
+ emit_pack_store_4ub(p, dest, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ }
+ /* Test for 3UB + 1UB:
+ */
+ else if (j < vtx->attr_count - 1 &&
+ a[1].format == EMIT_1UB_1F &&
+ a[1].vertoffset == a->vertoffset + 3) {
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 3, x86_deref(srcECX), a->inputsize);
+ update_src_ptr(p, srcECX, vtxESI, a);
+
+ /* Make room for incoming value:
+ */
+ sse_shufps(&p->func, temp, temp, SHUF(W,X,Y,Z));
+
+ get_src_ptr(p, srcECX, vtxESI, &a[1]);
+ emit_load(p, temp2, 1, x86_deref(srcECX), a[1].inputsize);
+ sse_movss(&p->func, temp, temp2);
+ update_src_ptr(p, srcECX, vtxESI, &a[1]);
+
+ /* Rearrange and possibly do BGR conversion:
+ */
+ if (a->format == EMIT_3UB_3F_BGR)
+ sse_shufps(&p->func, temp, temp, SHUF(W,Z,Y,X));
+ else
+ sse_shufps(&p->func, temp, temp, SHUF(Y,Z,W,X));
+
+ emit_pack_store_4ub(p, dest, temp);
+ j++; /* NOTE: two attrs consumed */
+ }
+ else {
+ printf("Can't emit 3ub\n");
+ return GL_FALSE; /* add this later */
+ }
+ break;
+
+ case EMIT_4UB_4F_RGBA:
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ emit_pack_store_4ub(p, dest, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ break;
+ case EMIT_4UB_4F_BGRA:
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ sse_shufps(&p->func, temp, temp, SHUF(Z,Y,X,W));
+ emit_pack_store_4ub(p, dest, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ break;
+ case EMIT_4UB_4F_ARGB:
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ sse_shufps(&p->func, temp, temp, SHUF(W,X,Y,Z));
+ emit_pack_store_4ub(p, dest, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ break;
+ case EMIT_4UB_4F_ABGR:
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ sse_shufps(&p->func, temp, temp, SHUF(W,Z,Y,X));
+ emit_pack_store_4ub(p, dest, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ break;
+ case EMIT_4CHAN_4F_RGBA:
+ switch (CHAN_TYPE) {
+ case GL_UNSIGNED_BYTE:
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ emit_pack_store_4ub(p, dest, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ break;
+ case GL_FLOAT:
+ get_src_ptr(p, srcECX, vtxESI, a);
+ emit_load(p, temp, 4, x86_deref(srcECX), a->inputsize);
+ emit_store(p, dest, 4, temp);
+ update_src_ptr(p, srcECX, vtxESI, a);
+ break;
+ case GL_UNSIGNED_SHORT:
+ default:
+ printf("unknown CHAN_TYPE %s\n", _mesa_lookup_enum_by_nr(CHAN_TYPE));
+ return GL_FALSE;
+ }
+ break;
+ default:
+ printf("unknown a[%d].format %d\n", j, a->format);
+ return GL_FALSE; /* catch any new opcodes */
+ }
+
+ /* Increment j by at least 1 - may have been incremented above also:
+ */
+ j++;
+ }
+
+ /* Next vertex:
+ */
+ x86_lea(&p->func, vertexEAX, x86_make_disp(vertexEAX, vtx->vertex_size));
+
+ /* decr count, loop if not zero
+ */
+ x86_dec(&p->func, countEBP);
+ x86_test(&p->func, countEBP, countEBP);
+ x86_jcc(&p->func, cc_NZ, label);
+
+ /* Exit mmx state?
+ */
+ if (p->func.need_emms)
+ mmx_emms(&p->func);
+
+ /* Land forward jump here:
+ */
+ x86_fixup_fwd_jump(&p->func, fixup);
+
+ /* Pop regs and return
+ */
+ x86_pop(&p->func, x86_get_base_reg(vtxESI));
+ x86_pop(&p->func, countEBP);
+ x86_ret(&p->func);
+
+ assert(!vtx->emit);
+ vtx->emit = (tnl_emit_func)x86_get_func(&p->func);
+
+ assert( (char *) p->func.csr - (char *) p->func.store <= MAX_SSE_CODE_SIZE );
+ return GL_TRUE;
+}
+
+
+
+void _tnl_generate_sse_emit( struct gl_context *ctx )
+{
+ struct tnl_clipspace *vtx = GET_VERTEX_STATE(ctx);
+ struct x86_program p;
+
+ if (!cpu_has_xmm) {
+ vtx->codegen_emit = NULL;
+ return;
+ }
+
+ memset(&p, 0, sizeof(p));
+
+ p.ctx = ctx;
+ p.inputs_safe = 0; /* for now */
+ p.outputs_safe = 0; /* for now */
+ p.have_sse2 = cpu_has_xmm2;
+ p.identity = x86_make_reg(file_XMM, 6);
+ p.chan0 = x86_make_reg(file_XMM, 7);
+
+ if (!x86_init_func_size(&p.func, MAX_SSE_CODE_SIZE)) {
+ vtx->emit = NULL;
+ return;
+ }
+
+ if (build_vertex_emit(&p)) {
+ _tnl_register_fastpath( vtx, GL_TRUE );
+ }
+ else {
+ /* Note the failure so that we don't keep trying to codegen an
+ * impossible state:
+ */
+ _tnl_register_fastpath( vtx, GL_FALSE );
+ x86_release_func(&p.func);
+ }
+}
+
+#else
+
+void _tnl_generate_sse_emit( struct gl_context *ctx )
+{
+ /* Dummy version for when USE_SSE_ASM not defined */
+}
+
+#endif
diff --git a/mesalib/src/mesa/tnl/t_vp_build.c b/mesalib/src/mesa/tnl/t_vp_build.c index 735937bbe..d0bada3bc 100644 --- a/mesalib/src/mesa/tnl/t_vp_build.c +++ b/mesalib/src/mesa/tnl/t_vp_build.c @@ -1,60 +1,60 @@ -/* - * Mesa 3-D graphics library - * Version: 7.1 - * - * Copyright (C) 2007 Tungsten Graphics 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 - * TUNGSTEN GRAPHICS 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 t_vp_build.c - * Create a vertex program to execute the current fixed function T&L pipeline. - * \author Keith Whitwell - */ - - -#include "main/glheader.h" -#include "main/ffvertex_prog.h" -#include "main/dd.h" -#include "t_vp_build.h" - - -/** - * XXX This should go away someday, but still referenced by some drivers... - */ -void _tnl_UpdateFixedFunctionProgram( GLcontext *ctx ) -{ - const struct gl_vertex_program *prev = ctx->VertexProgram._Current; - - if (!ctx->VertexProgram._Current || - ctx->VertexProgram._Current == ctx->VertexProgram._TnlProgram) { - ctx->VertexProgram._Current - = ctx->VertexProgram._TnlProgram - = _mesa_get_fixed_func_vertex_program(ctx); - } - - /* Tell the driver about the change. Could define a new target for - * this? - */ - if (ctx->VertexProgram._Current != prev && ctx->Driver.BindProgram) { - ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB, - (struct gl_program *) ctx->VertexProgram._Current); - } -} +/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 2007 Tungsten Graphics 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
+ * TUNGSTEN GRAPHICS 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 t_vp_build.c
+ * Create a vertex program to execute the current fixed function T&L pipeline.
+ * \author Keith Whitwell
+ */
+
+
+#include "main/glheader.h"
+#include "main/ffvertex_prog.h"
+#include "main/dd.h"
+#include "t_vp_build.h"
+
+
+/**
+ * XXX This should go away someday, but still referenced by some drivers...
+ */
+void _tnl_UpdateFixedFunctionProgram( struct gl_context *ctx )
+{
+ const struct gl_vertex_program *prev = ctx->VertexProgram._Current;
+
+ if (!ctx->VertexProgram._Current ||
+ ctx->VertexProgram._Current == ctx->VertexProgram._TnlProgram) {
+ ctx->VertexProgram._Current
+ = ctx->VertexProgram._TnlProgram
+ = _mesa_get_fixed_func_vertex_program(ctx);
+ }
+
+ /* Tell the driver about the change. Could define a new target for
+ * this?
+ */
+ if (ctx->VertexProgram._Current != prev && ctx->Driver.BindProgram) {
+ ctx->Driver.BindProgram(ctx, GL_VERTEX_PROGRAM_ARB,
+ (struct gl_program *) ctx->VertexProgram._Current);
+ }
+}
diff --git a/mesalib/src/mesa/tnl/t_vp_build.h b/mesalib/src/mesa/tnl/t_vp_build.h index d6ebc66c0..e5133e052 100644 --- a/mesalib/src/mesa/tnl/t_vp_build.h +++ b/mesalib/src/mesa/tnl/t_vp_build.h @@ -1,42 +1,42 @@ -/* - * Mesa 3-D graphics library - * Version: 6.3 - * - * Copyright (C) 2005 Tungsten Graphics 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 - * TUNGSTEN GRAPHICS 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_VP_BUILD_H -#define T_VP_BUILD_H - -#include "main/mtypes.h" - -#define TNL_FIXED_FUNCTION_STATE_FLAGS (_NEW_PROGRAM | \ - _NEW_LIGHT | \ - _NEW_TEXTURE | \ - _NEW_TEXTURE_MATRIX | \ - _NEW_TRANSFORM | \ - _NEW_FOG | \ - _NEW_POINT) - -extern void _tnl_UpdateFixedFunctionProgram( GLcontext *ctx ); - -#endif +/*
+ * Mesa 3-D graphics library
+ * Version: 6.3
+ *
+ * Copyright (C) 2005 Tungsten Graphics 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
+ * TUNGSTEN GRAPHICS 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_VP_BUILD_H
+#define T_VP_BUILD_H
+
+#include "main/mtypes.h"
+
+#define TNL_FIXED_FUNCTION_STATE_FLAGS (_NEW_PROGRAM | \
+ _NEW_LIGHT | \
+ _NEW_TEXTURE | \
+ _NEW_TEXTURE_MATRIX | \
+ _NEW_TRANSFORM | \
+ _NEW_FOG | \
+ _NEW_POINT)
+
+extern void _tnl_UpdateFixedFunctionProgram( struct gl_context *ctx );
+
+#endif
diff --git a/mesalib/src/mesa/tnl/tnl.h b/mesalib/src/mesa/tnl/tnl.h index 2c0d1fef7..9966878da 100644 --- a/mesalib/src/mesa/tnl/tnl.h +++ b/mesalib/src/mesa/tnl/tnl.h @@ -1,100 +1,100 @@ -/* - * Mesa 3-D graphics library - * Version: 7.1 - * - * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included - * in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS - * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN - * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - * - * Authors: - * Keith Whitwell <keith@tungstengraphics.com> - */ - -#ifndef _TNL_H -#define _TNL_H - -#include "main/mtypes.h" - - - -/* These are the public-access functions exported from tnl. (A few - * more are currently hooked into dispatch directly by the module - * itself.) - */ -extern GLboolean -_tnl_CreateContext( GLcontext *ctx ); - -extern void -_tnl_DestroyContext( GLcontext *ctx ); - -extern void -_tnl_InvalidateState( GLcontext *ctx, GLuint new_state ); - -/* Functions to revive the tnl module after being unhooked from - * dispatch and/or driver callbacks. - */ - -extern void -_tnl_wakeup( GLcontext *ctx ); - -/* Driver configuration options: - */ -extern void -_tnl_need_projected_coords( GLcontext *ctx, GLboolean flag ); - - -/* Control whether T&L does per-vertex fog - */ -extern void -_tnl_allow_vertex_fog( GLcontext *ctx, GLboolean value ); - -extern void -_tnl_allow_pixel_fog( GLcontext *ctx, GLboolean value ); - -extern GLboolean -_tnl_program_string(GLcontext *ctx, GLenum target, struct gl_program *program); - -struct _mesa_prim; -struct _mesa_index_buffer; - -void -_tnl_draw_prims( GLcontext *ctx, - const struct gl_client_array *arrays[], - const struct _mesa_prim *prim, - GLuint nr_prims, - const struct _mesa_index_buffer *ib, - GLuint min_index, - GLuint max_index); - -void -_tnl_vbo_draw_prims( GLcontext *ctx, - const struct gl_client_array *arrays[], - const struct _mesa_prim *prim, - GLuint nr_prims, - const struct _mesa_index_buffer *ib, - GLboolean index_bounds_valid, - GLuint min_index, - GLuint max_index); - -extern void -_mesa_load_tracked_matrices(GLcontext *ctx); - -extern void -_tnl_RasterPos(GLcontext *ctx, const GLfloat vObj[4]); - -#endif +/*
+ * Mesa 3-D graphics library
+ * Version: 7.1
+ *
+ * Copyright (C) 1999-2007 Brian Paul All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included
+ * in all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+ * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+ * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors:
+ * Keith Whitwell <keith@tungstengraphics.com>
+ */
+
+#ifndef _TNL_H
+#define _TNL_H
+
+#include "main/mtypes.h"
+
+
+
+/* These are the public-access functions exported from tnl. (A few
+ * more are currently hooked into dispatch directly by the module
+ * itself.)
+ */
+extern GLboolean
+_tnl_CreateContext( struct gl_context *ctx );
+
+extern void
+_tnl_DestroyContext( struct gl_context *ctx );
+
+extern void
+_tnl_InvalidateState( struct gl_context *ctx, GLuint new_state );
+
+/* Functions to revive the tnl module after being unhooked from
+ * dispatch and/or driver callbacks.
+ */
+
+extern void
+_tnl_wakeup( struct gl_context *ctx );
+
+/* Driver configuration options:
+ */
+extern void
+_tnl_need_projected_coords( struct gl_context *ctx, GLboolean flag );
+
+
+/* Control whether T&L does per-vertex fog
+ */
+extern void
+_tnl_allow_vertex_fog( struct gl_context *ctx, GLboolean value );
+
+extern void
+_tnl_allow_pixel_fog( struct gl_context *ctx, GLboolean value );
+
+extern GLboolean
+_tnl_program_string(struct gl_context *ctx, GLenum target, struct gl_program *program);
+
+struct _mesa_prim;
+struct _mesa_index_buffer;
+
+void
+_tnl_draw_prims( struct gl_context *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLuint min_index,
+ GLuint max_index);
+
+void
+_tnl_vbo_draw_prims( struct gl_context *ctx,
+ const struct gl_client_array *arrays[],
+ const struct _mesa_prim *prim,
+ GLuint nr_prims,
+ const struct _mesa_index_buffer *ib,
+ GLboolean index_bounds_valid,
+ GLuint min_index,
+ GLuint max_index);
+
+extern void
+_mesa_load_tracked_matrices(struct gl_context *ctx);
+
+extern void
+_tnl_RasterPos(struct gl_context *ctx, const GLfloat vObj[4]);
+
+#endif
|