Subversion Repositories Kolibri OS

Compare Revisions

Regard whitespace Rev 5563 → Rev 5564

/contrib/sdk/sources/Mesa/mesa-10.6.0/src/mesa/tnl/NOTES
0,0 → 1,100
INTRODUCTION
 
A generic, configurable software implementation of GL transformation &
lighting.
 
This module provides an implementation of the routines required by the
'vtxfmt' mechanism of core mesa for tnl functionality in all
combinations of compile and execute modes.
 
Most current drivers use the tnl module exclusively to provide this
functionality.
 
 
STATE
 
To create and destroy the module:
 
GLboolean _tnl_CreateContext( struct gl_context *ctx );
void _tnl_DestroyContext( struct gl_context *ctx );
 
The module is not active by default, and must be installed by calling
_tnl_Wakeup(). This function installs internal tnl functions into all
the vtxfmt dispatch hooks, thus taking over the task of transformation
and lighting entirely:
 
void _tnl_wakeup_exec( struct gl_context *ctx );
void _tnl_wakeup_save_exec( struct gl_context *ctx );
 
This module tracks state changes internally and maintains derived
values based on the current state. For this to work, the driver
ensure the following funciton is called whenever the state changes and
the swsetup module is 'awake':
 
void _tnl_InvalidateState( struct gl_context *ctx, GLuint new_state );
 
There is no explicit call to put the tnl module to sleep. Simply
install other function pointers into all the vtxfmt dispatch slots,
and (optionally) cease calling _tnl_InvalidateState().
 
CUSTOMIZATION
 
The module provides customizability through several mechanisms. The
most important is by allowing drivers to specify the pipeline through
which vertex data is passed, including its eventual transfer to
rasterization hardware (or software).
 
The default pipeline is specified in t_pipeline.c, and is usually a
starting point for driver pipelines. Some drivers will remove a stage
where hardware provides support for the implemented operation (for
instance fog where per-pixel hardware fog is available),
or add stages to shortcircuit latter operations (for
example taking advantage of hardware support for strips and other
higher-level primitives (for example the radeon driver).
 
In addition, the following functions provide further tweaks:
 
extern void
_tnl_need_projected_coords( struct gl_context *ctx, GLboolean flag );
 
- Direct the default vertex transformation stage to
produce/not produce projected clip coordinates.
extern void
_tnl_need_dlist_loopback( struct gl_context *ctx, GLboolean flag );
- Direct the display list component of the tnl module to
replay display lists as 'glVertex' type calls, rather than
passing the display list data directly into the tnl pipeline
mechanism.
 
This allows display lists to be replayed by the tnl module
even when the module is not strictly active.
 
 
extern void
_tnl_need_dlist_norm_lengths( struct gl_context *ctx, GLboolean flag );
 
- Direct the display list component to enable/disable caching
1/length values for display list normals. Doing so is
ususally helpful when lighting is performed in software, but
wasteful otherwise.
 
 
DRIVER INTERFACE
 
The module itself offers a minimal driver interface:
 
void (*RunPipeline)( struct gl_context *ctx );
 
Normally this is set to _tnl_RunPipeline(), however the driver can use
this hook to wrap checks or other code around this call.
 
In addition, the driver interface for the default render pipeline
stage is housed in the tnl context struct (this could be cleaner).
 
 
RENDER DRIVER INTERFACE
 
See t_context.h for the definition and explanation of this.
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/mesa/tnl/t_context.c
0,0 → 1,248
/*
* Mesa 3-D graphics library
*
* 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
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.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 "main/state.h"
#include "main/viewport.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;
GLuint i;
 
/* Create the TNLcontext structure
*/
ctx->swtnl_context = tnl = calloc(1, 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 );
}
 
_math_matrix_ctr(&tnl->_WindowMap);
 
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 = _tnl_validate_shine_tables;
 
tnl->nr_blocks = 0;
 
/* Lighting miscellaneous */
tnl->_ShineTabList = MALLOC_STRUCT( tnl_shine_tab );
make_empty_list( tnl->_ShineTabList );
/* Allocate 10 (arbitrary) shininess lookup tables */
for (i = 0 ; i < 10 ; i++) {
struct tnl_shine_tab *s = MALLOC_STRUCT( tnl_shine_tab );
s->shininess = -1;
s->refcount = 0;
insert_at_tail( tnl->_ShineTabList, s );
}
 
/* plug in the VBO drawing function */
vbo_set_draw_func(ctx, _tnl_draw_prims);
 
_math_init_transformation();
_math_init_translate();
 
return GL_TRUE;
}
 
 
void
_tnl_DestroyContext( struct gl_context *ctx )
{
struct tnl_shine_tab *s, *tmps;
TNLcontext *tnl = TNL_CONTEXT(ctx);
 
_math_matrix_dtr(&tnl->_WindowMap);
 
/* Free lighting shininess exponentiation table */
foreach_s( s, tmps, tnl->_ShineTabList ) {
free( s );
}
free( tnl->_ShineTabList );
 
_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.
*/
tnl->render_inputs_bitset = BITFIELD64_BIT(_TNL_ATTRIB_POS);
 
if (!fp || (fp->Base.InputsRead & VARYING_BIT_COL0)) {
tnl->render_inputs_bitset |= BITFIELD64_BIT(_TNL_ATTRIB_COLOR0);
}
 
if (_mesa_need_secondary_color(ctx))
tnl->render_inputs_bitset |= BITFIELD64_BIT(_TNL_ATTRIB_COLOR1);
 
for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
if (ctx->Texture._EnabledCoordUnits & (1 << i) ||
(fp && fp->Base.InputsRead & VARYING_BIT_TEX(i))) {
tnl->render_inputs_bitset |= BITFIELD64_BIT(_TNL_ATTRIB_TEX(i));
}
}
 
if (ctx->Fog.Enabled
|| (fp != NULL && (fp->Base.InputsRead & VARYING_BIT_FOGC) != 0)) {
/* Either fixed-function fog or a fragment program needs fog coord.
*/
tnl->render_inputs_bitset |= BITFIELD64_BIT(_TNL_ATTRIB_FOG);
}
 
if (ctx->Polygon.FrontMode != GL_FILL ||
ctx->Polygon.BackMode != GL_FILL)
tnl->render_inputs_bitset |= BITFIELD64_BIT(_TNL_ATTRIB_EDGEFLAG);
 
if (ctx->RenderMode == GL_FEEDBACK)
tnl->render_inputs_bitset |= BITFIELD64_BIT(_TNL_ATTRIB_TEX0);
 
if (ctx->Point._Attenuated || ctx->VertexProgram.PointSizeEnabled)
tnl->render_inputs_bitset |= BITFIELD64_BIT(_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(VARYING_SLOT_VAR0 + i)) {
tnl->render_inputs_bitset |= BITFIELD64_BIT(_TNL_ATTRIB_GENERIC(i));
}
}
}
 
if (new_state & (_NEW_VIEWPORT | _NEW_BUFFERS)) {
double scale[3], translate[3];
_mesa_get_viewport_xform(ctx, 0, scale, translate);
_math_matrix_viewport(&tnl->_WindowMap, scale, translate,
ctx->DrawBuffer->_DepthMaxF);
}
}
 
 
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;
}
 
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/mesa/tnl/t_context.h
0,0 → 1,555
/*
* mesa 3-D graphics library
*
* 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
* THE AUTHORS OR COPYRIGHT HOLDERS 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/imports.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 = 17, /* doesn't really exist! */
_TNL_ATTRIB_GENERIC1 = 18,
_TNL_ATTRIB_GENERIC2 = 19,
_TNL_ATTRIB_GENERIC3 = 20,
_TNL_ATTRIB_GENERIC4 = 21,
_TNL_ATTRIB_GENERIC5 = 22,
_TNL_ATTRIB_GENERIC6 = 23,
_TNL_ATTRIB_GENERIC7 = 24,
_TNL_ATTRIB_GENERIC8 = 25,
_TNL_ATTRIB_GENERIC9 = 26,
_TNL_ATTRIB_GENERIC10 = 27,
_TNL_ATTRIB_GENERIC11 = 28,
_TNL_ATTRIB_GENERIC12 = 29,
_TNL_ATTRIB_GENERIC13 = 30,
_TNL_ATTRIB_GENERIC14 = 31,
_TNL_ATTRIB_GENERIC15 = 32,
 
/* 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 = 17,
_TNL_ATTRIB_MAT_BACK_AMBIENT = 18,
_TNL_ATTRIB_MAT_FRONT_DIFFUSE = 19,
_TNL_ATTRIB_MAT_BACK_DIFFUSE = 20,
_TNL_ATTRIB_MAT_FRONT_SPECULAR = 21,
_TNL_ATTRIB_MAT_BACK_SPECULAR = 22,
_TNL_ATTRIB_MAT_FRONT_EMISSION = 23,
_TNL_ATTRIB_MAT_BACK_EMISSION = 24,
_TNL_ATTRIB_MAT_FRONT_SHININESS = 25,
_TNL_ATTRIB_MAT_BACK_SHININESS = 26,
_TNL_ATTRIB_MAT_FRONT_INDEXES = 27,
_TNL_ATTRIB_MAT_BACK_INDEXES = 28,
 
/* This is really a VARYING_SLOT, not an attrib. Need to fix
* tnl to understand the difference.
*/
_TNL_ATTRIB_POINTSIZE = 16,
 
_TNL_ATTRIB_MAX = 33
} ;
 
#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 texture attributes */
#define _TNL_NUM_TEX 8
 
/* 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];
};
 
 
/**
* 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 );
};
 
 
#define SHINE_TABLE_SIZE 256 /**< Material shininess lookup table sizes */
 
/**
* Material shininess lookup table.
*/
struct tnl_shine_tab
{
struct tnl_shine_tab *next, *prev;
GLfloat tab[SHINE_TABLE_SIZE+1];
GLfloat shininess;
GLuint refcount;
};
 
 
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;
};
 
 
/**
* 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;
GLmatrix _WindowMap;
 
/* Probably need a better configuration mechanism:
*/
GLboolean NeedNdcCoords;
GLboolean AllowVertexFog;
GLboolean AllowPixelFog;
GLboolean _DoVertexFog; /* eval fog function at each vertex? */
 
GLbitfield64 render_inputs_bitset;
 
GLvector4f tmp_inputs[VERT_ATTRIB_MAX];
 
/* Temp storage for t_draw.c:
*/
GLubyte *block[VERT_ATTRIB_MAX];
GLuint nr_blocks;
 
GLuint CurInstance;
 
struct tnl_shine_tab *_ShineTable[2]; /**< Active shine tables */
struct tnl_shine_tab *_ShineTabList; /**< MRU list of inactive shine tables */
/**@}*/
} 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
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/mesa/tnl/t_draw.c
0,0 → 1,529
/*
* Mesa 3-D graphics library
*
* 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
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.com>
*/
 
#include <stdio.h>
 
#include "main/glheader.h"
#include "main/bufferobj.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;
GLint 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->Mappings[MAP_INTERNAL].Pointer) {
bo[*nr_bo] = inputs[i]->BufferObj;
(*nr_bo)++;
ctx->Driver.MapBufferRange(ctx, 0, inputs[i]->BufferObj->Size,
GL_MAP_READ_BIT,
inputs[i]->BufferObj,
MAP_INTERNAL);
assert(inputs[i]->BufferObj->Mappings[MAP_INTERNAL].Pointer);
}
ptr = ADD_POINTERS(inputs[i]->BufferObj->Mappings[MAP_INTERNAL].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;
const void *ptr;
 
if (!ib) {
VB->Elts = NULL;
return;
}
 
if (_mesa_is_bufferobj(ib->obj) &&
!_mesa_bufferobj_mapped(ib->obj, MAP_INTERNAL)) {
/* if the buffer object isn't mapped yet, map it now */
bo[*nr_bo] = ib->obj;
(*nr_bo)++;
ptr = ctx->Driver.MapBufferRange(ctx, (GLsizeiptr) ib->ptr,
ib->count * vbo_sizeof_ib_type(ib->type),
GL_MAP_READ_BIT, ib->obj,
MAP_INTERNAL);
assert(ib->obj->Mappings[MAP_INTERNAL].Pointer);
} else {
/* user-space elements, or buffer already mapped */
ptr = ADD_POINTERS(ib->obj->Mappings[MAP_INTERNAL].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, bo[i], MAP_INTERNAL);
}
}
 
 
/* 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 _mesa_prim *prim,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
GLboolean index_bounds_valid,
GLuint min_index,
GLuint max_index,
struct gl_transform_feedback_object *tfb_vertcount,
struct gl_buffer_object *indirect)
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
const struct gl_client_array **arrays = ctx->Array._DrawArrays;
const GLuint TEST_SPLIT = 0;
const GLint max = TEST_SPLIT ? 8 : tnl->vb.Size - MAX_CLIPPED_VERTICES;
GLint max_basevertex = prim->basevertex;
GLuint i;
 
if (!index_bounds_valid)
vbo_get_minmax_indices(ctx, prim, ib, &min_index, &max_index, nr_prims);
 
/* 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", __func__, 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_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_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;
GLuint inst;
 
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;
}
 
assert(prim[i].num_instances > 0);
 
/* Binding inputs may imply mapping some vertex buffer objects.
* They will need to be unmapped below.
*/
for (inst = 0; inst < prim[i].num_instances; inst++) {
 
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->CurInstance = inst;
TNL_CONTEXT(ctx)->Driver.RunPipeline(ctx);
 
unmap_vbos(ctx, bo, nr_bo);
free_space(ctx);
}
 
i += this_nr_prims;
}
}
}
 
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/mesa/tnl/t_pipeline.c
0,0 → 1,300
/*
* Mesa 3-D graphics library
*
* 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
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.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 < VARYING_SLOT_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
}
 
/**
* START/END_FAST_MATH macros:
*
* START_FAST_MATH: Set x86 FPU to faster, 32-bit precision mode (and save
* original mode to a temporary).
* END_FAST_MATH: Restore x86 FPU to original mode.
*/
#if defined(__GNUC__) && defined(__i386__)
/*
* Set the x86 FPU control word to guarentee only 32 bits of precision
* are stored in registers. Allowing the FPU to store more introduces
* differences between situations where numbers are pulled out of memory
* vs. situations where the compiler is able to optimize register usage.
*
* In the worst case, we force the compiler to use a memory access to
* truncate the float, by specifying the 'volatile' keyword.
*/
/* Hardware default: All exceptions masked, extended double precision,
* round to nearest (IEEE compliant):
*/
#define DEFAULT_X86_FPU 0x037f
/* All exceptions masked, single precision, round to nearest:
*/
#define FAST_X86_FPU 0x003f
/* The fldcw instruction will cause any pending FP exceptions to be
* raised prior to entering the block, and we clear any pending
* exceptions before exiting the block. Hence, asm code has free
* reign over the FPU while in the fast math block.
*/
#if defined(NO_FAST_MATH)
#define START_FAST_MATH(x) \
do { \
static GLuint mask = DEFAULT_X86_FPU; \
__asm__ ( "fnstcw %0" : "=m" (*&(x)) ); \
__asm__ ( "fldcw %0" : : "m" (mask) ); \
} while (0)
#else
#define START_FAST_MATH(x) \
do { \
static GLuint mask = FAST_X86_FPU; \
__asm__ ( "fnstcw %0" : "=m" (*&(x)) ); \
__asm__ ( "fldcw %0" : : "m" (mask) ); \
} while (0)
#endif
/* Restore original FPU mode, and clear any exceptions that may have
* occurred in the FAST_MATH block.
*/
#define END_FAST_MATH(x) \
do { \
__asm__ ( "fnclex ; fldcw %0" : : "m" (*&(x)) ); \
} while (0)
 
#elif defined(_MSC_VER) && defined(_M_IX86)
#define DEFAULT_X86_FPU 0x037f /* See GCC comments above */
#define FAST_X86_FPU 0x003f /* See GCC comments above */
#if defined(NO_FAST_MATH)
#define START_FAST_MATH(x) do {\
static GLuint mask = DEFAULT_X86_FPU;\
__asm fnstcw word ptr [x]\
__asm fldcw word ptr [mask]\
} while(0)
#else
#define START_FAST_MATH(x) do {\
static GLuint mask = FAST_X86_FPU;\
__asm fnstcw word ptr [x]\
__asm fldcw word ptr [mask]\
} while(0)
#endif
#define END_FAST_MATH(x) do {\
__asm fnclex\
__asm fldcw word ptr [x]\
} while(0)
 
#else
#define START_FAST_MATH(x) x = 0
#define END_FAST_MATH(x) (void)(x)
#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 );
}
 
#ifndef _OPENMP
/* Don't adjust FPU precision mode in case multiple threads are to be used.
* This would require that the additional threads also changed the FPU mode
* which is quite a mess as this had to be done in all parallelized sections;
* otherwise the master thread and all other threads are running in different
* modes, producing inconsistent results.
* Note that all x64 implementations don't define/use START_FAST_MATH, so
* this is "hack" is only used in i386 mode
*/
START_FAST_MATH(__tmp);
#endif
 
for (i = 0; i < tnl->pipeline.nr_stages ; i++) {
struct tnl_pipeline_stage *s = &tnl->pipeline.stages[i];
if (!s->run( ctx, s ))
break;
}
 
#ifndef _OPENMP
END_FAST_MATH(__tmp);
#endif
}
 
 
 
/* 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
};
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/mesa/tnl/t_pipeline.h
0,0 → 1,73
/*
* Mesa 3-D graphics library
*
* 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
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.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
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/mesa/tnl/t_rasterpos.c
0,0 → 1,478
/*
* Mesa 3-D graphics library
*
* 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
* THE AUTHORS OR COPYRIGHT HOLDERS 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 "c99_math.h"
#include "main/glheader.h"
#include "main/feedback.h"
#include "main/light.h"
#include "main/macros.h"
#include "util/simple_list.h"
#include "main/mtypes.h"
#include "main/viewport.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. RGB 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)
*/
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 */
 
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 {
GLfloat spot = powf(PV_dot_dir, light->SpotExponent);
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]);
 
/* 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 shine;
GLfloat spec_coef;
 
shine = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SHININESS][0];
spec_coef = powf(n_dot_h, shine);
 
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]);
}
}
}
}
 
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 * (1.0f / 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];
double scale[3], translate[3];
 
/* 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) */
_mesa_get_viewport_xform(ctx, 0, scale, translate);
ctx->Current.RasterPos[0] = ndc[0] * scale[0] + translate[0];
ctx->Current.RasterPos[1] = ndc[1] * scale[1] + translate[1];
ctx->Current.RasterPos[2] = ndc[2] * scale[2] + translate[2];
ctx->Current.RasterPos[3] = clip[3];
 
if (ctx->Transform.DepthClamp) {
ctx->Current.RasterPos[3] = CLAMP(ctx->Current.RasterPos[3],
ctx->ViewportArray[0].Near,
ctx->ViewportArray[0].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] );
}
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/mesa/tnl/t_vb_cliptmp.h
0,0 → 1,320
/*
* Mesa 3-D graphics library
*
* 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
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.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 (dpPrev >= 0.0f) { \
outlist[outcount++] = idxPrev; \
} \
\
if (DIFFERENT_SIGNS(dp, dpPrev)) { \
if (dp < 0.0f) { \
/* 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 = dp0 < 0.0f; \
const GLboolean neg_dp1 = dp1 < 0.0f; \
\
/* 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 < 0.0f 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
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/mesa/tnl/t_vb_fog.c
0,0 → 1,276
/*
* Mesa 3-D graphics library
*
* 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
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.com>
*/
 
 
#include "c99_math.h"
#include "main/glheader.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. */
};
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/mesa/tnl/t_vb_light.c
0,0 → 1,472
/*
* Mesa 3-D graphics library
*
* 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
* THE AUTHORS OR COPYRIGHT HOLDERS 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 "c99_math.h"
#include "main/glheader.h"
#include "main/light.h"
#include "main/macros.h"
#include "main/imports.h"
#include "util/simple_list.h"
#include "main/mtypes.h"
 
#include "math/m_translate.h"
 
#include "t_context.h"
#include "t_pipeline.h"
#include "tnl.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))
 
 
 
/**********************************************************************/
/***** Lighting computation *****/
/**********************************************************************/
 
 
/*
* Notes:
* When two-sided lighting is enabled we compute the color (or index)
* for both the front and back side of the primitive. Then, when the
* orientation of the facet is later learned, we can determine which
* color (or index) to use for rendering.
*
* KW: We now know orientation in advance and only shade for
* the side or sides which are actually required.
*
* Variables:
* n = normal vector
* V = vertex position
* P = light source position
* Pe = (0,0,0,1)
*
* Precomputed:
* IF P[3]==0 THEN
* // light at infinity
* IF local_viewer THEN
* _VP_inf_norm = unit vector from V to P // Precompute
* ELSE
* // eye at infinity
* _h_inf_norm = Normalize( VP + <0,0,1> ) // Precompute
* ENDIF
* ENDIF
*
* Functions:
* Normalize( v ) = normalized vector v
* Magnitude( v ) = length of vector v
*/
 
 
 
static void
validate_shine_table( struct gl_context *ctx, GLuint side, GLfloat shininess )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
struct tnl_shine_tab *list = tnl->_ShineTabList;
struct tnl_shine_tab *s;
 
assert(side < 2);
 
foreach(s, list)
if ( s->shininess == shininess )
break;
 
if (s == list) {
GLint j;
GLfloat *m;
 
foreach(s, list)
if (s->refcount == 0)
break;
 
m = s->tab;
m[0] = 0.0;
if (shininess == 0.0) {
for (j = 1 ; j <= SHINE_TABLE_SIZE ; j++)
m[j] = 1.0;
}
else {
for (j = 1 ; j < SHINE_TABLE_SIZE ; j++) {
GLdouble t, x = j / (GLfloat) (SHINE_TABLE_SIZE - 1);
if (x < 0.005) /* underflow check */
x = 0.005;
t = pow(x, shininess);
if (t > 1e-20)
m[j] = (GLfloat) t;
else
m[j] = 0.0;
}
m[SHINE_TABLE_SIZE] = 1.0;
}
 
s->shininess = shininess;
}
 
if (tnl->_ShineTable[side])
tnl->_ShineTable[side]->refcount--;
 
tnl->_ShineTable[side] = s;
move_to_tail( list, s );
s->refcount++;
}
 
 
void
_tnl_validate_shine_tables( struct gl_context *ctx )
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
GLfloat shininess;
shininess = ctx->Light.Material.Attrib[MAT_ATTRIB_FRONT_SHININESS][0];
if (!tnl->_ShineTable[0] || tnl->_ShineTable[0]->shininess != shininess)
validate_shine_table( ctx, 0, shininess );
 
shininess = ctx->Light.Material.Attrib[MAT_ATTRIB_BACK_SHININESS][0];
if (!tnl->_ShineTable[1] || tnl->_ShineTable[1]->shininess != shininess)
validate_shine_table( ctx, 1, shininess );
}
 
 
/**
* 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.
*/
_tnl_validate_shine_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 );
 
_tnl_validate_shine_tables( ctx );
 
return store->mat_count;
}
 
/*
* Compute dp ^ SpecularExponent.
* Lerp between adjacent values in the f(x) lookup table, giving a
* continuous function, with adequate overall accuracy. (Though still
* pretty good compared to a straight lookup).
*/
static inline GLfloat
lookup_shininess(const struct gl_context *ctx, GLuint face, GLfloat dp)
{
TNLcontext *tnl = TNL_CONTEXT(ctx);
const struct tnl_shine_tab *tab = tnl->_ShineTable[face];
float f = dp * (SHINE_TABLE_SIZE - 1);
int k = (int) f;
if (k < 0 /* gcc may cast an overflow float value to negative int value */
|| k > SHINE_TABLE_SIZE - 2)
return powf(dp, tab->shininess);
else
return tab->tab[k] + (f - k) * (tab->tab[k+1] - tab->tab[k]);
}
 
/* 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
};
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/mesa/tnl/t_vb_lighttmp.h
0,0 → 1,631
/*
* Mesa 3-D graphics library
*
* 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
* THE AUTHORS OR COPYRIGHT HOLDERS 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 <keithw@vmware.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", __func__ );
#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 {
GLfloat spot = powf(PV_dot_dir, light->SpotExponent);
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 = lookup_shininess(ctx, side, n_dot_h);
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", __func__ );
#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 {
GLfloat spot = powf(PV_dot_dir, light->SpotExponent);
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 = lookup_shininess(ctx, side, n_dot_h);
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", __func__ );
#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 = lookup_shininess(ctx, 1, n_dot_h);
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 = lookup_shininess(ctx, 0, n_dot_h);
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", __func__, 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) {
spec = lookup_shininess(ctx, 0, n_dot_h);
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) {
spec = lookup_shininess(ctx, 1, n_dot_h);
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
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/mesa/tnl/t_vb_normals.c
0,0 → 1,186
/*
* Mesa 3-D graphics library
*
* 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
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.com>
*/
 
 
#include "main/glheader.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 */
};
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/mesa/tnl/t_vb_points.c
0,0 → 1,115
/*
* Mesa 3-D graphics library
*
* 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
* THE AUTHORS OR COPYRIGHT HOLDERS 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 "c99_math.h"
#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) ? (1.0f / sqrtf(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 */
};
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/mesa/tnl/t_vb_program.c
0,0 → 1,538
/*
* Mesa 3-D graphics library
*
* 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
* THE AUTHORS OR COPYRIGHT HOLDERS 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/macros.h"
#include "main/imports.h"
#include "main/samplerobj.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[VARYING_SLOT_MAX];
 
GLvector4f ndcCoords; /**< normalized device coords */
GLubyte *clipmask; /**< clip flags */
GLubyte ormask, andmask; /**< for clipping */
 
GLboolean vertex_textures;
 
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, _mesa_get_samplerobj(ctx, unit),
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,
GLuint instID)
{
/* Input registers get initialized from the current vertex attribs */
memcpy(machine->VertAttribs, ctx->Current.Attrib,
MAX_VERTEX_GENERIC_ATTRIBS * 4 * sizeof(GLfloat));
 
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;
 
machine->SystemValues[SYSTEM_VALUE_INSTANCE_ID][0] = (GLfloat) instID;
}
 
 
/**
* 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;
 
for (u = 0; u < ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits; u++) {
if (vp->Base.TexturesUsed[u]) {
/* Note: _Current *should* correspond to the target indicated
* in TexturesUsed[u].
*/
_swrast_map_texture(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;
 
for (u = 0; u < ctx->Const.Program[MESA_SHADER_VERTEX].MaxTextureImageUnits; u++) {
if (vp->Base.TexturesUsed[u]) {
/* Note: _Current *should* correspond to the target indicated
* in TexturesUsed[u].
*/
_swrast_unmap_texture(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[VARYING_SLOT_MAX], numOutputs;
GLuint i, j;
 
if (!program)
return GL_TRUE;
 
/* 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 < VARYING_SLOT_MAX; i++) {
if (program->Base.OutputsWritten & BITFIELD64_BIT(i)) {
outputs[numOutputs++] = i;
}
}
 
/* Allocate result vectors. We delay this until now to avoid allocating
* memory that would never be used if we don't run the software tnl pipeline.
*/
if (!store->results[0].storage) {
for (i = 0; i < VARYING_SLOT_MAX; i++) {
assert(!store->results[i].storage);
_mesa_vector4f_alloc( &store->results[i], 0, VB->Size, 32 );
store->results[i].size = 4;
}
}
 
map_textures(ctx, program);
 
for (i = 0; i < VB->Count; i++) {
GLuint attr;
 
init_machine(ctx, machine, tnl->CurInstance);
 
#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 & BITFIELD64_BIT(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(VARYING_SLOT_FOGC)) {
store->results[VARYING_SLOT_FOGC].data[i][1] = 0.0;
store->results[VARYING_SLOT_FOGC].data[i][2] = 0.0;
store->results[VARYING_SLOT_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);
 
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[VARYING_SLOT_POS];
VB->ClipPtr->size = 4;
VB->ClipPtr->count = VB->Count;
}
 
VB->AttribPtr[VERT_ATTRIB_COLOR0] = &store->results[VARYING_SLOT_COL0];
VB->AttribPtr[VERT_ATTRIB_COLOR1] = &store->results[VARYING_SLOT_COL1];
VB->AttribPtr[VERT_ATTRIB_FOG] = &store->results[VARYING_SLOT_FOGC];
VB->AttribPtr[_TNL_ATTRIB_POINTSIZE] = &store->results[VARYING_SLOT_PSIZ];
VB->BackfaceColorPtr = &store->results[VARYING_SLOT_BFC0];
VB->BackfaceSecondaryColorPtr = &store->results[VARYING_SLOT_BFC1];
 
for (i = 0; i < ctx->Const.MaxTextureCoordUnits; i++) {
VB->AttribPtr[_TNL_ATTRIB_TEX0 + i]
= &store->results[VARYING_SLOT_TEX0 + i];
}
 
for (i = 0; i < ctx->Const.MaxVarying; i++) {
if (program->Base.OutputsWritten & BITFIELD64_BIT(VARYING_SLOT_VAR0 + i)) {
/* Note: varying results get put into the generic attributes */
VB->AttribPtr[VERT_ATTRIB_GENERIC0+i]
= &store->results[VARYING_SLOT_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;
 
stage->privatePtr = calloc(1, sizeof(*store));
store = VP_STAGE_DATA(stage);
if (!store)
return GL_FALSE;
 
/* a few other misc allocations */
_mesa_vector4f_alloc( &store->ndcCoords, 0, size, 32 );
store->clipmask = _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 < VARYING_SLOT_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 */
};
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/mesa/tnl/t_vb_render.c
0,0 → 1,349
/*
* Mesa 3-D graphics library
*
* 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
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.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 <stdio.h>
#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 */
};
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/mesa/tnl/t_vb_rendertmp.h
0,0 → 1,486
/*
* Mesa 3-D graphics library
*
* 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
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.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
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/mesa/tnl/t_vb_texgen.c
0,0 → 1,607
/*
* Mesa 3-D graphics library
*
* 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
* THE AUTHORS OR COPYRIGHT HOLDERS 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 <keithw@vmware.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/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 * (1.0f / 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 * (1.0f / 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(1, 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 = malloc(VB->Size * sizeof(GLfloat) * 3);
store->tmp_m = 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] );
 
 
free( store->tmp_f );
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 */
};
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/mesa/tnl/t_vb_texmat.c
0,0 → 1,127
/*
* Mesa 3-D graphics library
*
* 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
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.com>
*/
 
 
#include "main/glheader.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(1, 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,
};
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/mesa/tnl/t_vb_vertex.c
0,0 → 1,282
/*
* Mesa 3-D graphics library
*
* 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
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.com>
*/
 
 
#include "main/glheader.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(1, 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 = _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 */
};
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/mesa/tnl/t_vertex.c
0,0 → 1,578
/*
* Copyright 2003 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
* 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
* VMWARE 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@vmware.com>
*/
 
#include <stdio.h>
#include "main/glheader.h"
#include "main/context.h"
#include "swrast/s_chan.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;
 
if (fastpath == NULL) {
_mesa_error_no_memory(__func__);
return;
}
 
fastpath->vertex_size = vtx->vertex_size;
fastpath->attr_count = vtx->attr_count;
fastpath->match_strides = match_strides;
fastpath->func = vtx->emit;
fastpath->attr = malloc(vtx->attr_count * sizeof(fastpath->attr[0]));
 
if (fastpath->attr == NULL) {
free(fastpath);
_mesa_error_no_memory(__func__);
return;
}
 
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);
GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL ||
ctx->Polygon.BackMode != GL_FILL);
GLboolean twosided = ctx->Light.Enabled && ctx->Light.Model.TwoSide;
 
if (vtx->need_extras && (twosided || 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);
GLboolean unfilled = (ctx->Polygon.FrontMode != GL_FILL ||
ctx->Polygon.BackMode != GL_FILL);
 
GLboolean twosided = ctx->Light.Enabled && ctx->Light.Model.TwoSide;
 
if (vtx->need_extras && (twosided || 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 two-sided lighting changes or filled/unfilled polygon state changes */
if (new_state & (_NEW_LIGHT | _NEW_POLYGON) ) {
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 = _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 (!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;
 
_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;
}
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/mesa/tnl/t_vertex.h
0,0 → 1,184
/*
* Copyright 2003 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
* 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
* VMWARE 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@vmware.com>
*/
 
#ifndef _TNL_VERTEX_H
#define _TNL_VERTEX_H
 
#include "main/glheader.h"
#include "t_context.h"
 
struct gl_context;
struct tnl_clipspace;
 
/* 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 weird 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
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/mesa/tnl/t_vertex_generic.c
0,0 → 1,1153
 
/*
* Copyright 2003 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
* 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
* VMWARE 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@vmware.com>
*/
 
#include "main/glheader.h"
#include "main/context.h"
#include "main/macros.h"
#include "util/simple_list.h"
#include "swrast/s_chan.h"
#include "t_context.h"
#include "t_vertex.h"
 
 
#if 0
#define DEBUG_INSERT printf("%s\n", __func__)
#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_4F(t, fdst, fout, fin);
 
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);
}
 
 
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/mesa/tnl/t_vertex_sse.c
0,0 → 1,686
/*
* Copyright 2003 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
* 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
* VMWARE 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@vmware.com>
*/
 
#include <stdio.h>
 
#include "main/glheader.h"
#include "main/context.h"
#include "util/simple_list.h"
#include "main/enums.h"
#include "swrast/s_chan.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
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/mesa/tnl/t_vp_build.c
0,0 → 1,59
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2007 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
* VMWARE 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/mtypes.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);
}
}
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/mesa/tnl/t_vp_build.h
0,0 → 1,41
/*
* Mesa 3-D graphics library
*
* Copyright (C) 2005 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
* VMWARE 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
 
struct gl_context;
 
#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
/contrib/sdk/sources/Mesa/mesa-10.6.0/src/mesa/tnl/tnl.h
0,0 → 1,95
/*
* Mesa 3-D graphics library
*
* 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
* THE AUTHORS OR COPYRIGHT HOLDERS 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@vmware.com>
*/
 
#ifndef _TNL_H
#define _TNL_H
 
#include "main/glheader.h"
 
struct gl_client_array;
struct gl_context;
struct gl_program;
 
 
/* 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 _mesa_prim *prim,
GLuint nr_prims,
const struct _mesa_index_buffer *ib,
GLboolean index_bounds_valid,
GLuint min_index,
GLuint max_index,
struct gl_transform_feedback_object *tfb_vertcount,
struct gl_buffer_object *indirect );
 
extern void
_tnl_RasterPos(struct gl_context *ctx, const GLfloat vObj[4]);
 
extern void
_tnl_validate_shine_tables( struct gl_context *ctx );
 
#endif