Blame |
Last modification |
View Log
| RSS feed
/* $Id: ss_vb.c,v 1.1 2003-02-28 11:54:35 pj Exp $ */
/*
* Mesa 3-D graphics library
* Version: 4.1
*
* Copyright (C) 1999-2002 Brian Paul All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included
* in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*
* Authors:
* Keith Whitwell <keith@tungstengraphics.com>
*/
#include "glheader.h"
#include "colormac.h"
#include "context.h"
#include "macros.h"
#include "imports.h"
#include "swrast/swrast.h"
#include "tnl/t_context.h"
#include "math/m_vector.h"
#include "math/m_translate.h"
#include "ss_context.h"
#include "ss_vb.h"
static void do_import( struct vertex_buffer *VB,
struct gl_client_array *to,
struct gl_client_array *from )
{
GLuint count = VB->Count;
if (!to->Ptr) {
to->Ptr = ALIGN_MALLOC( VB->Size * 4 * sizeof(GLchan), 32 );
to->Type = CHAN_TYPE;
}
/* No need to transform the same value 3000 times.
*/
if (!from->StrideB) {
to->StrideB = 0;
count = 1;
}
else
to->StrideB = 4 * sizeof(GLchan);
_math_trans_4chan( (GLchan (*)[4]) to->Ptr,
from->Ptr,
from->StrideB,
from->Type,
from->Size,
0,
count);
}
static void import_float_colors( GLcontext *ctx )
{
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
struct gl_client_array *to = &SWSETUP_CONTEXT(ctx)->ChanColor;
do_import( VB, to, VB->ColorPtr[0] );
VB->ColorPtr[0] = to;
}
static void import_float_spec_colors( GLcontext *ctx )
{
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
struct gl_client_array *to = &SWSETUP_CONTEXT(ctx)->ChanSecondaryColor;
do_import( VB, to, VB->SecondaryColorPtr[0] );
VB->SecondaryColorPtr[0] = to;
}
/* Provides a RasterSetup function which prebuilds vertices for the
* software rasterizer. This is required for the triangle functions
* in this module, but not the rest of the swrast module.
*/
#define COLOR 0x1
#define INDEX 0x2
#define TEX0 0x4
#define MULTITEX 0x8
#define SPEC 0x10
#define FOG 0x20
#define POINT 0x40
#define MAX_SETUPFUNC 0x80
static setup_func setup_tab[MAX_SETUPFUNC];
static interp_func interp_tab[MAX_SETUPFUNC];
static copy_pv_func copy_pv_tab[MAX_SETUPFUNC];
#define IND (0)
#define TAG(x) x##_none
#include "ss_vbtmp.h"
#define IND (COLOR)
#define TAG(x) x##_color
#include "ss_vbtmp.h"
#define IND (COLOR|SPEC)
#define TAG(x) x##_color_spec
#include "ss_vbtmp.h"
#define IND (COLOR|FOG)
#define TAG(x) x##_color_fog
#include "ss_vbtmp.h"
#define IND (COLOR|SPEC|FOG)
#define TAG(x) x##_color_spec_fog
#include "ss_vbtmp.h"
#define IND (COLOR|TEX0)
#define TAG(x) x##_color_tex0
#include "ss_vbtmp.h"
#define IND (COLOR|TEX0|SPEC)
#define TAG(x) x##_color_tex0_spec
#include "ss_vbtmp.h"
#define IND (COLOR|TEX0|FOG)
#define TAG(x) x##_color_tex0_fog
#include "ss_vbtmp.h"
#define IND (COLOR|TEX0|SPEC|FOG)
#define TAG(x) x##_color_tex0_spec_fog
#include "ss_vbtmp.h"
#define IND (COLOR|MULTITEX)
#define TAG(x) x##_color_multitex
#include "ss_vbtmp.h"
#define IND (COLOR|MULTITEX|SPEC)
#define TAG(x) x##_color_multitex_spec
#include "ss_vbtmp.h"
#define IND (COLOR|MULTITEX|FOG)
#define TAG(x) x##_color_multitex_fog
#include "ss_vbtmp.h"
#define IND (COLOR|MULTITEX|SPEC|FOG)
#define TAG(x) x##_color_multitex_spec_fog
#include "ss_vbtmp.h"
#define IND (COLOR|POINT)
#define TAG(x) x##_color_point
#include "ss_vbtmp.h"
#define IND (COLOR|SPEC|POINT)
#define TAG(x) x##_color_spec_point
#include "ss_vbtmp.h"
#define IND (COLOR|FOG|POINT)
#define TAG(x) x##_color_fog_point
#include "ss_vbtmp.h"
#define IND (COLOR|SPEC|FOG|POINT)
#define TAG(x) x##_color_spec_fog_point
#include "ss_vbtmp.h"
#define IND (COLOR|TEX0|POINT)
#define TAG(x) x##_color_tex0_point
#include "ss_vbtmp.h"
#define IND (COLOR|TEX0|SPEC|POINT)
#define TAG(x) x##_color_tex0_spec_point
#include "ss_vbtmp.h"
#define IND (COLOR|TEX0|FOG|POINT)
#define TAG(x) x##_color_tex0_fog_point
#include "ss_vbtmp.h"
#define IND (COLOR|TEX0|SPEC|FOG|POINT)
#define TAG(x) x##_color_tex0_spec_fog_point
#include "ss_vbtmp.h"
#define IND (COLOR|MULTITEX|POINT)
#define TAG(x) x##_color_multitex_point
#include "ss_vbtmp.h"
#define IND (COLOR|MULTITEX|SPEC|POINT)
#define TAG(x) x##_color_multitex_spec_point
#include "ss_vbtmp.h"
#define IND (COLOR|MULTITEX|FOG|POINT)
#define TAG(x) x##_color_multitex_fog_point
#include "ss_vbtmp.h"
#define IND (COLOR|MULTITEX|SPEC|FOG|POINT)
#define TAG(x) x##_color_multitex_spec_fog_point
#include "ss_vbtmp.h"
#define IND (INDEX)
#define TAG(x) x##_index
#include "ss_vbtmp.h"
#define IND (INDEX|FOG)
#define TAG(x) x##_index_fog
#include "ss_vbtmp.h"
#define IND (INDEX|POINT)
#define TAG(x) x##_index_point
#include "ss_vbtmp.h"
#define IND (INDEX|FOG|POINT)
#define TAG(x) x##_index_fog_point
#include "ss_vbtmp.h"
/***********************************************************************
* Additional setup and interp for back color and edgeflag.
***********************************************************************/
#define GET_COLOR(ptr, idx) (((GLchan (*)[4])((ptr)->Ptr))[idx])
static void interp_extras( GLcontext *ctx,
GLfloat t,
GLuint dst, GLuint out, GLuint in,
GLboolean force_boundary )
{
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
if (VB->ColorPtr[1]) {
INTERP_4CHAN( t,
GET_COLOR(VB->ColorPtr[1], dst),
GET_COLOR(VB->ColorPtr[1], out),
GET_COLOR(VB->ColorPtr[1], in) );
if (VB->SecondaryColorPtr[1]) {
INTERP_3CHAN( t,
GET_COLOR(VB->SecondaryColorPtr[1], dst),
GET_COLOR(VB->SecondaryColorPtr[1], out),
GET_COLOR(VB->SecondaryColorPtr[1], in) );
}
}
else if (VB->IndexPtr[1]) {
VB->IndexPtr[1]->data[dst] = (GLuint) (GLint)
LINTERP( t,
(GLfloat) VB->IndexPtr[1]->data[out],
(GLfloat) VB->IndexPtr[1]->data[in] );
}
if (VB->EdgeFlag) {
VB->EdgeFlag[dst] = VB->EdgeFlag[out] || force_boundary;
}
interp_tab[SWSETUP_CONTEXT(ctx)->SetupIndex](ctx, t, dst, out, in,
force_boundary);
}
static void copy_pv_extras( GLcontext *ctx, GLuint dst, GLuint src )
{
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
if (VB->ColorPtr[1]) {
COPY_CHAN4( GET_COLOR(VB->ColorPtr[1], dst),
GET_COLOR(VB->ColorPtr[1], src) );
if (VB->SecondaryColorPtr[1]) {
COPY_3V( GET_COLOR(VB->SecondaryColorPtr[1], dst),
GET_COLOR(VB->SecondaryColorPtr[1], src) );
}
}
else if (VB->IndexPtr[1]) {
VB->IndexPtr[1]->data[dst] = VB->IndexPtr[1]->data[src];
}
copy_pv_tab[SWSETUP_CONTEXT(ctx)->SetupIndex](ctx, dst, src);
}
/***********************************************************************
* Initialization
***********************************************************************/
static void
emit_invalid( GLcontext *ctx, GLuint start, GLuint end, GLuint newinputs )
{
_mesa_debug(ctx, "swrast_setup: invalid setup function\n");
(void) (ctx && start && end && newinputs);
}
static void
interp_invalid( GLcontext *ctx, GLfloat t,
GLuint edst, GLuint eout, GLuint ein,
GLboolean force_boundary )
{
_mesa_debug(ctx, "swrast_setup: invalid interp function\n");
(void) (ctx && t && edst && eout && ein && force_boundary);
}
static void
copy_pv_invalid( GLcontext *ctx, GLuint edst, GLuint esrc )
{
_mesa_debug(ctx, "swrast_setup: invalid copy_pv function\n");
(void) (ctx && edst && esrc );
}
static void init_standard( void )
{
GLuint i;
for (i = 0 ; i < Elements(setup_tab) ; i++) {
setup_tab[i] = emit_invalid;
interp_tab[i] = interp_invalid;
copy_pv_tab[i] = copy_pv_invalid;
}
init_none();
init_color();
init_color_spec();
init_color_fog();
init_color_spec_fog();
init_color_tex0();
init_color_tex0_spec();
init_color_tex0_fog();
init_color_tex0_spec_fog();
init_color_multitex();
init_color_multitex_spec();
init_color_multitex_fog();
init_color_multitex_spec_fog();
init_color_point();
init_color_spec_point();
init_color_fog_point();
init_color_spec_fog_point();
init_color_tex0_point();
init_color_tex0_spec_point();
init_color_tex0_fog_point();
init_color_tex0_spec_fog_point();
init_color_multitex_point();
init_color_multitex_spec_point();
init_color_multitex_fog_point();
init_color_multitex_spec_fog_point();
init_index();
init_index_fog();
init_index_point();
init_index_fog_point();
}
/* debug only */
#if 0
static void
printSetupFlags(const GLcontext *ctx, char *msg, GLuint flags )
{
_mesa_debug(ctx, "%s(%x): %s%s%s%s%s%s%s\n",
msg,
(int) flags,
(flags & COLOR) ? "color, " : "",
(flags & INDEX) ? "index, " : "",
(flags & TEX0) ? "tex0, " : "",
(flags & MULTITEX) ? "multitex, " : "",
(flags & SPEC) ? "spec, " : "",
(flags & FOG) ? "fog, " : "",
(flags & POINT) ? "point, " : "");
}
#endif
void
_swsetup_choose_rastersetup_func(GLcontext *ctx)
{
SScontext *swsetup = SWSETUP_CONTEXT(ctx);
TNLcontext *tnl = TNL_CONTEXT(ctx);
int funcindex = 0;
if (ctx->RenderMode == GL_RENDER) {
if (ctx->Visual.rgbMode) {
funcindex = COLOR;
if (ctx->Texture._EnabledUnits > 1)
funcindex |= MULTITEX; /* a unit above unit[0] is enabled */
else if (ctx->Texture._EnabledUnits == 1)
funcindex |= TEX0; /* only unit 0 is enabled */
if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR)
funcindex |= SPEC;
}
else {
funcindex = INDEX;
}
if (ctx->Point._Attenuated ||
(ctx->VertexProgram.Enabled && ctx->VertexProgram.PointSizeEnabled))
funcindex |= POINT;
if (ctx->Fog.Enabled)
funcindex |= FOG;
}
else if (ctx->RenderMode == GL_FEEDBACK) {
if (ctx->Visual.rgbMode)
funcindex = (COLOR | TEX0); /* is feedback color subject to fogging? */
else
funcindex = INDEX;
}
else
funcindex = 0;
swsetup->SetupIndex = funcindex;
tnl->Driver.Render.BuildVertices = setup_tab[funcindex];
if (ctx->_TriangleCaps & (DD_TRI_LIGHT_TWOSIDE|DD_TRI_UNFILLED)) {
tnl->Driver.Render.Interp = interp_extras;
tnl->Driver.Render.CopyPV = copy_pv_extras;
}
else {
tnl->Driver.Render.Interp = interp_tab[funcindex];
tnl->Driver.Render.CopyPV = copy_pv_tab[funcindex];
}
ASSERT(tnl->Driver.Render.BuildVertices);
ASSERT(tnl->Driver.Render.BuildVertices != emit_invalid);
}
void
_swsetup_vb_init( GLcontext *ctx )
{
(void) ctx;
init_standard();
/*
printSetupFlags(ctx);
*/
}