Subversion Repositories Kolibri OS

Compare Revisions

No changes between revisions

Regard whitespace Rev 1900 → Rev 1901

/programs/develop/libraries/Mesa/src/mesa/tnl/descrip.mms
0,0 → 1,68
# Makefile for core library for VMS
# contributed by Jouk Jansen joukj@hrem.nano.tudelft.nl
# Last revision : 39 September 2008
 
.first
define gl [---.include.gl]
define math [-.math]
define vbo [-.vbo]
define shader [-.shader]
define swrast [-.swrast]
define array_cache [-.array_cache]
define main [-.main]
define glapi [-.glapi]
define tnl [-.tnl]
 
.include [---]mms-config.
 
##### MACROS #####
 
VPATH = RCS
 
INCDIR = [---.include],[-.main],[-.glapi],[-.shader],[-.shader.slang]
LIBDIR = [---.lib]
CFLAGS = /include=($(INCDIR),[])/define=(PTHREADS=1)/name=(as_is,short)/float=ieee/ieee=denorm
 
SOURCES = t_context.c t_draw.c \
t_pipeline.c t_vb_fog.c \
t_vb_light.c t_vb_normals.c t_vb_points.c t_vb_program.c \
t_vb_render.c t_vb_texgen.c t_vb_texmat.c t_vb_vertex.c \
t_vertex.c t_rasterpos.c\
t_vertex_generic.c t_vp_build.c
 
OBJECTS = t_context.obj,t_draw.obj,\
t_pipeline.obj,t_vb_fog.obj,t_vb_light.obj,t_vb_normals.obj,\
t_vb_points.obj,t_vb_program.obj,t_vb_render.obj,t_vb_texgen.obj,\
t_vb_texmat.obj,t_vb_vertex.obj,t_rasterpos.obj,\
t_vertex.obj,t_vertex_generic.obj,\
t_vp_build.obj
 
##### RULES #####
 
VERSION=Mesa V3.4
 
##### TARGETS #####
# Make the library
$(LIBDIR)$(GL_LIB) : $(OBJECTS)
@ library $(LIBDIR)$(GL_LIB) $(OBJECTS)
 
clean :
purge
delete *.obj;*
 
t_context.obj : t_context.c
t_draw.obj : t_draw.c
t_pipeline.obj : t_pipeline.c
t_vb_fog.obj : t_vb_fog.c
t_vb_light.obj : t_vb_light.c
t_vb_normals.obj : t_vb_normals.c
t_vb_points.obj : t_vb_points.c
t_vb_program.obj : t_vb_program.c
t_vb_render.obj : t_vb_render.c
t_vb_texgen.obj : t_vb_texgen.c
t_vb_texmat.obj : t_vb_texmat.c
t_vb_vertex.obj : t_vb_vertex.c
t_vertex.obj : t_vertex.c
t_vertex_generic.obj : t_vertex_generic.c
t_vp_build.obj : t_vp_build.c
t_rasterpos.obj : t_rasterpos.c
/programs/develop/libraries/Mesa/src/mesa/tnl/t_context.c
0,0 → 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( 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;
}
 
/programs/develop/libraries/Mesa/src/mesa/tnl/t_context.h
0,0 → 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)( 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
/programs/develop/libraries/Mesa/src/mesa/tnl/t_draw.c
0,0 → 1,527
/*
* 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;
}
}
 
/**
* \brief Convert fixed-point to floating-point.
*
* In OpenGL, a fixed-point number is a "signed 2's complement 16.16 scaled
* integer" (Table 2.2 of the OpenGL ES 2.0 spec).
*
* If the buffer has the \c normalized flag set, the formula
* \code normalize(x) := (2*x + 1) / (2^16 - 1) \endcode
* is used to map the fixed-point numbers into the range [-1, 1].
*/
static void
convert_fixed_to_float(const struct gl_client_array *input,
const GLubyte *ptr, GLfloat *fptr,
GLuint count)
{
GLuint i, j;
const GLint size = input->Size;
 
if (input->Normalized) {
for (i = 0; i < count; ++i) {
const GLfixed *in = (GLfixed *) ptr;
for (j = 0; j < size; ++j) {
*fptr++ = (GLfloat) (2 * in[j] + 1) / (GLfloat) ((1 << 16) - 1);
}
ptr += input->StrideB;
}
} else {
for (i = 0; i < count; ++i) {
const GLfixed *in = (GLfixed *) ptr;
for (j = 0; j < size; ++j) {
*fptr++ = in[j] / (GLfloat) (1 << 16);
}
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;
case GL_FIXED:
convert_fixed_to_float(input, ptr, fptr, count);
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;
}
}
}
 
/programs/develop/libraries/Mesa/src/mesa/tnl/t_pipeline.c
0,0 → 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( 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
};
/programs/develop/libraries/Mesa/src/mesa/tnl/t_pipeline.h
0,0 → 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( 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
/programs/develop/libraries/Mesa/src/mesa/tnl/t_rasterpos.c
0,0 → 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( 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] );
}
}
/programs/develop/libraries/Mesa/src/mesa/tnl/t_vb_cliptmp.h
0,0 → 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)( 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
/programs/develop/libraries/Mesa/src/mesa/tnl/t_vb_fog.c
0,0 → 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(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. */
};
/programs/develop/libraries/Mesa/src/mesa/tnl/t_vb_light.c
0,0 → 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)( 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
};
/programs/develop/libraries/Mesa/src/mesa/tnl/t_vb_lighttmp.h
0,0 → 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)( 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
/programs/develop/libraries/Mesa/src/mesa/tnl/t_vb_normals.c
0,0 → 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(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 */
};
/programs/develop/libraries/Mesa/src/mesa/tnl/t_vb_points.c
0,0 → 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(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 */
};
/programs/develop/libraries/Mesa/src/mesa/tnl/t_vb_program.c
0,0 → 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 */
 
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 */
};
/programs/develop/libraries/Mesa/src/mesa/tnl/t_vb_render.c
0,0 → 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( 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 */
};
/programs/develop/libraries/Mesa/src/mesa/tnl/t_vb_rendertmp.h
0,0 → 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)( 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
/programs/develop/libraries/Mesa/src/mesa/tnl/t_vb_texgen.c
0,0 → 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)( 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 */
};
/programs/develop/libraries/Mesa/src/mesa/tnl/t_vb_texmat.c
0,0 → 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( 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,
};
/programs/develop/libraries/Mesa/src/mesa/tnl/t_vb_vertex.c
0,0 → 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( 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 */
};
/programs/develop/libraries/Mesa/src/mesa/tnl/t_vertex.c
0,0 → 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( 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;
}
}
/programs/develop/libraries/Mesa/src/mesa/tnl/t_vertex.h
0,0 → 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( 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
/programs/develop/libraries/Mesa/src/mesa/tnl/t_vertex_generic.c
0,0 → 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( 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);
}
 
 
/programs/develop/libraries/Mesa/src/mesa/tnl/t_vertex_sse.c
0,0 → 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;
 
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
/programs/develop/libraries/Mesa/src/mesa/tnl/t_vp_build.c
0,0 → 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( 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);
}
}
/programs/develop/libraries/Mesa/src/mesa/tnl/t_vp_build.h
0,0 → 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( struct gl_context *ctx );
 
#endif
/programs/develop/libraries/Mesa/src/mesa/tnl/tnl.h
0,0 → 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( 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
/programs/develop/libraries/Mesa/src/mesa/tnl/.
Property changes:
Added: tsvn:logminsize
+5
\ No newline at end of property