/shark/trunk/ports/mesa/src/tnl/t_array_api.h |
---|
0,0 → 1,47 |
/* $Id: t_array_api.h,v 1.1 2003-02-28 11:48:06 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 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. |
*/ |
#ifndef _T_VARRAY_H |
#define _T_VARRAY_H |
#include "mtypes.h" |
#include "t_context.h" |
extern void _tnl_DrawArrays(GLenum mode, GLint first, GLsizei count); |
extern void _tnl_DrawElements(GLenum mode, GLsizei count, GLenum type, |
const GLvoid *indices); |
extern void _tnl_DrawRangeElements(GLenum mode, GLuint start, |
GLuint end, GLsizei count, GLenum type, |
const GLvoid *indices); |
extern void _tnl_array_init( GLcontext *ctx ); |
extern void _tnl_array_destroy( GLcontext *ctx ); |
#endif |
/shark/trunk/ports/mesa/src/tnl/t_eval_api.c |
---|
0,0 → 1,248 |
/* $Id: t_eval_api.c,v 1.1 2003-02-28 11:48:06 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 - original code |
* Brian Paul - vertex program updates |
*/ |
#include "glheader.h" |
#include "colormac.h" |
#include "context.h" |
#include "macros.h" |
#include "imports.h" |
#include "mmath.h" |
#include "mtypes.h" |
#include "math/m_eval.h" |
#include "t_eval_api.h" |
#include "t_imm_api.h" |
#include "t_imm_alloc.h" |
#include "t_imm_exec.h" |
/* KW: If are compiling, we don't know whether eval will produce a |
* vertex when it is run in the future. If this is pure immediate |
* mode, eval is a noop if neither vertex map is enabled. |
* |
* Thus we need to have a check in the display list code or |
* elsewhere for eval(1,2) vertices in the case where |
* map(1,2)_vertex is disabled, and to purge those vertices from |
* the vb. |
*/ |
void |
_tnl_exec_EvalMesh1( GLenum mode, GLint i1, GLint i2 ) |
{ |
GET_CURRENT_CONTEXT(ctx); |
GLint i; |
GLfloat u, du; |
GLenum prim; |
ASSERT_OUTSIDE_BEGIN_END(ctx); |
if (MESA_VERBOSE & VERBOSE_API) |
_mesa_debug(ctx, "glEvalMesh1()"); |
switch (mode) { |
case GL_POINT: |
prim = GL_POINTS; |
break; |
case GL_LINE: |
prim = GL_LINE_STRIP; |
break; |
default: |
_mesa_error( ctx, GL_INVALID_ENUM, "glEvalMesh1(mode)" ); |
return; |
} |
/* No effect if vertex maps disabled. |
*/ |
if (!ctx->Eval.Map1Vertex4 && !ctx->Eval.Map1Vertex3 && |
(!ctx->VertexProgram.Enabled || !ctx->Eval.Map1Attrib[VERT_ATTRIB_POS])) |
return; |
du = ctx->Eval.MapGrid1du; |
u = ctx->Eval.MapGrid1u1 + i1 * du; |
/* Need to turn off compilation -- this is already saved, and the |
* coordinates generated and the test above depend on state that |
* may change before the list is executed. |
* |
* TODO: Anaylse display lists to determine if this state is |
* constant. |
* |
* State to watch: |
* - enabled maps |
* - map state for each enabled map, including control points |
* - grid state |
* |
* Could alternatively cache individual maps in arrays, rather than |
* building immediates. |
*/ |
{ |
GLboolean compiling = ctx->CompileFlag; |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct immediate *im = TNL_CURRENT_IM(ctx); |
GLboolean (*NotifyBegin)(GLcontext *ctx, GLenum p); |
NotifyBegin = tnl->Driver.NotifyBegin; |
tnl->Driver.NotifyBegin = 0; |
if (compiling) { |
struct immediate *tmp = _tnl_alloc_immediate( ctx ); |
FLUSH_VERTICES( ctx, 0 ); |
SET_IMMEDIATE( ctx, tmp ); |
TNL_CURRENT_IM(ctx)->ref_count++; |
ctx->CompileFlag = GL_FALSE; |
} |
_tnl_Begin( prim ); |
for (i=i1;i<=i2;i++,u+=du) { |
_tnl_eval_coord1f( ctx, u ); |
} |
_tnl_end(ctx); |
/* Need this for replay *and* compile: |
*/ |
FLUSH_VERTICES( ctx, 0 ); |
tnl->Driver.NotifyBegin = NotifyBegin; |
if (compiling) { |
TNL_CURRENT_IM(ctx)->ref_count--; |
ASSERT( TNL_CURRENT_IM(ctx)->ref_count == 0 ); |
_tnl_free_immediate( ctx, TNL_CURRENT_IM(ctx) ); |
SET_IMMEDIATE( ctx, im ); |
ctx->CompileFlag = GL_TRUE; |
} |
} |
} |
void |
_tnl_exec_EvalMesh2( GLenum mode, GLint i1, GLint i2, GLint j1, GLint j2 ) |
{ |
GET_CURRENT_CONTEXT(ctx); |
GLint i, j; |
GLfloat u, du, v, dv, v1, u1; |
ASSERT_OUTSIDE_BEGIN_END(ctx); |
if (MESA_VERBOSE & VERBOSE_API) |
_mesa_debug(ctx, "glEvalMesh2()"); |
/* No effect if vertex maps disabled. |
*/ |
if (!ctx->Eval.Map2Vertex4 && !ctx->Eval.Map2Vertex3 && |
(!ctx->VertexProgram.Enabled || !ctx->Eval.Map2Attrib[VERT_ATTRIB_POS])) |
return; |
du = ctx->Eval.MapGrid2du; |
dv = ctx->Eval.MapGrid2dv; |
v1 = ctx->Eval.MapGrid2v1 + j1 * dv; |
u1 = ctx->Eval.MapGrid2u1 + i1 * du; |
/* Need to turn off compilation -- this is already saved, and the |
* coordinates generated and the test above depend on state that |
* may change before the list is executed. |
*/ |
{ |
GLboolean compiling = ctx->CompileFlag; |
struct immediate *im = TNL_CURRENT_IM(ctx); |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
GLboolean (*NotifyBegin)(GLcontext *ctx, GLenum p); |
NotifyBegin = tnl->Driver.NotifyBegin; |
tnl->Driver.NotifyBegin = 0; |
if (compiling) { |
struct immediate *tmp = _tnl_alloc_immediate( ctx ); |
FLUSH_VERTICES( ctx, 0 ); |
SET_IMMEDIATE( ctx, tmp ); |
TNL_CURRENT_IM(ctx)->ref_count++; |
ctx->CompileFlag = GL_FALSE; |
} |
switch (mode) { |
case GL_POINT: |
_tnl_Begin( GL_POINTS ); |
for (v=v1,j=j1;j<=j2;j++,v+=dv) { |
for (u=u1,i=i1;i<=i2;i++,u+=du) { |
_tnl_eval_coord2f( ctx, u, v ); |
} |
} |
_tnl_end(ctx); |
break; |
case GL_LINE: |
for (v=v1,j=j1;j<=j2;j++,v+=dv) { |
_tnl_Begin( GL_LINE_STRIP ); |
for (u=u1,i=i1;i<=i2;i++,u+=du) { |
_tnl_eval_coord2f( ctx, u, v ); |
} |
_tnl_end(ctx); |
} |
for (u=u1,i=i1;i<=i2;i++,u+=du) { |
_tnl_Begin( GL_LINE_STRIP ); |
for (v=v1,j=j1;j<=j2;j++,v+=dv) { |
_tnl_eval_coord2f( ctx, u, v ); |
} |
_tnl_end(ctx); |
} |
break; |
case GL_FILL: |
for (v=v1,j=j1;j<j2;j++,v+=dv) { |
_tnl_Begin( GL_TRIANGLE_STRIP ); |
for (u=u1,i=i1;i<=i2;i++,u+=du) { |
_tnl_eval_coord2f( ctx, u, v ); |
_tnl_eval_coord2f( ctx, u, v+dv ); |
} |
_tnl_end(ctx); |
} |
break; |
default: |
_mesa_error( ctx, GL_INVALID_ENUM, "glEvalMesh2(mode)" ); |
return; |
} |
/* Need this for replay *and* compile: |
*/ |
FLUSH_VERTICES( ctx, 0 ); |
tnl->Driver.NotifyBegin = NotifyBegin; |
if (compiling) { |
TNL_CURRENT_IM(ctx)->ref_count--; |
_tnl_free_immediate( ctx, TNL_CURRENT_IM( ctx ) ); |
SET_IMMEDIATE( ctx, im ); |
ctx->CompileFlag = GL_TRUE; |
} |
} |
} |
void _tnl_eval_init( GLcontext *ctx ) |
{ |
GLvertexformat *vfmt = &(TNL_CONTEXT(ctx)->vtxfmt); |
vfmt->EvalMesh1 = _tnl_exec_EvalMesh1; |
vfmt->EvalMesh2 = _tnl_exec_EvalMesh2; |
} |
/shark/trunk/ports/mesa/src/tnl/t_vtx_exec.c |
---|
0,0 → 1,632 |
/* $XFree86$ */ |
/************************************************************************** |
Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas. |
All Rights Reserved. |
Permission is hereby granted, free of charge, to any person obtaining a |
copy of this software and associated documentation files (the "Software"), |
to deal in the Software without restriction, including without limitation |
on the rights to use, copy, modify, merge, publish, distribute, sub |
license, and/or sell copies of the Software, and to permit persons to whom |
the Software is furnished to do so, subject to the following conditions: |
The above copyright notice and this permission notice (including the next |
paragraph) shall be included in all copies or substantial portions of the |
Software. |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, |
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
USE OR OTHER DEALINGS IN THE SOFTWARE. |
**************************************************************************/ |
/* |
* Authors: |
* Keith Whitwell <keith@tungstengraphics.com> |
* |
*/ |
#include "api_noop.h" |
#include "api_arrayelt.h" |
#include "context.h" |
#include "imports.h" |
#include "mmath.h" |
#include "mtypes.h" |
#include "enums.h" |
#include "glapi.h" |
#include "colormac.h" |
#include "light.h" |
#include "state.h" |
#include "vtxfmt.h" |
#include "tnl/tnl.h" |
#include "tnl/t_context.h" |
#include "tnl/t_array_api.h" |
static void _tnl_FlushVertices( GLcontext *, GLuint ); |
void tnl_copy_to_current( GLcontext *ctx ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
GLuint flag = tnl->vertex_format; |
GLint i; |
assert(ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT); |
for (i = 0 ; i < 16 ; i++) |
if (flag & (1<<i)) |
COPY_4FV( ctx->Current.Attrib[i], tnl->attribptr[i] ); |
if (flag & VERT_BIT_INDEX) |
ctx->Current.Index = tnl->indexptr[0]; |
if (flag & VERT_BIT_EDGEFLAG) |
ctx->Current.EdgeFlag = tnl->edgeflagptr[0]; |
if (flag & VERT_BIT_MATERIAL) { |
_mesa_update_material( ctx, |
IM->Material[IM->LastMaterial], |
IM->MaterialOrMask ); |
tnl->Driver.NotifyMaterialChange( ctx ); |
} |
ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT; |
} |
static GLboolean discreet_gl_prim[GL_POLYGON+1] = { |
1, /* 0 points */ |
1, /* 1 lines */ |
0, /* 2 line_strip */ |
0, /* 3 line_loop */ |
1, /* 4 tris */ |
0, /* 5 tri_fan */ |
0, /* 6 tri_strip */ |
1, /* 7 quads */ |
0, /* 8 quadstrip */ |
0, /* 9 poly */ |
}; |
/* Optimize the primitive list: ONLY FOR EXECUTE ATM |
*/ |
static void optimize_prims( TNLcontext *tnl ) |
{ |
int i, j; |
if (tnl->nrprims <= 1) |
return; |
for (j = 0, i = 1 ; i < tnl->nrprims; i++) { |
int pj = tnl->primlist[j].prim & 0xf; |
int pi = tnl->primlist[i].prim & 0xf; |
if (pj == pi && discreet_gl_prim[pj] && |
tnl->primlist[i].start == tnl->primlist[j].end) { |
tnl->primlist[j].end = tnl->primlist[i].end; |
} |
else { |
j++; |
if (j != i) tnl->primlist[j] = tnl->primlist[i]; |
} |
} |
tnl->nrprims = j+1; |
} |
/* Bind vertex buffer pointers, run pipeline: |
*/ |
static void flush_prims( TNLcontext *tnl ) |
{ |
int i,j; |
tnl->dma.current.ptr = tnl->dma.current.start += |
(tnl->initial_counter - tnl->counter) * tnl->vertex_size * 4; |
tnl->tcl.vertex_format = tnl->vertex_format; |
tnl->tcl.aos_components[0] = &tmp; |
tnl->tcl.nr_aos_components = 1; |
tnl->dma.flush = 0; |
tnl->Driver.RunPipeline( ... ); |
tnl->nrprims = 0; |
} |
static void start_prim( TNLcontext *tnl, GLuint mode ) |
{ |
if (MESA_VERBOSE & DEBUG_VFMT) |
_mesa_debug(NULL, "%s %d\n", __FUNCTION__, |
tnl->initial_counter - tnl->counter); |
tnl->primlist[tnl->nrprims].start = tnl->initial_counter - tnl->counter; |
tnl->primlist[tnl->nrprims].prim = mode; |
} |
static void note_last_prim( TNLcontext *tnl, GLuint flags ) |
{ |
if (MESA_VERBOSE & DEBUG_VFMT) |
_mesa_debug(NULL, "%s %d\n", __FUNCTION__, |
tnl->initial_counter - tnl->counter); |
if (tnl->prim[0] != GL_POLYGON+1) { |
tnl->primlist[tnl->nrprims].prim |= flags; |
tnl->primlist[tnl->nrprims].end = tnl->initial_counter - tnl->counter; |
if (++tnl->nrprims == TNL_MAX_PRIMS) |
flush_prims( tnl ); |
} |
} |
static void copy_vertex( TNLcontext *tnl, GLuint n, GLfloat *dst ) |
{ |
GLuint i; |
GLfloat *src = (GLfloat *)(tnl->dma.current.address + |
tnl->dma.current.ptr + |
(tnl->primlist[tnl->nrprims].start + n) * |
tnl->vertex_size * 4); |
if (MESA_VERBOSE & DEBUG_VFMT) |
_mesa_debug(NULL, "copy_vertex %d\n", |
tnl->primlist[tnl->nrprims].start + n); |
for (i = 0 ; i < tnl->vertex_size; i++) { |
dst[i] = src[i]; |
} |
} |
static GLuint copy_wrapped_verts( TNLcontext *tnl, GLfloat (*tmp)[15] ) |
{ |
GLuint ovf, i; |
GLuint nr = (tnl->initial_counter - tnl->counter) - tnl->primlist[tnl->nrprims].start; |
if (MESA_VERBOSE & DEBUG_VFMT) |
_mesa_debug(NULL, "%s %d verts\n", __FUNCTION__, nr); |
switch( tnl->prim[0] ) |
{ |
case GL_POINTS: |
return 0; |
case GL_LINES: |
ovf = nr&1; |
for (i = 0 ; i < ovf ; i++) |
copy_vertex( tnl, nr-ovf+i, tmp[i] ); |
return i; |
case GL_TRIANGLES: |
ovf = nr%3; |
for (i = 0 ; i < ovf ; i++) |
copy_vertex( tnl, nr-ovf+i, tmp[i] ); |
return i; |
case GL_QUADS: |
ovf = nr&3; |
for (i = 0 ; i < ovf ; i++) |
copy_vertex( tnl, nr-ovf+i, tmp[i] ); |
return i; |
case GL_LINE_STRIP: |
if (nr == 0) |
return 0; |
copy_vertex( tnl, nr-1, tmp[0] ); |
return 1; |
case GL_LINE_LOOP: |
case GL_TRIANGLE_FAN: |
case GL_POLYGON: |
if (nr == 0) |
return 0; |
else if (nr == 1) { |
copy_vertex( tnl, 0, tmp[0] ); |
return 1; |
} else { |
copy_vertex( tnl, 0, tmp[0] ); |
copy_vertex( tnl, nr-1, tmp[1] ); |
return 2; |
} |
case GL_TRIANGLE_STRIP: |
ovf = MIN2( nr-1, 2 ); |
for (i = 0 ; i < ovf ; i++) |
copy_vertex( tnl, nr-ovf+i, tmp[i] ); |
return i; |
case GL_QUAD_STRIP: |
ovf = MIN2( nr-1, 2 ); |
if (nr > 2) ovf += nr&1; |
for (i = 0 ; i < ovf ; i++) |
copy_vertex( tnl, nr-ovf+i, tmp[i] ); |
return i; |
default: |
assert(0); |
return 0; |
} |
} |
/* Extend for vertex-format changes on wrap: |
*/ |
static void wrap_buffer( void ) |
{ |
TNLcontext *tnl = tnl->tnl; |
GLfloat tmp[3][15]; |
GLuint i, nrverts; |
if (MESA_VERBOSE & (DEBUG_VFMT|DEBUG_PRIMS)) |
_mesa_debug(NULL, "%s %d\n", __FUNCTION__, |
tnl->initial_counter - tnl->counter); |
/* Don't deal with parity. *** WONT WORK FOR COMPILE |
*/ |
if ((((tnl->initial_counter - tnl->counter) - |
tnl->primlist[tnl->nrprims].start) & 1)) { |
tnl->counter++; |
tnl->initial_counter++; |
return; |
} |
/* Copy vertices out of dma: |
*/ |
nrverts = copy_dma_verts( tnl, tmp ); |
if (MESA_VERBOSE & DEBUG_VFMT) |
_mesa_debug(NULL, "%d vertices to copy\n", nrverts); |
/* Finish the prim at this point: |
*/ |
note_last_prim( tnl, 0 ); |
flush_prims( tnl ); |
/* Reset counter, dmaptr |
*/ |
tnl->dmaptr = (int *)(tnl->dma.current.ptr + tnl->dma.current.address); |
tnl->counter = (tnl->dma.current.end - tnl->dma.current.ptr) / |
(tnl->vertex_size * 4); |
tnl->counter--; |
tnl->initial_counter = tnl->counter; |
tnl->notify = wrap_buffer; |
tnl->dma.flush = flush_prims; |
start_prim( tnl, tnl->prim[0] ); |
/* Reemit saved vertices |
* *** POSSIBLY IN NEW FORMAT |
* --> Can't always extend at end of vertex? |
*/ |
for (i = 0 ; i < nrverts; i++) { |
if (MESA_VERBOSE & DEBUG_VERTS) { |
int j; |
_mesa_debug(NULL, "re-emit vertex %d to %p\n", i, tnl->dmaptr); |
if (MESA_VERBOSE & DEBUG_VERBOSE) |
for (j = 0 ; j < tnl->vertex_size; j++) |
_mesa_debug(NULL, "\t%08x/%f\n", *(int*)&tmp[i][j], tmp[i][j]); |
} |
memcpy( tnl->dmaptr, tmp[i], tnl->vertex_size * 4 ); |
tnl->dmaptr += tnl->vertex_size; |
tnl->counter--; |
} |
} |
/* Always follow data, don't try to predict what's necessary. |
*/ |
static GLboolean check_vtx_fmt( GLcontext *ctx ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
if (ctx->Driver.NeedFlush & FLUSH_UPDATE_CURRENT) |
ctx->Driver.FlushVertices( ctx, FLUSH_UPDATE_CURRENT ); |
TNL_NEWPRIM(tnl); |
tnl->vertex_format = VERT_BIT_POS; |
tnl->prim = &ctx->Driver.CurrentExecPrimitive; |
/* Currently allow the full 4 components per attrib. Can use the |
* mechanism from radeon driver color handling to reduce this (and |
* also to store ubyte colors where these are incoming). This |
* won't work for compile mode. |
* |
* Only adding components when they are first received eliminates |
* the need for displaylist fixup, as there are no 'empty' slots |
* at the start of buffers. |
*/ |
for (i = 0 ; i < 16 ; i++) { |
if (ind & (1<<i)) { |
tnl->attribptr[i] = &tnl->vertex[tnl->vertex_size].f; |
tnl->vertex_size += 4; |
tnl->attribptr[i][0] = ctx->Current.Attrib[i][0]; |
tnl->attribptr[i][1] = ctx->Current.Attrib[i][1]; |
tnl->attribptr[i][2] = ctx->Current.Attrib[i][2]; |
tnl->attribptr[i][3] = ctx->Current.Attrib[i][3]; |
} |
else |
tnl->attribptr[i] = ctx->Current.Attrib[i]; |
} |
/* Edgeflag, Index: |
*/ |
for (i = 16 ; i < 18 ; i++) |
; |
/* Materials: |
*/ |
for (i = 18 ; i < 28 ; i++) |
; |
/* Eval: |
*/ |
for (i = 28 ; i < 29 ; i++) |
; |
if (tnl->installed_vertex_format != tnl->vertex_format) { |
if (MESA_VERBOSE & DEBUG_VFMT) |
_mesa_debug(NULL, "reinstall on vertex_format change\n"); |
_mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt ); |
tnl->installed_vertex_format = tnl->vertex_format; |
} |
return GL_TRUE; |
} |
void _tnl_InvalidateVtxfmt( GLcontext *ctx ) |
{ |
tnl->recheck = GL_TRUE; |
tnl->fell_back = GL_FALSE; |
} |
static void _tnl_ValidateVtxfmt( GLcontext *ctx ) |
{ |
if (MESA_VERBOSE & DEBUG_VFMT) |
_mesa_debug(NULL, "%s\n", __FUNCTION__); |
if (ctx->Driver.NeedFlush) |
ctx->Driver.FlushVertices( ctx, ctx->Driver.NeedFlush ); |
tnl->recheck = GL_FALSE; |
if (check_vtx_fmt( ctx )) { |
if (!tnl->installed) { |
if (MESA_VERBOSE & DEBUG_VFMT) |
_mesa_debug(NULL, "reinstall (new install)\n"); |
_mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt ); |
ctx->Driver.FlushVertices = _tnl_FlushVertices; |
tnl->installed = GL_TRUE; |
} |
else |
_mesa_debug(NULL, "%s: already installed", __FUNCTION__); |
} |
else { |
if (MESA_VERBOSE & DEBUG_VFMT) |
_mesa_debug(NULL, "%s: failed\n", __FUNCTION__); |
if (tnl->installed) { |
if (tnl->tnl->dma.flush) |
tnl->tnl->dma.flush( tnl->tnl ); |
_tnl_wakeup_exec( ctx ); |
tnl->installed = GL_FALSE; |
} |
} |
} |
/* Begin/End |
*/ |
static void _tnl_Begin( GLenum mode ) |
{ |
GLcontext *ctx = tnl->context; |
TNLcontext *tnl = tnl->tnl; |
if (MESA_VERBOSE & DEBUG_VFMT) |
_mesa_debug(NULL, "%s\n", __FUNCTION__); |
if (mode > GL_POLYGON) { |
_mesa_error( ctx, GL_INVALID_ENUM, "glBegin" ); |
return; |
} |
if (tnl->prim[0] != GL_POLYGON+1) { |
_mesa_error( ctx, GL_INVALID_OPERATION, "glBegin" ); |
return; |
} |
if (ctx->NewState) |
_mesa_update_state( ctx ); |
if (tnl->recheck) |
_tnl_ValidateVtxfmt( ctx ); |
if (tnl->dma.flush && tnl->counter < 12) { |
if (MESA_VERBOSE & DEBUG_VFMT) |
_mesa_debug(NULL, "%s: flush almost-empty buffers\n", __FUNCTION__); |
flush_prims( tnl ); |
} |
if (!tnl->dma.flush) { |
if (tnl->dma.current.ptr + 12*tnl->vertex_size*4 > |
tnl->dma.current.end) { |
TNL_NEWPRIM( tnl ); |
_tnl_RefillCurrentDmaRegion( tnl ); |
} |
tnl->dmaptr = (int *)(tnl->dma.current.address + tnl->dma.current.ptr); |
tnl->counter = (tnl->dma.current.end - tnl->dma.current.ptr) / |
(tnl->vertex_size * 4); |
tnl->counter--; |
tnl->initial_counter = tnl->counter; |
tnl->notify = wrap_buffer; |
tnl->dma.flush = flush_prims; |
tnl->context->Driver.NeedFlush |= FLUSH_STORED_VERTICES; |
} |
tnl->prim[0] = mode; |
start_prim( tnl, mode | PRIM_BEGIN ); |
} |
static void _tnl_End( void ) |
{ |
TNLcontext *tnl = tnl->tnl; |
GLcontext *ctx = tnl->context; |
if (MESA_VERBOSE & DEBUG_VFMT) |
_mesa_debug(NULL, "%s\n", __FUNCTION__); |
if (tnl->prim[0] == GL_POLYGON+1) { |
_mesa_error( ctx, GL_INVALID_OPERATION, "glEnd" ); |
return; |
} |
note_last_prim( tnl, PRIM_END ); |
tnl->prim[0] = GL_POLYGON+1; |
} |
static void _tnl_FlushVertices( GLcontext *ctx, GLuint flags ) |
{ |
if (MESA_VERBOSE & DEBUG_VFMT) |
_mesa_debug(NULL, "%s\n", __FUNCTION__); |
assert(tnl->installed); |
if (flags & FLUSH_UPDATE_CURRENT) { |
_tnl_copy_to_current( ctx ); |
if (MESA_VERBOSE & DEBUG_VFMT) |
_mesa_debug(NULL, "reinstall on update_current\n"); |
_mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt ); |
ctx->Driver.NeedFlush &= ~FLUSH_UPDATE_CURRENT; |
} |
if (flags & FLUSH_STORED_VERTICES) { |
TNLcontext *tnl = TNL_CONTEXT( ctx ); |
assert (tnl->dma.flush == 0 || |
tnl->dma.flush == flush_prims); |
if (tnl->dma.flush == flush_prims) |
flush_prims( TNL_CONTEXT( ctx ) ); |
ctx->Driver.NeedFlush &= ~FLUSH_STORED_VERTICES; |
} |
} |
/* At this point, don't expect very many versions of each function to |
* be generated, so not concerned about freeing them? |
*/ |
static void _tnl_InitVtxfmt( GLcontext *ctx ) |
{ |
GLvertexformat *vfmt = &(tnl->vtxfmt); |
MEMSET( vfmt, 0, sizeof(GLvertexformat) ); |
/* Hook in chooser functions for codegen, etc: |
*/ |
_tnl_InitVtxfmtChoosers( vfmt ); |
/* Handled fully in supported states, but no codegen: |
*/ |
vfmt->ArrayElement = _ae_loopback_array_elt; /* generic helper */ |
vfmt->Rectf = _mesa_noop_Rectf; /* generic helper */ |
vfmt->Begin = _tnl_Begin; |
vfmt->End = _tnl_End; |
tnl->context = ctx; |
tnl->tnl = TNL_CONTEXT(ctx); |
tnl->prim = &ctx->Driver.CurrentExecPrimitive; |
tnl->primflags = 0; |
make_empty_list( &tnl->dfn_cache.Vertex2f ); |
make_empty_list( &tnl->dfn_cache.Vertex2fv ); |
make_empty_list( &tnl->dfn_cache.Vertex3f ); |
make_empty_list( &tnl->dfn_cache.Vertex3fv ); |
make_empty_list( &tnl->dfn_cache.Color4ub ); |
make_empty_list( &tnl->dfn_cache.Color4ubv ); |
make_empty_list( &tnl->dfn_cache.Color3ub ); |
make_empty_list( &tnl->dfn_cache.Color3ubv ); |
make_empty_list( &tnl->dfn_cache.Color4f ); |
make_empty_list( &tnl->dfn_cache.Color4fv ); |
make_empty_list( &tnl->dfn_cache.Color3f ); |
make_empty_list( &tnl->dfn_cache.Color3fv ); |
make_empty_list( &tnl->dfn_cache.SecondaryColor3fEXT ); |
make_empty_list( &tnl->dfn_cache.SecondaryColor3fvEXT ); |
make_empty_list( &tnl->dfn_cache.SecondaryColor3ubEXT ); |
make_empty_list( &tnl->dfn_cache.SecondaryColor3ubvEXT ); |
make_empty_list( &tnl->dfn_cache.Normal3f ); |
make_empty_list( &tnl->dfn_cache.Normal3fv ); |
make_empty_list( &tnl->dfn_cache.TexCoord2f ); |
make_empty_list( &tnl->dfn_cache.TexCoord2fv ); |
make_empty_list( &tnl->dfn_cache.TexCoord1f ); |
make_empty_list( &tnl->dfn_cache.TexCoord1fv ); |
make_empty_list( &tnl->dfn_cache.MultiTexCoord2fARB ); |
make_empty_list( &tnl->dfn_cache.MultiTexCoord2fvARB ); |
make_empty_list( &tnl->dfn_cache.MultiTexCoord1fARB ); |
make_empty_list( &tnl->dfn_cache.MultiTexCoord1fvARB ); |
_tnl_InitCodegen( &tnl->codegen ); |
} |
static void free_funcs( struct dynfn *l ) |
{ |
struct dynfn *f, *tmp; |
foreach_s (f, tmp, l) { |
remove_from_list( f ); |
ALIGN_FREE( f->code ); |
FREE( f ); |
} |
} |
static void _tnl_DestroyVtxfmt( GLcontext *ctx ) |
{ |
count_funcs(); |
free_funcs( &tnl->dfn_cache.Vertex2f ); |
free_funcs( &tnl->dfn_cache.Vertex2fv ); |
free_funcs( &tnl->dfn_cache.Vertex3f ); |
free_funcs( &tnl->dfn_cache.Vertex3fv ); |
free_funcs( &tnl->dfn_cache.Color4ub ); |
free_funcs( &tnl->dfn_cache.Color4ubv ); |
free_funcs( &tnl->dfn_cache.Color3ub ); |
free_funcs( &tnl->dfn_cache.Color3ubv ); |
free_funcs( &tnl->dfn_cache.Color4f ); |
free_funcs( &tnl->dfn_cache.Color4fv ); |
free_funcs( &tnl->dfn_cache.Color3f ); |
free_funcs( &tnl->dfn_cache.Color3fv ); |
free_funcs( &tnl->dfn_cache.SecondaryColor3ubEXT ); |
free_funcs( &tnl->dfn_cache.SecondaryColor3ubvEXT ); |
free_funcs( &tnl->dfn_cache.SecondaryColor3fEXT ); |
free_funcs( &tnl->dfn_cache.SecondaryColor3fvEXT ); |
free_funcs( &tnl->dfn_cache.Normal3f ); |
free_funcs( &tnl->dfn_cache.Normal3fv ); |
free_funcs( &tnl->dfn_cache.TexCoord2f ); |
free_funcs( &tnl->dfn_cache.TexCoord2fv ); |
free_funcs( &tnl->dfn_cache.TexCoord1f ); |
free_funcs( &tnl->dfn_cache.TexCoord1fv ); |
free_funcs( &tnl->dfn_cache.MultiTexCoord2fARB ); |
free_funcs( &tnl->dfn_cache.MultiTexCoord2fvARB ); |
free_funcs( &tnl->dfn_cache.MultiTexCoord1fARB ); |
free_funcs( &tnl->dfn_cache.MultiTexCoord1fvARB ); |
} |
/shark/trunk/ports/mesa/src/tnl/t_eval_api.h |
---|
0,0 → 1,44 |
/* $Id: t_eval_api.h,v 1.1 2003-02-28 11:48:06 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 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. |
*/ |
#ifndef _T_EVAL_H |
#define _T_EVAL_H |
#include "mtypes.h" |
#include "t_context.h" |
/* Use _mesa_save_EvalMesh{1,2} to save these to display lists. |
*/ |
extern void _tnl_exec_EvalMesh1( GLenum mode, GLint i1, GLint i2 ); |
extern void _tnl_exec_EvalMesh2( GLenum mode, GLint i1, GLint i2, |
GLint j1, GLint j2 ); |
void _tnl_eval_init( GLcontext *ctx ); |
#endif |
/shark/trunk/ports/mesa/src/tnl/t_vtx_x86.c |
---|
0,0 → 1,705 |
/* $XFree86$ */ |
/************************************************************************** |
Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas. |
All Rights Reserved. |
Permission is hereby granted, free of charge, to any person obtaining a |
copy of this software and associated documentation files (the "Software"), |
to deal in the Software without restriction, including without limitation |
on the rights to use, copy, modify, merge, publish, distribute, sub |
license, and/or sell copies of the Software, and to permit persons to whom |
the Software is furnished to do so, subject to the following conditions: |
The above copyright notice and this permission notice (including the next |
paragraph) shall be included in all copies or substantial portions of the |
Software. |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, |
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
USE OR OTHER DEALINGS IN THE SOFTWARE. |
**************************************************************************/ |
/* |
* Authors: |
* Keith Whitwell <keith@tungstengraphics.com> |
*/ |
#include "imports.h" |
#include "mmath.h" |
#include "simple_list.h" |
#include "tnl_vtxfmt.h" |
#if defined(USE_X86_ASM) |
struct dynfn *tnl_makeX86Vertex2f( TNLcontext *tnl, int key ) |
{ |
struct dynfn *dfn = MALLOC_STRUCT( dynfn ); |
if (RADEON_DEBUG & DEBUG_CODEGEN) |
_mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key ); |
switch (tnl->vertex_size) { |
default: { |
/* Repz convenient as it's possible to emit code for any size |
* vertex with little tweaking. Might as well read vertsize |
* though, and have only one of these. |
*/ |
static char temp[] = { |
0x57, /* push %edi */ |
0x56, /* push %esi */ |
0xbe, 0, 0, 0, 0, /* mov $VERTEX+2,%esi */ |
0x8b, 0x3d, 0, 0, 0, 0, /* mov DMAPTR,%edi */ |
0x8b, 0x44, 0x24, 0x0c, /* mov 0x0c(%esp,1),%eax */ |
0x8b, 0x54, 0x24, 0x10, /* mov 0x10(%esp,1),%edx */ |
0x89, 0x07, /* mov %eax,(%edi) */ |
0x89, 0x57, 0x04, /* mov %edx,0x4(%edi) */ |
0x83, 0xc7, 0x08, /* add $0x8,%edi */ |
0xb9, 0, 0, 0, 0, /* mov $VERTSIZE-2,%ecx */ |
0xf3, 0xa5, /* repz movsl %ds:(%esi),%es:(%edi)*/ |
0xa1, 0, 0, 0, 0, /* mov COUNTER,%eax */ |
0x89, 0x3d, 0, 0, 0, 0, /* mov %edi,DMAPTR */ |
0x48, /* dec %eax */ |
0xa3, 0, 0, 0, 0, /* mov %eax,COUNTER */ |
0x5e, /* pop %esi */ |
0x5f, /* pop %edi */ |
0x74, 0x01, /* je +1 */ |
0xc3, /* ret */ |
0xff, 0x25, 0, 0, 0, 0 /* jmp NOTIFY */ |
}; |
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); |
memcpy (dfn->code, temp, sizeof(temp)); |
FIXUP(dfn->code, 3, 0x0, (int)&tnl->vertex[2]); |
FIXUP(dfn->code, 9, 0x0, (int)&tnl->dmaptr); |
FIXUP(dfn->code, 37, 0x0, tnl->vertex_size-2); |
FIXUP(dfn->code, 44, 0x0, (int)&tnl->counter); |
FIXUP(dfn->code, 50, 0x0, (int)&tnl->dmaptr); |
FIXUP(dfn->code, 56, 0x0, (int)&tnl->counter); |
FIXUP(dfn->code, 67, 0x0, (int)&tnl->notify); |
break; |
} |
} |
insert_at_head( &tnl->dfn_cache.Vertex3f, dfn ); |
dfn->key = key; |
return dfn; |
} |
/* Build specialized versions of the immediate calls on the fly for |
* the current state. Generic x86 versions. |
*/ |
struct dynfn *tnl_makeX86Vertex3f( TNLcontext *tnl, int key ) |
{ |
struct dynfn *dfn = MALLOC_STRUCT( dynfn ); |
if (RADEON_DEBUG & DEBUG_CODEGEN) |
_mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key ); |
switch (tnl->vertex_size) { |
case 4: { |
static char temp[] = { |
0x8b, 0x0d, 0,0,0,0, /* mov DMAPTR,%ecx */ |
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ |
0x8b, 0x54, 0x24, 0x08, /* mov 0x8(%esp,1),%edx */ |
0x89, 0x01, /* mov %eax,(%ecx) */ |
0x89, 0x51, 0x04, /* mov %edx,0x4(%ecx) */ |
0x8b, 0x44, 0x24, 0x0c, /* mov 0xc(%esp,1),%eax */ |
0x8b, 0x15, 0,0,0,0, /* mov VERTEX[3],%edx */ |
0x89, 0x41, 0x08, /* mov %eax,0x8(%ecx) */ |
0x89, 0x51, 0x0c, /* mov %edx,0xc(%ecx) */ |
0xa1, 0, 0, 0, 0, /* mov COUNTER,%eax */ |
0x83, 0xc1, 0x10, /* add $0x10,%ecx */ |
0x48, /* dec %eax */ |
0x89, 0x0d, 0,0,0,0, /* mov %ecx,DMAPTR */ |
0xa3, 0, 0, 0, 0, /* mov %eax,COUNTER */ |
0x74, 0x01, /* je +1 */ |
0xc3, /* ret */ |
0xff, 0x25, 0,0,0,0 /* jmp *NOTIFY */ |
}; |
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); |
memcpy (dfn->code, temp, sizeof(temp)); |
FIXUP(dfn->code, 2, 0x0, (int)&tnl->dmaptr); |
FIXUP(dfn->code, 25, 0x0, (int)&tnl->vertex[3]); |
FIXUP(dfn->code, 36, 0x0, (int)&tnl->counter); |
FIXUP(dfn->code, 46, 0x0, (int)&tnl->dmaptr); |
FIXUP(dfn->code, 51, 0x0, (int)&tnl->counter); |
FIXUP(dfn->code, 60, 0x0, (int)&tnl->notify); |
break; |
} |
case 6: { |
static char temp[] = { |
0x57, /* push %edi */ |
0x8b, 0x3d, 0, 0, 0, 0, /* mov DMAPTR,%edi */ |
0x8b, 0x44, 0x24, 0x8, /* mov 0x8(%esp,1),%eax */ |
0x8b, 0x54, 0x24, 0xc, /* mov 0xc(%esp,1),%edx */ |
0x8b, 0x4c, 0x24, 0x10, /* mov 0x10(%esp,1),%ecx */ |
0x89, 0x07, /* mov %eax,(%edi) */ |
0x89, 0x57, 0x04, /* mov %edx,0x4(%edi) */ |
0x89, 0x4f, 0x08, /* mov %ecx,0x8(%edi) */ |
0xa1, 0, 0, 0, 0, /* mov VERTEX[3],%eax */ |
0x8b, 0x15, 0, 0, 0, 0, /* mov VERTEX[4],%edx */ |
0x8b, 0x0d, 0, 0, 0, 0, /* mov VERTEX[5],%ecx */ |
0x89, 0x47, 0x0c, /* mov %eax,0xc(%edi) */ |
0x89, 0x57, 0x10, /* mov %edx,0x10(%edi) */ |
0x89, 0x4f, 0x14, /* mov %ecx,0x14(%edi) */ |
0x83, 0xc7, 0x18, /* add $0x18,%edi */ |
0xa1, 0, 0, 0, 0, /* mov COUNTER,%eax */ |
0x89, 0x3d, 0, 0, 0, 0, /* mov %edi,DMAPTR */ |
0x48, /* dec %eax */ |
0x5f, /* pop %edi */ |
0xa3, 0, 0, 0, 0, /* mov %eax,COUNTER */ |
0x74, 0x01, /* je +1 */ |
0xc3, /* ret */ |
0xff, 0x25, 0,0,0,0, /* jmp *NOTIFY */ |
}; |
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); |
memcpy (dfn->code, temp, sizeof(temp)); |
FIXUP(dfn->code, 3, 0x0, (int)&tnl->dmaptr); |
FIXUP(dfn->code, 28, 0x0, (int)&tnl->vertex[3]); |
FIXUP(dfn->code, 34, 0x0, (int)&tnl->vertex[4]); |
FIXUP(dfn->code, 40, 0x0, (int)&tnl->vertex[5]); |
FIXUP(dfn->code, 57, 0x0, (int)&tnl->counter); |
FIXUP(dfn->code, 63, 0x0, (int)&tnl->dmaptr); |
FIXUP(dfn->code, 70, 0x0, (int)&tnl->counter); |
FIXUP(dfn->code, 79, 0x0, (int)&tnl->notify); |
break; |
} |
default: { |
/* Repz convenient as it's possible to emit code for any size |
* vertex with little tweaking. Might as well read vertsize |
* though, and have only one of these. |
*/ |
static char temp[] = { |
0x57, /* push %edi */ |
0x56, /* push %esi */ |
0xbe, 0, 0, 0, 0, /* mov $VERTEX+3,%esi */ |
0x8b, 0x3d, 0, 0, 0, 0, /* mov DMAPTR,%edi */ |
0x8b, 0x44, 0x24, 0x0c, /* mov 0x0c(%esp,1),%eax */ |
0x8b, 0x54, 0x24, 0x10, /* mov 0x10(%esp,1),%edx */ |
0x8b, 0x4c, 0x24, 0x14, /* mov 0x14(%esp,1),%ecx */ |
0x89, 0x07, /* mov %eax,(%edi) */ |
0x89, 0x57, 0x04, /* mov %edx,0x4(%edi) */ |
0x89, 0x4f, 0x08, /* mov %ecx,0x8(%edi) */ |
0x83, 0xc7, 0x0c, /* add $0xc,%edi */ |
0xb9, 0, 0, 0, 0, /* mov $VERTSIZE-3,%ecx */ |
0xf3, 0xa5, /* repz movsl %ds:(%esi),%es:(%edi)*/ |
0xa1, 0, 0, 0, 0, /* mov COUNTER,%eax */ |
0x89, 0x3d, 0, 0, 0, 0, /* mov %edi,DMAPTR */ |
0x48, /* dec %eax */ |
0xa3, 0, 0, 0, 0, /* mov %eax,COUNTER */ |
0x5e, /* pop %esi */ |
0x5f, /* pop %edi */ |
0x74, 0x01, /* je +1 */ |
0xc3, /* ret */ |
0xff, 0x25, 0, 0, 0, 0 /* jmp NOTIFY */ |
}; |
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); |
memcpy (dfn->code, temp, sizeof(temp)); |
FIXUP(dfn->code, 3, 0x0, (int)&tnl->vertex[3]); |
FIXUP(dfn->code, 9, 0x0, (int)&tnl->dmaptr); |
FIXUP(dfn->code, 37, 0x0, tnl->vertex_size-3); |
FIXUP(dfn->code, 44, 0x0, (int)&tnl->counter); |
FIXUP(dfn->code, 50, 0x0, (int)&tnl->dmaptr); |
FIXUP(dfn->code, 56, 0x0, (int)&tnl->counter); |
FIXUP(dfn->code, 67, 0x0, (int)&tnl->notify); |
break; |
} |
} |
insert_at_head( &tnl->dfn_cache.Vertex3f, dfn ); |
dfn->key = key; |
return dfn; |
} |
struct dynfn *tnl_makeX86Vertex3fv( TNLcontext *tnl, int key ) |
{ |
struct dynfn *dfn = MALLOC_STRUCT( dynfn ); |
if (TNL_DEBUG & DEBUG_CODEGEN) |
_mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key ); |
switch (tnl->vertex_size) { |
case 6: { |
static char temp[] = { |
0xa1, 0x00, 0x00, 0, 0, /* mov 0x0,%eax */ |
0x8b, 0x4c, 0x24, 0x04, /* mov 0x4(%esp,1),%ecx */ |
0x8b, 0x11, /* mov (%ecx),%edx */ |
0x89, 0x10, /* mov %edx,(%eax) */ |
0x8b, 0x51, 0x04, /* mov 0x4(%ecx),%edx */ |
0x8b, 0x49, 0x08, /* mov 0x8(%ecx),%ecx */ |
0x89, 0x50, 0x04, /* mov %edx,0x4(%eax) */ |
0x89, 0x48, 0x08, /* mov %ecx,0x8(%eax) */ |
0x8b, 0x15, 0x1c, 0, 0, 0, /* mov 0x1c,%edx */ |
0x8b, 0x0d, 0x20, 0, 0, 0, /* mov 0x20,%ecx */ |
0x89, 0x50, 0x0c, /* mov %edx,0xc(%eax) */ |
0x89, 0x48, 0x10, /* mov %ecx,0x10(%eax) */ |
0x8b, 0x15, 0x24, 0, 0, 0, /* mov 0x24,%edx */ |
0x89, 0x50, 0x14, /* mov %edx,0x14(%eax) */ |
0x83, 0xc0, 0x18, /* add $0x18,%eax */ |
0xa3, 0x00, 0x00, 0, 0, /* mov %eax,0x0 */ |
0xa1, 0x04, 0x00, 0, 0, /* mov 0x4,%eax */ |
0x48, /* dec %eax */ |
0xa3, 0x04, 0x00, 0, 0, /* mov %eax,0x4 */ |
0x74, 0x01, /* je 2a4 <.f11> */ |
0xc3, /* ret */ |
0xff, 0x25, 0x08, 0, 0, 0, /* jmp *0x8 */ |
}; |
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); |
memcpy (dfn->code, temp, sizeof(temp)); |
FIXUP(dfn->code, 1, 0x00000000, (int)&tnl->dmaptr); |
FIXUP(dfn->code, 27, 0x0000001c, (int)&tnl->vertex[3]); |
FIXUP(dfn->code, 33, 0x00000020, (int)&tnl->vertex[4]); |
FIXUP(dfn->code, 45, 0x00000024, (int)&tnl->vertex[5]); |
FIXUP(dfn->code, 56, 0x00000000, (int)&tnl->dmaptr); |
FIXUP(dfn->code, 61, 0x00000004, (int)&tnl->counter); |
FIXUP(dfn->code, 67, 0x00000004, (int)&tnl->counter); |
FIXUP(dfn->code, 76, 0x00000008, (int)&tnl->notify); |
break; |
} |
case 8: { |
static char temp[] = { |
0xa1, 0x00, 0x00, 0, 0, /* mov 0x0,%eax */ |
0x8b, 0x4c, 0x24, 0x04, /* mov 0x4(%esp,1),%ecx */ |
0x8b, 0x11, /* mov (%ecx),%edx */ |
0x89, 0x10, /* mov %edx,(%eax) */ |
0x8b, 0x51, 0x04, /* mov 0x4(%ecx),%edx */ |
0x8b, 0x49, 0x08, /* mov 0x8(%ecx),%ecx */ |
0x89, 0x50, 0x04, /* mov %edx,0x4(%eax) */ |
0x89, 0x48, 0x08, /* mov %ecx,0x8(%eax) */ |
0x8b, 0x15, 0x1c, 0, 0, 0, /* mov 0x1c,%edx */ |
0x8b, 0x0d, 0x20, 0, 0, 0, /* mov 0x20,%ecx */ |
0x89, 0x50, 0x0c, /* mov %edx,0xc(%eax) */ |
0x89, 0x48, 0x10, /* mov %ecx,0x10(%eax) */ |
0x8b, 0x15, 0x1c, 0, 0, 0, /* mov 0x1c,%edx */ |
0x8b, 0x0d, 0x20, 0, 0, 0, /* mov 0x20,%ecx */ |
0x89, 0x50, 0x14, /* mov %edx,0x14(%eax) */ |
0x89, 0x48, 0x18, /* mov %ecx,0x18(%eax) */ |
0x8b, 0x15, 0x24, 0, 0, 0, /* mov 0x24,%edx */ |
0x89, 0x50, 0x1c, /* mov %edx,0x1c(%eax) */ |
0x83, 0xc0, 0x20, /* add $0x20,%eax */ |
0xa3, 0x00, 0x00, 0, 0, /* mov %eax,0x0 */ |
0xa1, 0x04, 0x00, 0, 0, /* mov 0x4,%eax */ |
0x48, /* dec %eax */ |
0xa3, 0x04, 0x00, 0, 0, /* mov %eax,0x4 */ |
0x74, 0x01, /* je 2a4 <.f11> */ |
0xc3, /* ret */ |
0xff, 0x25, 0x08, 0, 0, 0, /* jmp *0x8 */ |
}; |
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); |
memcpy (dfn->code, temp, sizeof(temp)); |
FIXUP(dfn->code, 1, 0x00000000, (int)&tnl->dmaptr); |
FIXUP(dfn->code, 27, 0x0000001c, (int)&tnl->vertex[3]); |
FIXUP(dfn->code, 33, 0x00000020, (int)&tnl->vertex[4]); |
FIXUP(dfn->code, 45, 0x0000001c, (int)&tnl->vertex[5]); |
FIXUP(dfn->code, 51, 0x00000020, (int)&tnl->vertex[6]); |
FIXUP(dfn->code, 63, 0x00000024, (int)&tnl->vertex[7]); |
FIXUP(dfn->code, 74, 0x00000000, (int)&tnl->dmaptr); |
FIXUP(dfn->code, 79, 0x00000004, (int)&tnl->counter); |
FIXUP(dfn->code, 85, 0x00000004, (int)&tnl->counter); |
FIXUP(dfn->code, 94, 0x00000008, (int)&tnl->notify); |
break; |
} |
default: { |
/* Repz convenient as it's possible to emit code for any size |
* vertex with little tweaking. Might as well read vertsize |
* though, and have only one of these. |
*/ |
static char temp[] = { |
0x8b, 0x54, 0x24, 0x04, /* mov 0x4(%esp,1),%edx */ |
0x57, /* push %edi */ |
0x56, /* push %esi */ |
0x8b, 0x3d, 1,1,1,1, /* mov DMAPTR,%edi */ |
0x8b, 0x02, /* mov (%edx),%eax */ |
0x8b, 0x4a, 0x04, /* mov 0x4(%edx),%ecx */ |
0x8b, 0x72, 0x08, /* mov 0x8(%edx),%esi */ |
0x89, 0x07, /* mov %eax,(%edi) */ |
0x89, 0x4f, 0x04, /* mov %ecx,0x4(%edi) */ |
0x89, 0x77, 0x08, /* mov %esi,0x8(%edi) */ |
0x83, 0xc7, 0x0c, /* add $0xc,%edi */ |
0xb9, 0x06, 0x00, 0x00, 0x00, /* mov $VERTSIZE-3,%ecx */ |
0xbe, 0x58, 0x00, 0x00, 0x00, /* mov $VERTEX[3],%esi */ |
0xf3, 0xa5, /* repz movsl %ds:(%esi),%es:(%edi)*/ |
0x89, 0x3d, 1, 1, 1, 1, /* mov %edi,DMAPTR */ |
0xa1, 2, 2, 2, 2, /* mov COUNTER,%eax */ |
0x5e, /* pop %esi */ |
0x5f, /* pop %edi */ |
0x48, /* dec %eax */ |
0xa3, 2, 2, 2, 2, /* mov %eax,COUNTER */ |
0x74, 0x01, /* je +1 */ |
0xc3, /* ret */ |
0xff, 0x25, 0, 0, 0, 0 /* jmp NOTIFY */ |
}; |
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); |
memcpy (dfn->code, temp, sizeof(temp)); |
FIXUP(dfn->code, 8, 0x01010101, (int)&tnl->dmaptr); |
FIXUP(dfn->code, 32, 0x00000006, tnl->vertex_size-3); |
FIXUP(dfn->code, 37, 0x00000058, (int)&tnl->vertex[3]); |
FIXUP(dfn->code, 45, 0x01010101, (int)&tnl->dmaptr); |
FIXUP(dfn->code, 50, 0x02020202, (int)&tnl->counter); |
FIXUP(dfn->code, 58, 0x02020202, (int)&tnl->counter); |
FIXUP(dfn->code, 67, 0x0, (int)&tnl->notify); |
break; |
} |
} |
insert_at_head( &tnl->dfn_cache.Vertex3fv, dfn ); |
dfn->key = key; |
return dfn; |
} |
struct dynfn *tnl_makeX86Attr4fv( TNLcontext *tnl, int key ) |
{ |
static char temp[] = { |
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ |
0xba, 0, 0, 0, 0, /* mov $DEST,%edx */ |
0x8b, 0x08, /* mov (%eax),%ecx */ |
0x89, 0x0a, /* mov %ecx,(%edx) */ |
0x8b, 0x48, 0x04, /* mov 0x4(%eax),%ecx */ |
0x89, 0x4a, 0x04, /* mov %ecx,0x4(%edx) */ |
0x8b, 0x48, 0x08, /* mov 0x8(%eax),%ecx */ |
0x89, 0x4a, 0x08, /* mov %ecx,0x8(%edx) */ |
0x8b, 0x48, 0x0a, /* mov 0xa(%eax),%ecx */ |
0x89, 0x4a, 0x0a, /* mov %ecx,0xa(%edx) */ |
0xc3, /* ret */ |
}; |
struct dynfn *dfn = MALLOC_STRUCT( dynfn ); |
if (TNL_DEBUG & DEBUG_CODEGEN) |
_mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key ); |
insert_at_head( &tnl->dfn_cache.Normal3fv, dfn ); |
dfn->key = key; |
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); |
memcpy (dfn->code, temp, sizeof(temp)); |
FIXUP(dfn->code, 5, 0x0, (int)tnl->normalptr); |
return dfn; |
} |
struct dynfn *tnl_makeX86Attr4f( TNLcontext *tnl, int key ) |
{ |
static char temp[] = { |
0xba, 0x78, 0x56, 0x34, 0x12, /* mov $DEST,%edx */ |
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ |
0x89, 0x02, /* mov %eax,(%edx) */ |
0x8b, 0x44, 0x24, 0x08, /* mov 0x8(%esp,1),%eax */ |
0x89, 0x42, 0x04, /* mov %eax,0x4(%edx) */ |
0x8b, 0x44, 0x24, 0x0c, /* mov 0xc(%esp,1),%eax */ |
0x89, 0x42, 0x08, /* mov %eax,0x8(%edx) */ |
0x8b, 0x44, 0x24, 0x10, /* mov 0x10(%esp,1),%eax */ |
0x89, 0x42, 0x0a, /* mov %eax,0xa(%edx) */ |
0xc3, /* ret */ |
}; |
struct dynfn *dfn = MALLOC_STRUCT( dynfn ); |
if (TNL_DEBUG & DEBUG_CODEGEN) |
_mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key ); |
insert_at_head( &tnl->dfn_cache.Normal3f, dfn ); |
dfn->key = key; |
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); |
memcpy (dfn->code, temp, sizeof(temp)); |
FIXUP(dfn->code, 1, 0x12345678, (int)tnl->normalptr); |
return dfn; |
} |
struct dynfn *tnl_makeX86Attr3fv( TNLcontext *tnl, int key ) |
{ |
static char temp[] = { |
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ |
0xba, 0, 0, 0, 0, /* mov $DEST,%edx */ |
0x8b, 0x08, /* mov (%eax),%ecx */ |
0x89, 0x0a, /* mov %ecx,(%edx) */ |
0x8b, 0x48, 0x04, /* mov 0x4(%eax),%ecx */ |
0x89, 0x4a, 0x04, /* mov %ecx,0x4(%edx) */ |
0x8b, 0x48, 0x08, /* mov 0x8(%eax),%ecx */ |
0x89, 0x4a, 0x08, /* mov %ecx,0x8(%edx) */ |
0xc3, /* ret */ |
}; |
struct dynfn *dfn = MALLOC_STRUCT( dynfn ); |
if (TNL_DEBUG & DEBUG_CODEGEN) |
_mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key ); |
insert_at_head( &tnl->dfn_cache.Normal3fv, dfn ); |
dfn->key = key; |
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); |
memcpy (dfn->code, temp, sizeof(temp)); |
FIXUP(dfn->code, 5, 0x0, (int)tnl->normalptr); |
return dfn; |
} |
struct dynfn *tnl_makeX86Attr3f( TNLcontext *tnl, int key ) |
{ |
static char temp[] = { |
0xba, 0x78, 0x56, 0x34, 0x12, /* mov $DEST,%edx */ |
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ |
0x89, 0x02, /* mov %eax,(%edx) */ |
0x8b, 0x44, 0x24, 0x08, /* mov 0x8(%esp,1),%eax */ |
0x89, 0x42, 0x04, /* mov %eax,0x4(%edx) */ |
0x8b, 0x44, 0x24, 0x0c, /* mov 0xc(%esp,1),%eax */ |
0x89, 0x42, 0x08, /* mov %eax,0x8(%edx) */ |
0xc3, /* ret */ |
}; |
struct dynfn *dfn = MALLOC_STRUCT( dynfn ); |
if (TNL_DEBUG & DEBUG_CODEGEN) |
_mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key ); |
insert_at_head( &tnl->dfn_cache.Normal3f, dfn ); |
dfn->key = key; |
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); |
memcpy (dfn->code, temp, sizeof(temp)); |
FIXUP(dfn->code, 1, 0x12345678, (int)tnl->normalptr); |
return dfn; |
} |
struct dynfn *tnl_makeX86Attr4ubv( TNLcontext *tnl, int key ) |
{ |
struct dynfn *dfn = MALLOC_STRUCT( dynfn ); |
insert_at_head( &tnl->dfn_cache.Color4ubv, dfn ); |
dfn->key = key; |
if (TNL_DEBUG & DEBUG_CODEGEN) |
_mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key ); |
if (key & TNL_CP_VC_FRMT_PKCOLOR) { |
static char temp[] = { |
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ |
0xba, 0x78, 0x56, 0x34, 0x12, /* mov $DEST,%edx */ |
0x8b, 0x00, /* mov (%eax),%eax */ |
0x89, 0x02, /* mov %eax,(%edx) */ |
0xc3, /* ret */ |
}; |
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); |
memcpy (dfn->code, temp, sizeof(temp)); |
FIXUP(dfn->code, 5, 0x12345678, (int)tnl->ubytecolorptr); |
return dfn; |
} |
else { |
static char temp[] = { |
0x53, /* push %ebx */ |
0xba, 0x00, 0x00, 0x00, 0x00, /* mov $0x0,%edx */ |
0x31, 0xc0, /* xor %eax,%eax */ |
0x31, 0xc9, /* xor %ecx,%ecx */ |
0x8b, 0x5c, 0x24, 0x08, /* mov 0x8(%esp,1), %ebx */ |
0x8b, 0x1b, /* mov (%ebx), %ebx */ |
0x88, 0xd8, /* mov %bl, %al */ |
0x88, 0xf9, /* mov %bh, %cl */ |
0x8b, 0x04, 0x82, /* mov (%edx,%eax,4),%eax */ |
0x8b, 0x0c, 0x8a, /* mov (%edx,%ecx,4),%ecx */ |
0xa3, 0xaf, 0xbe, 0xad, 0xde, /* mov %eax,0xdeadbeaf */ |
0x89, 0x0d, 0xaf, 0xbe, 0xad, 0xde, /* mov %ecx,0xdeadbeaf */ |
0x31, 0xc0, /* xor %eax,%eax */ |
0x31, 0xc9, /* xor %ecx,%ecx */ |
0xc1, 0xeb, 0x10, /* shr $0x10, %ebx */ |
0x88, 0xd8, /* mov %bl, %al */ |
0x88, 0xf9, /* mov %bh, %cl */ |
0x8b, 0x04, 0x82, /* mov (%edx,%eax,4),%eax */ |
0x8b, 0x0c, 0x8a, /* mov (%edx,%ecx,4),%ecx */ |
0xa3, 0xaf, 0xbe, 0xad, 0xde, /* mov %eax,0xdeadbeaf */ |
0x89, 0x0d, 0xaf, 0xbe, 0xad, 0xde, /* mov %ecx,0xdeadbeaf */ |
0x5b, /* pop %ebx */ |
0xc3, /* ret */ |
}; |
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); |
memcpy (dfn->code, temp, sizeof(temp)); |
FIXUP(dfn->code, 2, 0x00000000, (int)_mesa_ubyte_to_float_color_tab); |
FIXUP(dfn->code, 27, 0xdeadbeaf, (int)tnl->floatcolorptr); |
FIXUP(dfn->code, 33, 0xdeadbeaf, (int)tnl->floatcolorptr+4); |
FIXUP(dfn->code, 55, 0xdeadbeaf, (int)tnl->floatcolorptr+8); |
FIXUP(dfn->code, 61, 0xdeadbeaf, (int)tnl->floatcolorptr+12); |
return dfn; |
} |
} |
struct dynfn *tnl_makeX86Attr4ub( TNLcontext *tnl, int key ) |
{ |
if (TNL_DEBUG & DEBUG_CODEGEN) |
_mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key ); |
if (key & TNL_CP_VC_FRMT_PKCOLOR) { |
/* XXX push/pop */ |
static char temp[] = { |
0x53, /* push %ebx */ |
0x8b, 0x44, 0x24, 0x08, /* mov 0x8(%esp,1),%eax */ |
0x8b, 0x54, 0x24, 0x0c, /* mov 0xc(%esp,1),%edx */ |
0x8b, 0x4c, 0x24, 0x10, /* mov 0x10(%esp,1),%ecx */ |
0x8b, 0x5c, 0x24, 0x14, /* mov 0x14(%esp,1),%ebx */ |
0xa2, 0, 0, 0, 0, /* mov %al,DEST */ |
0x88, 0x15, 0, 0, 0, 0, /* mov %dl,DEST+1 */ |
0x88, 0x0d, 0, 0, 0, 0, /* mov %cl,DEST+2 */ |
0x88, 0x1d, 0, 0, 0, 0, /* mov %bl,DEST+3 */ |
0x5b, /* pop %ebx */ |
0xc3, /* ret */ |
}; |
struct dynfn *dfn = MALLOC_STRUCT( dynfn ); |
insert_at_head( &tnl->dfn_cache.Color4ub, dfn ); |
dfn->key = key; |
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); |
memcpy (dfn->code, temp, sizeof(temp)); |
FIXUP(dfn->code, 18, 0x0, (int)tnl->ubytecolorptr); |
FIXUP(dfn->code, 24, 0x0, (int)tnl->ubytecolorptr+1); |
FIXUP(dfn->code, 30, 0x0, (int)tnl->ubytecolorptr+2); |
FIXUP(dfn->code, 36, 0x0, (int)tnl->ubytecolorptr+3); |
return dfn; |
} |
else |
return 0; |
} |
struct dynfn *tnl_makeX86Attr2fv( TNLcontext *tnl, int key ) |
{ |
static char temp[] = { |
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ |
0xba, 0x78, 0x56, 0x34, 0x12, /* mov $DEST,%edx */ |
0x8b, 0x08, /* mov (%eax),%ecx */ |
0x8b, 0x40, 0x04, /* mov 0x4(%eax),%eax */ |
0x89, 0x0a, /* mov %ecx,(%edx) */ |
0x89, 0x42, 0x04, /* mov %eax,0x4(%edx) */ |
0xc3, /* ret */ |
}; |
struct dynfn *dfn = MALLOC_STRUCT( dynfn ); |
if (TNL_DEBUG & DEBUG_CODEGEN) |
_mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key ); |
insert_at_head( &tnl->dfn_cache.TexCoord2fv, dfn ); |
dfn->key = key; |
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); |
memcpy (dfn->code, temp, sizeof(temp)); |
FIXUP(dfn->code, 5, 0x12345678, (int)tnl->texcoordptr[0]); |
return dfn; |
} |
struct dynfn *tnl_makeX86Attr2f( TNLcontext *tnl, int key ) |
{ |
static char temp[] = { |
0xba, 0x78, 0x56, 0x34, 0x12, /* mov $DEST,%edx */ |
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ |
0x8b, 0x4c, 0x24, 0x08, /* mov 0x8(%esp,1),%ecx */ |
0x89, 0x02, /* mov %eax,(%edx) */ |
0x89, 0x4a, 0x04, /* mov %ecx,0x4(%edx) */ |
0xc3, /* ret */ |
}; |
struct dynfn *dfn = MALLOC_STRUCT( dynfn ); |
if (TNL_DEBUG & DEBUG_CODEGEN) |
_mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key ); |
insert_at_head( &tnl->dfn_cache.TexCoord2f, dfn ); |
dfn->key = key; |
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); |
memcpy (dfn->code, temp, sizeof(temp)); |
FIXUP(dfn->code, 1, 0x12345678, (int)tnl->texcoordptr[0]); |
return dfn; |
} |
struct dynfn *tnl_makeX86Attr1fv( TNLcontext *tnl, int key ) |
{ |
static char temp[] = { |
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ |
0xba, 0x78, 0x56, 0x34, 0x12, /* mov $DEST,%edx */ |
0x8b, 0x08, /* mov (%eax),%ecx */ |
0x89, 0x0a, /* mov %ecx,(%edx) */ |
0xc3, /* ret */ |
}; |
struct dynfn *dfn = MALLOC_STRUCT( dynfn ); |
if (TNL_DEBUG & DEBUG_CODEGEN) |
_mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key ); |
insert_at_head( &tnl->dfn_cache.TexCoord2fv, dfn ); |
dfn->key = key; |
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); |
memcpy (dfn->code, temp, sizeof(temp)); |
FIXUP(dfn->code, 5, 0x12345678, (int)tnl->texcoordptr[0]); |
return dfn; |
} |
struct dynfn *tnl_makeX86Attr1f( TNLcontext *tnl, int key ) |
{ |
static char temp[] = { |
0xba, 0x78, 0x56, 0x34, 0x12, /* mov $DEST,%edx */ |
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ |
0x89, 0x02, /* mov %eax,(%edx) */ |
0xc3, /* ret */ |
}; |
struct dynfn *dfn = MALLOC_STRUCT( dynfn ); |
if (TNL_DEBUG & DEBUG_CODEGEN) |
_mesa_debug(NULL, "%s 0x%08x\n", __FUNCTION__, key ); |
insert_at_head( &tnl->dfn_cache.TexCoord2f, dfn ); |
dfn->key = key; |
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); |
memcpy (dfn->code, temp, sizeof(temp)); |
FIXUP(dfn->code, 1, 0x12345678, (int)tnl->texcoordptr[0]); |
return dfn; |
} |
void _tnl_InitX86Codegen( struct dfn_generators *gen ) |
{ |
gen->Attr1f = tnl_makeX86Attr1f; |
gen->Attr1fv = tnl_makeX86Attr1fv; |
gen->Attr2f = tnl_makeX86Attr2f; |
gen->Attr2fv = tnl_makeX86Attr2fv; |
gen->Attr3f = tnl_makeX86Attr3f; |
gen->Attr3fv = tnl_makeX86Attr3fv; |
gen->Attr4f = tnl_makeX86Attr4f; |
gen->Attr4fv = tnl_makeX86Attr4fv; |
gen->Attr4ub = tnl_makeX86Attr4ub; |
gen->Attr4ubv = tnl_makeX86Attr4ubv; |
gen->Vertex3f = tnl_makeX86Vertex3f; |
gen->Vertex3fv = tnl_makeX86Vertex3fv; |
} |
#else |
void _tnl_InitX86Codegen( struct dfn_generators *gen ) |
{ |
(void) gen; |
} |
#endif |
/shark/trunk/ports/mesa/src/tnl/t_vtx_sse.c |
---|
0,0 → 1,91 |
/* $XFree86$ */ |
/************************************************************************** |
Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas. |
All Rights Reserved. |
Permission is hereby granted, free of charge, to any person obtaining a |
copy of this software and associated documentation files (the "Software"), |
to deal in the Software without restriction, including without limitation |
on the rights to use, copy, modify, merge, publish, distribute, sub |
license, and/or sell copies of the Software, and to permit persons to whom |
the Software is furnished to do so, subject to the following conditions: |
The above copyright notice and this permission notice (including the next |
paragraph) shall be included in all copies or substantial portions of the |
Software. |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, |
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
USE OR OTHER DEALINGS IN THE SOFTWARE. |
**************************************************************************/ |
/* |
* Authors: |
* Keith Whitwell <keith@tungstengraphics.com> |
*/ |
#include "imports.h" |
#include "simple_list.h" |
#include "t_vtx_api.h" |
#if defined(USE_SSE_ASM) |
/* Build specialized versions of the immediate calls on the fly for |
* the current state. ???P4 SSE2 versions??? |
*/ |
static struct dynfn *makeSSENormal3fv( struct _vb *vb, int key ) |
{ |
/* Requires P4 (sse2?) |
*/ |
static unsigned char temp[] = { |
0x8b, 0x44, 0x24, 0x04, /* mov 0x4(%esp,1),%eax */ |
0xba, 0x78, 0x56, 0x34, 0x12, /* mov $0x12345678,%edx */ |
0xf3, 0x0f, 0x7e, 0x00, /* movq (%eax),%xmm0 */ |
0x66, 0x0f, 0x6e, 0x48, 0x08, /* movd 0x8(%eax),%xmm1 */ |
0x66, 0x0f, 0xd6, 0x42, 0x0c, /* movq %xmm0,0xc(%edx) */ |
0x66, 0x0f, 0x7e, 0x4a, 0x14, /* movd %xmm1,0x14(%edx) */ |
0xc3, /* ret */ |
}; |
struct dynfn *dfn = MALLOC_STRUCT( dynfn ); |
insert_at_head( &vb->dfn_cache.Normal3fv, dfn ); |
dfn->key = key; |
dfn->code = ALIGN_MALLOC( sizeof(temp), 16 ); |
memcpy (dfn->code, temp, sizeof(temp)); |
FIXUP(dfn->code, 5, 0x0, (int)vb->normalptr); |
return dfn; |
} |
void _tnl_InitSSECodegen( struct dfn_generators *gen ) |
{ |
/* Need to: |
* - check kernel sse support |
* - check p4/sse2 |
*/ |
(void) makeSSENormal3fv; |
} |
#else |
void _tnl_InitSSECodegen( struct dfn_generators *gen ) |
{ |
(void) gen; |
} |
#endif |
/shark/trunk/ports/mesa/src/tnl/t_imm_alloc.c |
---|
0,0 → 1,124 |
/* $Id: t_imm_alloc.c,v 1.1 2003-02-28 11:48:06 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 "imports.h" |
#include "mtypes.h" |
#include "t_imm_alloc.h" |
static int id = 0; /* give each struct immediate a unique ID number */ |
static struct immediate *real_alloc_immediate( GLcontext *ctx ) |
{ |
struct immediate *IM = ALIGN_CALLOC_STRUCT( immediate, 32 ); |
if (!IM) |
return 0; |
/* memset(IM, 0, sizeof(*IM)); */ |
IM->id = id++; |
IM->ref_count = 0; |
IM->FlushElt = 0; |
IM->LastPrimitive = IMM_MAX_COPIED_VERTS; |
IM->Count = IMM_MAX_COPIED_VERTS; |
IM->Start = IMM_MAX_COPIED_VERTS; |
IM->Material = 0; |
IM->MaterialMask = 0; |
IM->MaxTextureUnits = ctx->Const.MaxTextureUnits; |
IM->TexSize = 0; |
IM->NormalLengthPtr = 0; |
IM->CopyTexSize = 0; |
IM->CopyStart = IM->Start; |
return IM; |
} |
static void real_free_immediate( struct immediate *IM ) |
{ |
static int freed = 0; |
if (IM->Material) { |
FREE( IM->Material ); |
FREE( IM->MaterialMask ); |
IM->Material = 0; |
IM->MaterialMask = 0; |
} |
if (IM->NormalLengthPtr) |
ALIGN_FREE( IM->NormalLengthPtr ); |
ALIGN_FREE( IM ); |
freed++; |
/* printf("outstanding %d\n", id - freed); */ |
} |
/* Cache a single allocated immediate struct. |
*/ |
struct immediate *_tnl_alloc_immediate( GLcontext *ctx ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct immediate *tmp = tnl->freed_immediate; |
if (tmp) { |
tnl->freed_immediate = 0; |
return tmp; |
} |
else |
return real_alloc_immediate( ctx ); |
} |
/* May be called after tnl is destroyed. |
*/ |
void _tnl_free_immediate( GLcontext *ctx, struct immediate *IM ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
ASSERT(IM->ref_count == 0); |
if (IM->NormalLengthPtr) { |
ALIGN_FREE(IM->NormalLengthPtr); |
IM->NormalLengthPtr = NULL; |
} |
if (!tnl) { |
real_free_immediate( IM ); |
} |
else { |
if (tnl->freed_immediate) |
real_free_immediate( tnl->freed_immediate ); |
tnl->freed_immediate = IM; |
} |
} |
/shark/trunk/ports/mesa/src/tnl/t_vb_rendertmp.h |
---|
0,0 → 1,445 |
/* $Id: t_vb_rendertmp.h,v 1.1 2003-02-28 11:48:08 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included |
* in all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
* |
* Authors: |
* Keith Whitwell <keith@tungstengraphics.com> |
*/ |
#ifndef POSTFIX |
#define POSTFIX |
#endif |
#ifndef INIT |
#define INIT(x) |
#endif |
#ifndef NEED_EDGEFLAG_SETUP |
#define NEED_EDGEFLAG_SETUP 0 |
#define EDGEFLAG_GET(a) 0 |
#define EDGEFLAG_SET(a,b) (void)b |
#endif |
#ifndef RESET_STIPPLE |
#define RESET_STIPPLE |
#endif |
#ifndef RESET_OCCLUSION |
#define RESET_OCCLUSION |
#endif |
#ifndef TEST_PRIM_END |
#define TEST_PRIM_END(flags) (flags & PRIM_END) |
#define TEST_PRIM_BEGIN(flags) (flags & PRIM_BEGIN) |
#define TEST_PRIM_PARITY(flags) (flags & PRIM_PARITY) |
#endif |
#ifndef ELT |
#define ELT(x) x |
#endif |
#ifndef RENDER_TAB_QUALIFIER |
#define RENDER_TAB_QUALIFIER static |
#endif |
static void TAG(render_points)( GLcontext *ctx, |
GLuint start, |
GLuint count, |
GLuint flags ) |
{ |
LOCAL_VARS; |
(void) flags; |
RESET_OCCLUSION; |
INIT(GL_POINTS); |
RENDER_POINTS( start, count ); |
POSTFIX; |
} |
static void TAG(render_lines)( GLcontext *ctx, |
GLuint start, |
GLuint count, |
GLuint flags ) |
{ |
GLuint j; |
LOCAL_VARS; |
(void) flags; |
RESET_OCCLUSION; |
INIT(GL_LINES); |
for (j=start+1; j<count; j+=2 ) { |
RESET_STIPPLE; |
RENDER_LINE( ELT(j-1), ELT(j) ); |
} |
POSTFIX; |
} |
static void TAG(render_line_strip)( GLcontext *ctx, |
GLuint start, |
GLuint count, |
GLuint flags ) |
{ |
GLuint j; |
LOCAL_VARS; |
(void) flags; |
RESET_OCCLUSION; |
INIT(GL_LINE_STRIP); |
if (TEST_PRIM_BEGIN(flags)) { |
RESET_STIPPLE; |
} |
for (j=start+1; j<count; j++ ) |
RENDER_LINE( ELT(j-1), ELT(j) ); |
POSTFIX; |
} |
static void TAG(render_line_loop)( GLcontext *ctx, |
GLuint start, |
GLuint count, |
GLuint flags ) |
{ |
GLuint i; |
LOCAL_VARS; |
(void) flags; |
RESET_OCCLUSION; |
INIT(GL_LINE_LOOP); |
if (start+1 < count) { |
if (TEST_PRIM_BEGIN(flags)) { |
RESET_STIPPLE; |
RENDER_LINE( ELT(start), ELT(start+1) ); |
} |
for ( i = start+2 ; i < count ; i++) { |
RENDER_LINE( ELT(i-1), ELT(i) ); |
} |
if ( TEST_PRIM_END(flags)) { |
RENDER_LINE( ELT(count-1), ELT(start) ); |
} |
} |
POSTFIX; |
} |
static void TAG(render_triangles)( GLcontext *ctx, |
GLuint start, |
GLuint count, |
GLuint flags ) |
{ |
GLuint j; |
LOCAL_VARS; |
(void) flags; |
INIT(GL_TRIANGLES); |
if (NEED_EDGEFLAG_SETUP) { |
for (j=start+2; j<count; j+=3) { |
/* Leave the edgeflags as supplied by the user. |
*/ |
RESET_STIPPLE; |
RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) ); |
} |
} else { |
for (j=start+2; j<count; j+=3) { |
RENDER_TRI( ELT(j-2), ELT(j-1), ELT(j) ); |
} |
} |
POSTFIX; |
} |
static void TAG(render_tri_strip)( GLcontext *ctx, |
GLuint start, |
GLuint count, |
GLuint flags ) |
{ |
GLuint j; |
GLuint parity = 0; |
LOCAL_VARS; |
if (TEST_PRIM_PARITY(flags)) |
parity = 1; |
INIT(GL_TRIANGLE_STRIP); |
if (NEED_EDGEFLAG_SETUP) { |
for (j=start+2;j<count;j++,parity^=1) { |
GLuint ej2 = ELT(j-2+parity); |
GLuint ej1 = ELT(j-1-parity); |
GLuint ej = ELT(j); |
GLboolean ef2 = EDGEFLAG_GET( ej2 ); |
GLboolean ef1 = EDGEFLAG_GET( ej1 ); |
GLboolean 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) { |
RENDER_TRI( ELT(j-2+parity), ELT(j-1-parity), ELT(j) ); |
} |
} |
POSTFIX; |
} |
static void TAG(render_tri_fan)( GLcontext *ctx, |
GLuint start, |
GLuint count, |
GLuint flags ) |
{ |
GLuint j; |
LOCAL_VARS; |
(void) flags; |
INIT(GL_TRIANGLE_FAN); |
if (NEED_EDGEFLAG_SETUP) { |
for (j=start+2;j<count;j++) { |
/* For trifans, all edges are boundary. |
*/ |
GLuint ejs = ELT(start); |
GLuint ej1 = ELT(j-1); |
GLuint ej = ELT(j); |
GLboolean efs = EDGEFLAG_GET( ejs ); |
GLboolean ef1 = EDGEFLAG_GET( ej1 ); |
GLboolean ef = EDGEFLAG_GET( ej ); |
if (TEST_PRIM_BEGIN(flags)) { |
RESET_STIPPLE; |
} |
EDGEFLAG_SET( ejs, GL_TRUE ); |
EDGEFLAG_SET( ej1, GL_TRUE ); |
EDGEFLAG_SET( ej, GL_TRUE ); |
RENDER_TRI( ejs, ej1, ej); |
EDGEFLAG_SET( ejs, efs ); |
EDGEFLAG_SET( ej1, ef1 ); |
EDGEFLAG_SET( ej, ef ); |
} |
} else { |
for (j=start+2;j<count;j++) { |
RENDER_TRI( ELT(start), ELT(j-1), ELT(j) ); |
} |
} |
POSTFIX; |
} |
static void TAG(render_poly)( GLcontext *ctx, |
GLuint start, |
GLuint count, |
GLuint flags ) |
{ |
GLuint j = start+2; |
LOCAL_VARS; |
(void) flags; |
INIT(GL_POLYGON); |
if (NEED_EDGEFLAG_SETUP) { |
GLboolean efstart = EDGEFLAG_GET( ELT(start) ); |
GLboolean efcount = EDGEFLAG_GET( ELT(count-1) ); |
/* If the primitive does not begin here, the first edge |
* is non-boundary. |
*/ |
if (!TEST_PRIM_BEGIN(flags)) |
EDGEFLAG_SET( ELT(start), GL_FALSE ); |
else { |
RESET_STIPPLE; |
} |
/* If the primitive does not end here, the final edge is |
* non-boundary. |
*/ |
if (!TEST_PRIM_END(flags)) |
EDGEFLAG_SET( ELT(count-1), GL_FALSE ); |
/* Draw the first triangles (possibly zero) |
*/ |
if (j+1<count) { |
GLboolean ef = EDGEFLAG_GET( ELT(j) ); |
EDGEFLAG_SET( ELT(j), GL_FALSE ); |
RENDER_TRI( ELT(j-1), ELT(j), ELT(start) ); |
EDGEFLAG_SET( ELT(j), ef ); |
j++; |
/* Don't render the first edge again: |
*/ |
EDGEFLAG_SET( ELT(start), GL_FALSE ); |
for (;j+1<count;j++) { |
GLboolean efj = EDGEFLAG_GET( ELT(j) ); |
EDGEFLAG_SET( ELT(j), GL_FALSE ); |
RENDER_TRI( ELT(j-1), ELT(j), ELT(start) ); |
EDGEFLAG_SET( ELT(j), efj ); |
} |
} |
/* Draw the last or only triangle |
*/ |
if (j < count) |
RENDER_TRI( ELT(j-1), ELT(j), ELT(start) ); |
/* Restore the first and last edgeflags: |
*/ |
EDGEFLAG_SET( ELT(count-1), efcount ); |
EDGEFLAG_SET( ELT(start), efstart ); |
} |
else { |
for (j=start+2;j<count;j++) { |
RENDER_TRI( ELT(j-1), ELT(j), ELT(start) ); |
} |
} |
POSTFIX; |
} |
static void TAG(render_quads)( GLcontext *ctx, |
GLuint start, |
GLuint count, |
GLuint flags ) |
{ |
GLuint j; |
LOCAL_VARS; |
(void) flags; |
INIT(GL_QUADS); |
if (NEED_EDGEFLAG_SETUP) { |
for (j=start+3; j<count; j+=4) { |
/* Use user-specified edgeflags for quads. |
*/ |
RESET_STIPPLE; |
RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) ); |
} |
} else { |
for (j=start+3; j<count; j+=4) { |
RENDER_QUAD( ELT(j-3), ELT(j-2), ELT(j-1), ELT(j) ); |
} |
} |
POSTFIX; |
} |
static void TAG(render_quad_strip)( GLcontext *ctx, |
GLuint start, |
GLuint count, |
GLuint flags ) |
{ |
GLuint j; |
LOCAL_VARS; |
(void) flags; |
INIT(GL_QUAD_STRIP); |
if (NEED_EDGEFLAG_SETUP) { |
for (j=start+3;j<count;j+=2) { |
/* All edges are boundary. Set edgeflags to 1, draw the |
* quad, and restore them to the original values. |
*/ |
GLboolean ef3 = EDGEFLAG_GET( ELT(j-3) ); |
GLboolean ef2 = EDGEFLAG_GET( ELT(j-2) ); |
GLboolean ef1 = EDGEFLAG_GET( ELT(j-1) ); |
GLboolean ef = EDGEFLAG_GET( ELT(j) ); |
if (TEST_PRIM_BEGIN(flags)) { |
RESET_STIPPLE; |
} |
EDGEFLAG_SET( ELT(j-3), GL_TRUE ); |
EDGEFLAG_SET( ELT(j-2), GL_TRUE ); |
EDGEFLAG_SET( ELT(j-1), GL_TRUE ); |
EDGEFLAG_SET( ELT(j), GL_TRUE ); |
RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) ); |
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) { |
RENDER_QUAD( ELT(j-1), ELT(j-3), ELT(j-2), ELT(j) ); |
} |
} |
POSTFIX; |
} |
static void TAG(render_noop)( GLcontext *ctx, |
GLuint start, |
GLuint count, |
GLuint flags ) |
{ |
(void)(ctx && start && count && flags); |
} |
RENDER_TAB_QUALIFIER void (*TAG(render_tab)[GL_POLYGON+2])(GLcontext *, |
GLuint, |
GLuint, |
GLuint) = |
{ |
TAG(render_points), |
TAG(render_lines), |
TAG(render_line_loop), |
TAG(render_line_strip), |
TAG(render_triangles), |
TAG(render_tri_strip), |
TAG(render_tri_fan), |
TAG(render_quads), |
TAG(render_quad_strip), |
TAG(render_poly), |
TAG(render_noop), |
}; |
#ifndef PRESERVE_VB_DEFS |
#undef RENDER_TRI |
#undef RENDER_QUAD |
#undef RENDER_LINE |
#undef RENDER_POINTS |
#undef LOCAL_VARS |
#undef INIT |
#undef POSTFIX |
#undef RESET_STIPPLE |
#undef DBG |
#undef ELT |
#undef RENDER_TAB_QUALIFIER |
#endif |
#ifndef PRESERVE_TAG |
#undef TAG |
#endif |
#undef PRESERVE_VB_DEFS |
#undef PRESERVE_TAG |
/shark/trunk/ports/mesa/src/tnl/t_imm_fixup.c |
---|
0,0 → 1,871 |
/* $Id: t_imm_fixup.c,v 1.1 2003-02-28 11:48:07 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 "context.h" |
#include "enums.h" |
#include "dlist.h" |
#include "colormac.h" |
#include "light.h" |
#include "macros.h" |
#include "imports.h" |
#include "mmath.h" |
#include "state.h" |
#include "mtypes.h" |
#include "math/m_matrix.h" |
#include "math/m_xform.h" |
#include "t_context.h" |
#include "t_imm_alloc.h" |
#include "t_imm_debug.h" |
#include "t_imm_elt.h" |
#include "t_imm_fixup.h" |
#include "t_imm_exec.h" |
#include "t_pipeline.h" |
static const GLuint increment[GL_POLYGON+2] = { 1,2,1,1,3,1,1,4,2,1,1 }; |
static const GLuint intro[GL_POLYGON+2] = { 0,0,2,2,0,2,2,0,2,2,0 }; |
void |
_tnl_fixup_4f( GLfloat data[][4], GLuint flag[], GLuint start, GLuint match ) |
{ |
GLuint i = start; |
for (;;) { |
if ((flag[++i] & match) == 0) { |
COPY_4FV(data[i], data[i-1]); |
if (flag[i] & VERT_BIT_END_VB) break; |
} |
} |
} |
void |
_tnl_fixup_3f( float data[][3], GLuint flag[], GLuint start, GLuint match ) |
{ |
GLuint i = start; |
for (;;) { |
if ((flag[++i] & match) == 0) { |
/* _mesa_debug(NULL, "_tnl_fixup_3f copy to %p values %f %f %f\n", */ |
/* data[i], */ |
/* data[i-1][0], */ |
/* data[i-1][1], */ |
/* data[i-1][2]); */ |
COPY_3V(data[i], data[i-1]); |
if (flag[i] & VERT_BIT_END_VB) break; |
} |
} |
} |
void |
_tnl_fixup_1ui( GLuint *data, GLuint flag[], GLuint start, GLuint match ) |
{ |
GLuint i = start; |
for (;;) { |
if ((flag[++i] & match) == 0) { |
data[i] = data[i-1]; |
if (flag[i] & VERT_BIT_END_VB) break; |
} |
} |
flag[i] |= match; |
} |
void |
_tnl_fixup_1f( GLfloat *data, GLuint flag[], GLuint start, GLuint match ) |
{ |
GLuint i = start; |
for (;;) { |
if ((flag[++i] & match) == 0) { |
data[i] = data[i-1]; |
if (flag[i] & VERT_BIT_END_VB) break; |
} |
} |
flag[i] |= match; |
} |
void |
_tnl_fixup_1ub( GLubyte *data, GLuint flag[], GLuint start, GLuint match ) |
{ |
GLuint i = start; |
for (;;) { |
if ((flag[++i] & match) == 0) { |
data[i] = data[i-1]; |
if (flag[i] & VERT_BIT_END_VB) break; |
} |
} |
flag[i] |= match; |
} |
static void |
fixup_first_4f( GLfloat data[][4], GLuint flag[], GLuint match, |
GLuint start, GLfloat *dflt ) |
{ |
GLuint i = start-1; |
match |= VERT_BIT_END_VB; |
while ((flag[++i]&match) == 0) |
COPY_4FV(data[i], dflt); |
} |
#if 0 |
static void |
fixup_first_3f( GLfloat data[][3], GLuint flag[], GLuint match, |
GLuint start, GLfloat *dflt ) |
{ |
GLuint i = start-1; |
match |= VERT_BIT_END_VB; |
/* _mesa_debug(NULL, "fixup_first_3f default: %f %f %f start: %d\n", */ |
/* dflt[0], dflt[1], dflt[2], start); */ |
while ((flag[++i]&match) == 0) |
COPY_3FV(data[i], dflt); |
} |
#endif |
static void |
fixup_first_1ui( GLuint data[], GLuint flag[], GLuint match, |
GLuint start, GLuint dflt ) |
{ |
GLuint i = start-1; |
match |= VERT_BIT_END_VB; |
while ((flag[++i]&match) == 0) |
data[i] = dflt; |
} |
#if 00 |
static void |
fixup_first_1f( GLfloat data[], GLuint flag[], GLuint match, |
GLuint start, GLfloat dflt ) |
{ |
GLuint i = start-1; |
match |= VERT_BIT_END_VB; |
while ((flag[++i]&match) == 0) |
data[i] = dflt; |
} |
#endif |
static void |
fixup_first_1ub( GLubyte data[], GLuint flag[], GLuint match, |
GLuint start, GLubyte dflt ) |
{ |
GLuint i = start-1; |
match |= VERT_BIT_END_VB; |
while ((flag[++i]&match) == 0) |
data[i] = dflt; |
} |
/* |
* Copy vertex attributes from the ctx->Current group into the immediate |
* struct at the given position according to copyMask. |
*/ |
static void copy_from_current( GLcontext *ctx, struct immediate *IM, |
GLuint pos, GLuint copyMask ) |
{ |
GLuint attrib, attribBit; |
if (MESA_VERBOSE&VERBOSE_IMMEDIATE) |
_tnl_print_vert_flags("copy from current", copyMask); |
#if 0 |
if (copyMask & VERT_BIT_NORMAL) { |
COPY_4V(IM->Attrib[VERT_ATTRIB_NORMAL][pos], |
ctx->Current.Attrib[VERT_ATTRIB_NORMAL]); |
} |
if (copyMask & VERT_BIT_COLOR0) { |
COPY_4FV( IM->Attrib[VERT_ATTRIB_COLOR0][pos], |
ctx->Current.Attrib[VERT_ATTRIB_COLOR0]); |
} |
if (copyMask & VERT_BIT_COLOR1) |
COPY_4FV( IM->Attrib[VERT_ATTRIB_COLOR1][pos], |
ctx->Current.Attrib[VERT_ATTRIB_COLOR1]); |
if (copyMask & VERT_BIT_FOG) |
IM->Attrib[VERT_ATTRIB_FOG][pos][0] = ctx->Current.Attrib[VERT_ATTRIB_FOG][0]; |
if (copyMask & VERT_BITS_TEX_ANY) { |
GLuint i; |
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) { |
if (copyMask & VERT_BIT_TEX(i)) |
COPY_4FV(IM->Attrib[VERT_ATTRIB_TEX0 + i][pos], |
ctx->Current.Attrib[VERT_ATTRIB_TEX0 + i]); |
} |
} |
#else |
for (attrib = 0, attribBit = 1; attrib < 16; attrib++, attribBit <<= 1) { |
if (copyMask & attribBit) { |
COPY_4FV( IM->Attrib[attrib][pos], ctx->Current.Attrib[attrib]); |
} |
} |
#endif |
if (copyMask & VERT_BIT_INDEX) |
IM->Index[pos] = ctx->Current.Index; |
if (copyMask & VERT_BIT_EDGEFLAG) |
IM->EdgeFlag[pos] = ctx->Current.EdgeFlag; |
} |
void _tnl_fixup_input( GLcontext *ctx, struct immediate *IM ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
GLuint start = IM->CopyStart; |
GLuint andflag = IM->CopyAndFlag; |
GLuint orflag = IM->CopyOrFlag | IM->Evaluated; |
GLuint fixup; |
IM->CopyTexSize = IM->TexSize; |
/* _mesa_debug(ctx, "Fixup input, Start: %u Count: %u LastData: %u\n", */ |
/* IM->Start, IM->Count, IM->LastData); */ |
/* _tnl_print_vert_flags("Orflag", orflag); */ |
/* _tnl_print_vert_flags("Andflag", andflag); */ |
fixup = ~andflag & VERT_BITS_FIXUP; |
if (!ctx->CompileFlag) |
fixup &= tnl->pipeline.inputs; |
if (!ctx->ExecuteFlag) |
fixup &= orflag; |
if ((orflag & (VERT_BIT_POS|VERT_BITS_EVAL_ANY)) == 0) |
fixup = 0; |
if (fixup) { |
GLuint copy = fixup & ~IM->Flag[start]; |
/* Equivalent to a lazy copy-from-current when setting up the |
* immediate. |
*/ |
if (ctx->ExecuteFlag && copy) |
copy_from_current( ctx, IM, start, copy ); |
if (MESA_VERBOSE&VERBOSE_IMMEDIATE) |
_tnl_print_vert_flags("fixup", fixup); |
/* XXX replace these conditionals with a loop over the 16 |
* vertex attributes. |
*/ |
if (fixup & VERT_BITS_TEX_ANY) { |
GLuint i; |
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) { |
if (fixup & VERT_BIT_TEX(i)) { |
if (orflag & VERT_BIT_TEX(i)) |
_tnl_fixup_4f( IM->Attrib[VERT_ATTRIB_TEX0 + i], IM->Flag, |
start, VERT_BIT_TEX(i) ); |
else |
fixup_first_4f( IM->Attrib[VERT_ATTRIB_TEX0 + i], IM->Flag, |
VERT_BIT_END_VB, start, |
IM->Attrib[VERT_ATTRIB_TEX0 + i][start]); |
} |
} |
} |
if (fixup & VERT_BIT_EDGEFLAG) { |
if (orflag & VERT_BIT_EDGEFLAG) |
_tnl_fixup_1ub( IM->EdgeFlag, IM->Flag, start, VERT_BIT_EDGEFLAG ); |
else |
fixup_first_1ub( IM->EdgeFlag, IM->Flag, VERT_BIT_END_VB, start, |
IM->EdgeFlag[start] ); |
} |
if (fixup & VERT_BIT_INDEX) { |
if (orflag & VERT_BIT_INDEX) |
_tnl_fixup_1ui( IM->Index, IM->Flag, start, VERT_BIT_INDEX ); |
else |
fixup_first_1ui( IM->Index, IM->Flag, VERT_BIT_END_VB, start, |
IM->Index[start] ); |
} |
if (fixup & VERT_BIT_COLOR0) { |
if (orflag & VERT_BIT_COLOR0) |
_tnl_fixup_4f( IM->Attrib[VERT_ATTRIB_COLOR0], IM->Flag, start, |
VERT_BIT_COLOR0 ); |
/* No need for else case as the drivers understand stride |
* zero here. (TODO - propogate this) |
*/ |
} |
if (fixup & VERT_BIT_COLOR1) { |
if (orflag & VERT_BIT_COLOR1) |
_tnl_fixup_4f( IM->Attrib[VERT_ATTRIB_COLOR1], IM->Flag, start, |
VERT_BIT_COLOR1 ); |
else |
fixup_first_4f( IM->Attrib[VERT_ATTRIB_COLOR1], IM->Flag, VERT_BIT_END_VB, start, |
IM->Attrib[VERT_ATTRIB_COLOR1][start] ); |
} |
if (fixup & VERT_BIT_FOG) { |
if (orflag & VERT_BIT_FOG) |
_tnl_fixup_4f( IM->Attrib[VERT_ATTRIB_FOG], IM->Flag, |
start, VERT_BIT_FOG ); |
else |
fixup_first_4f( IM->Attrib[VERT_ATTRIB_FOG], IM->Flag, VERT_BIT_END_VB, |
start, IM->Attrib[VERT_ATTRIB_FOG][start] ); |
} |
if (fixup & VERT_BIT_NORMAL) { |
if (orflag & VERT_BIT_NORMAL) |
_tnl_fixup_4f( IM->Attrib[VERT_ATTRIB_NORMAL], IM->Flag, start, |
VERT_BIT_NORMAL ); |
else |
fixup_first_4f( IM->Attrib[VERT_ATTRIB_NORMAL], IM->Flag, |
VERT_BIT_END_VB, start, |
IM->Attrib[VERT_ATTRIB_NORMAL][start] ); |
} |
} |
/* Prune possible half-filled slot. |
*/ |
IM->Flag[IM->LastData+1] &= ~VERT_BIT_END_VB; |
IM->Flag[IM->Count] |= VERT_BIT_END_VB; |
/* Materials: |
*/ |
if (IM->MaterialOrMask & ~IM->MaterialAndMask) { |
GLuint vulnerable = IM->MaterialOrMask; |
GLuint i = IM->Start; |
do { |
while (!(IM->Flag[i] & VERT_BIT_MATERIAL)) |
i++; |
vulnerable &= ~IM->MaterialMask[i]; |
_mesa_copy_material_pairs( IM->Material[i], |
ctx->Light.Material, |
vulnerable ); |
++i; |
} while (vulnerable); |
} |
} |
static void |
copy_material( struct immediate *next, |
struct immediate *prev, |
GLuint dst, GLuint src ) |
{ |
/* _mesa_debug(NULL, "%s\n", __FUNCTION__); */ |
if (next->Material == 0) { |
next->Material = (struct gl_material (*)[2]) |
MALLOC( sizeof(struct gl_material) * IMM_SIZE * 2 ); |
next->MaterialMask = (GLuint *) MALLOC( sizeof(GLuint) * IMM_SIZE ); |
} |
next->MaterialMask[dst] = prev->MaterialOrMask; |
MEMCPY(next->Material[dst], prev->Material[src], |
2 * sizeof(struct gl_material)); |
} |
static GLboolean is_fan_like[GL_POLYGON+1] = { |
GL_FALSE, |
GL_FALSE, |
GL_TRUE, /* line loop */ |
GL_FALSE, |
GL_FALSE, |
GL_FALSE, |
GL_TRUE, /* tri fan */ |
GL_FALSE, |
GL_FALSE, |
GL_TRUE /* polygon */ |
}; |
/* Copy the untransformed data from the shared vertices of a primitive |
* that wraps over two immediate structs. This is done prior to |
* set_immediate so that prev and next may point to the same |
* structure. In general it's difficult to avoid this copy on long |
* primitives. |
* |
* Have to be careful with the transitions between display list |
* replay, compile and normal execute modes. |
*/ |
void _tnl_copy_immediate_vertices( GLcontext *ctx, struct immediate *next ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct immediate *prev = tnl->ExecCopySource; |
struct vertex_arrays *inputs = &tnl->imm_inputs; |
GLuint count = tnl->ExecCopyCount; |
GLuint *elts = tnl->ExecCopyElts; |
GLuint offset = IMM_MAX_COPIED_VERTS - count; |
GLuint i; |
if (!prev) { |
ASSERT(tnl->ExecCopyCount == 0); |
return; |
} |
next->CopyStart = next->Start - count; |
if ((prev->CopyOrFlag & VERT_BITS_DATA) == VERT_BIT_ELT && |
ctx->Array.LockCount && |
ctx->Array.Vertex.Enabled) |
{ |
/* Copy Elt values only |
*/ |
for (i = 0 ; i < count ; i++) |
{ |
GLuint src = elts[i+offset]; |
GLuint dst = next->CopyStart+i; |
next->Elt[dst] = prev->Elt[src]; |
next->Flag[dst] = VERT_BIT_ELT; |
elts[i+offset] = dst; |
} |
/* _mesa_debug(ctx, "ADDING VERT_BIT_ELT!\n"); */ |
next->CopyOrFlag |= VERT_BIT_ELT; |
next->CopyAndFlag &= VERT_BIT_ELT; |
} |
else { |
GLuint copy = tnl->pipeline.inputs & (prev->CopyOrFlag|prev->Evaluated); |
GLuint flag; |
if (is_fan_like[ctx->Driver.CurrentExecPrimitive]) { |
flag = ((prev->CopyOrFlag|prev->Evaluated) & VERT_BITS_FIXUP); |
next->CopyOrFlag |= flag; |
} |
else { |
/* Don't let an early 'glColor', etc. poison the elt path. |
*/ |
flag = ((prev->OrFlag|prev->Evaluated) & VERT_BITS_FIXUP); |
} |
next->TexSize |= tnl->ExecCopyTexSize; |
next->CopyAndFlag &= flag; |
/* _tnl_print_vert_flags("copy vertex components", copy); */ |
/* _tnl_print_vert_flags("prev copyorflag", prev->CopyOrFlag); */ |
/* _tnl_print_vert_flags("flag", flag); */ |
/* Copy whole vertices |
*/ |
for (i = 0 ; i < count ; i++) |
{ |
GLuint src = elts[i+offset]; |
GLuint isrc = src - prev->CopyStart; |
GLuint dst = next->CopyStart+i; |
/* Values subject to eval must be copied out of the 'inputs' |
* struct. (Copied rows should not be evaluated twice). |
* |
* Note these pointers are null when inactive. |
*/ |
COPY_4FV( next->Attrib[VERT_ATTRIB_POS][dst], |
inputs->Obj.data[isrc] ); |
if (copy & VERT_BIT_NORMAL) { |
/* _mesa_debug(ctx, "copy vert norm %d to %d (%p): %f %f %f\n", */ |
/* isrc, dst, */ |
/* next->Normal[dst], */ |
/* inputs->Normal.data[isrc][0], */ |
/* inputs->Normal.data[isrc][1], */ |
/* inputs->Normal.data[isrc][2]); */ |
COPY_3FV( next->Attrib[VERT_ATTRIB_NORMAL][dst], inputs->Normal.data[isrc] ); |
} |
if (copy & VERT_BIT_COLOR0) |
COPY_4FV( next->Attrib[VERT_ATTRIB_COLOR0][dst], |
((GLfloat (*)[4])inputs->Color.Ptr)[isrc] ); |
if (copy & VERT_BIT_INDEX) |
next->Index[dst] = inputs->Index.data[isrc]; |
if (copy & VERT_BITS_TEX_ANY) { |
GLuint i; |
for (i = 0 ; i < prev->MaxTextureUnits ; i++) { |
if (copy & VERT_BIT_TEX(i)) |
COPY_4FV( next->Attrib[VERT_ATTRIB_TEX0 + i][dst], |
inputs->TexCoord[i].data[isrc] ); |
} |
} |
/* Remaining values should be the same in the 'input' struct and the |
* original immediate. |
*/ |
if (copy & (VERT_BIT_ELT|VERT_BIT_EDGEFLAG|VERT_BIT_COLOR1|VERT_BIT_FOG| |
VERT_BIT_MATERIAL)) { |
if (prev->Flag[src] & VERT_BIT_MATERIAL) |
copy_material(next, prev, dst, src); |
next->Elt[dst] = prev->Elt[src]; |
next->EdgeFlag[dst] = prev->EdgeFlag[src]; |
COPY_4FV( next->Attrib[VERT_ATTRIB_COLOR1][dst], |
prev->Attrib[VERT_ATTRIB_COLOR1][src] ); |
COPY_4FV( next->Attrib[VERT_ATTRIB_FOG][dst], |
prev->Attrib[VERT_ATTRIB_FOG][src] ); |
} |
next->Flag[dst] = flag; |
next->CopyOrFlag |= prev->Flag[src] & (VERT_BITS_FIXUP| |
VERT_BIT_MATERIAL| |
VERT_BIT_POS); |
elts[i+offset] = dst; |
} |
} |
if (--tnl->ExecCopySource->ref_count == 0) |
_tnl_free_immediate( ctx, tnl->ExecCopySource ); |
tnl->ExecCopySource = next; next->ref_count++; |
} |
/* Revive a compiled immediate struct - propogate new 'Current' |
* values. Often this is redundant because the current values were |
* known and fixed up at compile time (or in the first execution of |
* the cassette). |
*/ |
void _tnl_fixup_compiled_cassette( GLcontext *ctx, struct immediate *IM ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
GLuint fixup; |
GLuint start = IM->Start; |
/* _mesa_debug(ctx, "%s\n", __FUNCTION__); */ |
IM->Evaluated = 0; |
IM->CopyOrFlag = IM->OrFlag; |
IM->CopyAndFlag = IM->AndFlag; |
IM->CopyTexSize = IM->TexSize | tnl->ExecCopyTexSize; |
_tnl_copy_immediate_vertices( ctx, IM ); |
if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) { |
ASSERT(IM->CopyStart == IM->Start); |
} |
/* Naked array elements can be copied into the first cassette in a |
* display list. Need to translate them away: |
*/ |
if (IM->CopyOrFlag & VERT_BIT_ELT) { |
GLuint copy = tnl->pipeline.inputs & ~ctx->Array._Enabled; |
GLuint i; |
ASSERT(IM->CopyStart < IM->Start); |
_tnl_translate_array_elts( ctx, IM, IM->CopyStart, IM->Start ); |
for (i = IM->CopyStart ; i < IM->Start ; i++) |
copy_from_current( ctx, IM, i, copy ); |
_tnl_copy_to_current( ctx, IM, ctx->Array._Enabled, IM->Start ); |
} |
fixup = tnl->pipeline.inputs & ~IM->Flag[start] & VERT_BITS_FIXUP; |
/* _tnl_print_vert_flags("fixup compiled", fixup); */ |
if (fixup) { |
/* XXX try to replace this code with a loop over the 16 vertex |
* attributes. |
*/ |
if (fixup & VERT_BIT_NORMAL) { |
fixup_first_4f(IM->Attrib[VERT_ATTRIB_NORMAL], IM->Flag, |
VERT_BIT_NORMAL, start, |
ctx->Current.Attrib[VERT_ATTRIB_NORMAL] ); |
} |
if (fixup & VERT_BIT_COLOR0) { |
if (IM->CopyOrFlag & VERT_BIT_COLOR0) |
fixup_first_4f(IM->Attrib[VERT_ATTRIB_COLOR0], IM->Flag, |
VERT_BIT_COLOR0, start, |
ctx->Current.Attrib[VERT_ATTRIB_COLOR0] ); |
else |
fixup &= ~VERT_BIT_COLOR0; |
} |
if (fixup & VERT_BIT_COLOR1) |
fixup_first_4f(IM->Attrib[VERT_ATTRIB_COLOR1], IM->Flag, |
VERT_BIT_COLOR1, start, |
ctx->Current.Attrib[VERT_ATTRIB_COLOR1] ); |
if (fixup & VERT_BIT_FOG) |
fixup_first_4f( IM->Attrib[VERT_ATTRIB_FOG], IM->Flag, |
VERT_BIT_FOG, start, |
ctx->Current.Attrib[VERT_ATTRIB_FOG] ); |
if (fixup & VERT_BITS_TEX_ANY) { |
GLuint i; |
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) { |
if (fixup & VERT_BIT_TEX(i)) |
fixup_first_4f( IM->Attrib[VERT_ATTRIB_TEX0 + i], IM->Flag, |
VERT_BIT_TEX(i), start, |
ctx->Current.Attrib[VERT_ATTRIB_TEX0 + i] ); |
} |
} |
if (fixup & VERT_BIT_EDGEFLAG) |
fixup_first_1ub(IM->EdgeFlag, IM->Flag, VERT_BIT_EDGEFLAG, start, |
ctx->Current.EdgeFlag ); |
if (fixup & VERT_BIT_INDEX) |
fixup_first_1ui(IM->Index, IM->Flag, VERT_BIT_INDEX, start, |
ctx->Current.Index ); |
IM->CopyOrFlag |= fixup; |
} |
/* Materials: |
*/ |
if (IM->MaterialOrMask & ~IM->MaterialAndMask) { |
GLuint vulnerable = IM->MaterialOrMask; |
GLuint i = IM->Start; |
do { |
while (!(IM->Flag[i] & VERT_BIT_MATERIAL)) |
i++; |
vulnerable &= ~IM->MaterialMask[i]; |
_mesa_copy_material_pairs( IM->Material[i], |
ctx->Light.Material, |
vulnerable ); |
++i; |
} while (vulnerable); |
} |
} |
static void copy_none( TNLcontext *tnl, GLuint start, GLuint count, GLuint ovf) |
{ |
(void) (start && ovf && tnl && count); |
} |
static void copy_last( TNLcontext *tnl, GLuint start, GLuint count, GLuint ovf) |
{ |
(void) start; (void) ovf; |
tnl->ExecCopyCount = 1; |
tnl->ExecCopyElts[2] = count-1; |
} |
static void copy_first_and_last( TNLcontext *tnl, GLuint start, GLuint count, |
GLuint ovf) |
{ |
(void) ovf; |
tnl->ExecCopyCount = 2; |
tnl->ExecCopyElts[1] = start; |
tnl->ExecCopyElts[2] = count-1; |
} |
static void copy_last_two( TNLcontext *tnl, GLuint start, GLuint count, |
GLuint ovf ) |
{ |
(void) start; |
tnl->ExecCopyCount = 2+ovf; |
tnl->ExecCopyElts[0] = count-3; |
tnl->ExecCopyElts[1] = count-2; |
tnl->ExecCopyElts[2] = count-1; |
} |
static void copy_overflow( TNLcontext *tnl, GLuint start, GLuint count, |
GLuint ovf ) |
{ |
(void) start; |
tnl->ExecCopyCount = ovf; |
tnl->ExecCopyElts[0] = count-3; |
tnl->ExecCopyElts[1] = count-2; |
tnl->ExecCopyElts[2] = count-1; |
} |
typedef void (*copy_func)( TNLcontext *tnl, GLuint start, GLuint count, |
GLuint ovf ); |
static copy_func copy_tab[GL_POLYGON+2] = |
{ |
copy_none, |
copy_overflow, |
copy_first_and_last, |
copy_last, |
copy_overflow, |
copy_last_two, |
copy_first_and_last, |
copy_overflow, |
copy_last_two, |
copy_first_and_last, |
copy_none |
}; |
/* Figure out what vertices need to be copied next time. |
*/ |
void |
_tnl_get_exec_copy_verts( GLcontext *ctx, struct immediate *IM ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
GLuint last = IM->LastPrimitive; |
GLuint prim = ctx->Driver.CurrentExecPrimitive; |
GLuint pincr = increment[prim]; |
GLuint pintro = intro[prim]; |
GLuint ovf = 0; |
/* _mesa_debug(ctx, "_tnl_get_exec_copy_verts %s\n", */ |
/* _mesa_lookup_enum_by_nr(prim)); */ |
if (tnl->ExecCopySource) |
if (--tnl->ExecCopySource->ref_count == 0) |
_tnl_free_immediate( ctx, tnl->ExecCopySource ); |
if (prim == GL_POLYGON+1) { |
tnl->ExecCopySource = 0; |
tnl->ExecCopyCount = 0; |
tnl->ExecCopyTexSize = 0; |
tnl->ExecParity = 0; |
} else { |
/* Remember this immediate as the one to copy from. |
*/ |
tnl->ExecCopySource = IM; IM->ref_count++; |
tnl->ExecCopyCount = 0; |
tnl->ExecCopyTexSize = IM->CopyTexSize; |
if (IM->LastPrimitive != IM->CopyStart) |
tnl->ExecParity = 0; |
tnl->ExecParity ^= IM->PrimitiveLength[IM->LastPrimitive] & 1; |
if (pincr != 1 && (IM->Count - last - pintro)) |
ovf = (IM->Count - last - pintro) % pincr; |
if (last < IM->Count) |
copy_tab[prim]( tnl, last, IM->Count, ovf ); |
} |
} |
/* Recalculate ExecCopyElts, ExecParity, etc. |
*/ |
void |
_tnl_get_purged_copy_verts( GLcontext *ctx, struct immediate *IM ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
if (ctx->Driver.CurrentExecPrimitive != GL_POLYGON+1) { |
GLuint last = IM->LastPrimitive; |
GLenum prim = IM->Primitive[last]; |
GLuint pincr = increment[prim]; |
GLuint pintro = intro[prim]; |
GLuint ovf = 0, i; |
tnl->ExecCopyCount = 0; |
if (IM->LastPrimitive != IM->CopyStart) |
tnl->ExecParity = 0; |
tnl->ExecParity ^= IM->PrimitiveLength[IM->LastPrimitive] & 1; |
if (pincr != 1 && (IM->Count - last - pintro)) |
ovf = (IM->Count - last - pintro) % pincr; |
if (last < IM->Count) |
copy_tab[prim]( tnl, last, IM->Count, ovf ); |
for (i = 0 ; i < tnl->ExecCopyCount ; i++) |
tnl->ExecCopyElts[i] = IM->Elt[tnl->ExecCopyElts[i]]; |
} |
} |
void _tnl_upgrade_current_data( GLcontext *ctx, |
GLuint required, |
GLuint flags ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_buffer *VB = &tnl->vb; |
struct immediate *IM = (struct immediate *)VB->import_source; |
ASSERT(IM); |
/* _tnl_print_vert_flags("_tnl_upgrade_client_data", required); */ |
if ((required & VERT_BIT_COLOR0) && (VB->ColorPtr[0]->Flags & CA_CLIENT_DATA)) { |
struct gl_client_array *tmp = &tnl->imm_inputs.Color; |
GLuint start = IM->CopyStart; |
tmp->Ptr = IM->Attrib[VERT_ATTRIB_COLOR0] + start; |
tmp->StrideB = 4 * sizeof(GLfloat); |
tmp->Flags = 0; |
COPY_4FV( IM->Attrib[VERT_ATTRIB_COLOR0][start], |
ctx->Current.Attrib[VERT_ATTRIB_COLOR0]); |
/* |
ASSERT(IM->Flag[IM->LastData+1] & VERT_BIT_END_VB); |
*/ |
fixup_first_4f( IM->Attrib[VERT_ATTRIB_COLOR0], IM->Flag, |
VERT_BIT_END_VB, |
start, IM->Attrib[VERT_ATTRIB_COLOR0][start] ); |
VB->importable_data &= ~VERT_BIT_COLOR0; |
} |
} |
/shark/trunk/ports/mesa/src/tnl/t_imm_alloc.h |
---|
0,0 → 1,40 |
/* $Id: t_imm_alloc.h,v 1.1 2003-02-28 11:48:06 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 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. |
*/ |
#ifndef _T_IMM_ALLOC_H |
#define _T_IMM_ALLOC_H |
#include "mtypes.h" |
#include "t_context.h" |
extern struct immediate *_tnl_alloc_immediate( GLcontext *ctx ); |
extern void _tnl_free_immediate( GLcontext *ctx, struct immediate *im ); |
#endif |
/shark/trunk/ports/mesa/src/tnl/t_imm_fixup.h |
---|
0,0 → 1,64 |
/* $Id: t_imm_fixup.h,v 1.1 2003-02-28 11:48:07 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 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. |
*/ |
#ifndef _T_IMM_FIXUP_H |
#define _T_IMM_FIXUP_H |
#include "mtypes.h" |
#include "t_context.h" |
extern void _tnl_fixup_1ub( GLubyte *data, GLuint flag[], |
GLuint start, GLuint match ); |
extern void _tnl_fixup_1f( GLfloat *data, GLuint flag[], |
GLuint start, GLuint match ); |
extern void _tnl_fixup_1ui( GLuint *data, GLuint flag[], |
GLuint start, GLuint match ); |
extern void _tnl_fixup_3f( float data[][3], GLuint flag[], |
GLuint start, GLuint match ); |
extern void _tnl_fixup_4f( GLfloat data[][4], GLuint flag[], |
GLuint start, GLuint match ); |
extern void _tnl_fixup_input( GLcontext *ctx, struct immediate *IM ); |
extern void _tnl_fixup_compiled_cassette( GLcontext *ctx, |
struct immediate *IM ); |
extern void _tnl_copy_immediate_vertices( GLcontext *ctx, |
struct immediate *IM ); |
extern void _tnl_get_purged_copy_verts( GLcontext *ctx, struct immediate *IM ); |
extern void _tnl_get_exec_copy_verts( GLcontext *ctx, struct immediate *IM ); |
extern void _tnl_upgrade_current_data( GLcontext *ctx, GLuint required, |
GLuint flags ); |
#endif |
/shark/trunk/ports/mesa/src/tnl/t_vb_fog.c |
---|
0,0 → 1,254 |
/* $Id: t_vb_fog.c,v 1.1 2003-02-28 11:48:07 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 "mmath.h" |
#include "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 */ |
GLvector4f input; /* points into VB->EyePtr Z values */ |
}; |
#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 |
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] = (GLfloat) exp(-f); |
} |
inited = 1; |
} |
static void make_win_fog_coords( GLcontext *ctx, GLvector4f *out, |
const GLvector4f *in ) |
{ |
GLfloat end = ctx->Fog.End; |
GLfloat *v = in->start; |
GLuint stride = in->stride; |
GLuint n = in->count; |
GLfloat (*data)[4] = out->data; |
GLfloat d; |
GLuint i; |
out->count = in->count; |
switch (ctx->Fog.Mode) { |
case GL_LINEAR: |
if (ctx->Fog.Start == ctx->Fog.End) |
d = 1.0F; |
else |
d = 1.0F / (ctx->Fog.End - ctx->Fog.Start); |
for ( i = 0 ; i < n ; i++, STRIDE_F(v, stride)) { |
GLfloat f = (end - ABSF(*v)) * 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)) |
NEG_EXP( data[i][0], d * ABSF(*v) ); |
break; |
case GL_EXP2: |
d = ctx->Fog.Density*ctx->Fog.Density; |
for ( i = 0 ; i < n ; i++, STRIDE_F(v, stride)) { |
GLfloat z = *v; |
NEG_EXP( data[i][0], d * z * z ); |
} |
break; |
default: |
_mesa_problem(ctx, "Bad fog mode in make_fog_coord"); |
return; |
} |
} |
static GLboolean run_fog_stage( GLcontext *ctx, |
struct gl_pipeline_stage *stage ) |
{ |
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; |
struct fog_stage_data *store = FOG_STAGE_DATA(stage); |
GLvector4f *input; |
if (stage->changed_inputs == 0) |
return GL_TRUE; |
if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT) { |
/* fog computed from Z depth */ |
/* source = VB->ObjPtr or VB->EyePtr coords */ |
/* dest = VB->FogCoordPtr = fog stage private storage */ |
VB->FogCoordPtr = &store->fogcoord; |
if (!ctx->_NeedEyeCoords) { |
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->ObjPtr->size]( (GLfloat *) input->data, |
4 * sizeof(GLfloat), |
VB->ObjPtr, plane ); |
input->count = VB->ObjPtr->count; |
} |
else { |
input = &store->input; |
if (VB->EyePtr->size < 2) |
_mesa_vector4f_clean_elem( VB->EyePtr, VB->Count, 2 ); |
input->data = (GLfloat (*)[4]) &(VB->EyePtr->data[0][2]); |
input->start = VB->EyePtr->start+2; |
input->stride = VB->EyePtr->stride; |
input->count = VB->EyePtr->count; |
} |
} |
else { |
/* use glFogCoord() coordinates */ |
/* source = VB->FogCoordPtr */ |
input = VB->FogCoordPtr; |
/* dest = fog stage private storage */ |
VB->FogCoordPtr = &store->fogcoord; |
} |
make_win_fog_coords( ctx, VB->FogCoordPtr, input ); |
return GL_TRUE; |
} |
static void check_fog_stage( GLcontext *ctx, struct gl_pipeline_stage *stage ) |
{ |
stage->active = ctx->Fog.Enabled && !ctx->VertexProgram.Enabled; |
if (ctx->Fog.FogCoordinateSource == GL_FRAGMENT_DEPTH_EXT) |
stage->inputs = VERT_BIT_EYE; |
else |
stage->inputs = VERT_BIT_FOG; |
} |
/* Called the first time stage->run() is invoked. |
*/ |
static GLboolean alloc_fog_data( GLcontext *ctx, |
struct gl_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 ); |
_mesa_vector4f_init( &store->input, 0, 0 ); |
if (!inited) |
init_static_data(); |
/* Now run the stage. |
*/ |
stage->run = run_fog_stage; |
return stage->run( ctx, stage ); |
} |
static void free_fog_data( struct gl_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 gl_pipeline_stage _tnl_fog_coordinate_stage = |
{ |
"build fog coordinates", /* name */ |
_NEW_FOG, /* check_state */ |
_NEW_FOG, /* run_state */ |
GL_FALSE, /* active? */ |
0, /* inputs */ |
VERT_BIT_FOG, /* outputs */ |
0, /* changed_inputs */ |
NULL, /* private_data */ |
free_fog_data, /* dtr */ |
check_fog_stage, /* check */ |
alloc_fog_data /* run -- initially set to init. */ |
}; |
/shark/trunk/ports/mesa/src/tnl/t_vb_cliptmp.h |
---|
0,0 → 1,271 |
/* $Id: t_vb_cliptmp.h,v 1.1 2003-02-28 11:48:07 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included |
* in all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
* |
* Authors: |
* Keith Whitwell <keith@tungstengraphics.com> |
*/ |
#define CLIP_DOTPROD(K, A, B, C, D) X(K)*A + Y(K)*B + Z(K)*C + W(K)*D |
#define POLY_CLIP( PLANE, A, B, C, D ) \ |
do { \ |
if (mask & PLANE) { \ |
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 ); \ |
\ |
clipmask[idxPrev] |= PLANE; \ |
if (!NEGATIVE(dpPrev)) { \ |
outlist[outcount++] = idxPrev; \ |
clipmask[idxPrev] &= ~PLANE; \ |
} \ |
\ |
if (DIFFERENT_SIGNS(dp, dpPrev)) { \ |
GLuint newvert = VB->LastClipped++; \ |
VB->ClipMask[newvert] = 0; \ |
outlist[outcount++] = newvert; \ |
if (NEGATIVE(dp)) { \ |
/* Going out of bounds. Avoid division by zero as we \ |
* know dp != dpPrev from DIFFERENT_SIGNS, above. \ |
*/ \ |
GLfloat t = dp / (dp - dpPrev); \ |
INTERP_4F( t, coord[newvert], coord[idx], coord[idxPrev]); \ |
interp( ctx, t, newvert, idx, idxPrev, GL_TRUE ); \ |
} else { \ |
/* Coming back in. \ |
*/ \ |
GLfloat t = dpPrev / (dpPrev - dp); \ |
INTERP_4F( t, coord[newvert], coord[idxPrev], coord[idx]); \ |
interp( ctx, t, newvert, idxPrev, idx, GL_FALSE ); \ |
} \ |
} \ |
\ |
idxPrev = idx; \ |
dpPrev = dp; \ |
} \ |
\ |
if (outcount < 3) \ |
return; \ |
\ |
{ \ |
GLuint *tmp = inlist; \ |
inlist = outlist; \ |
outlist = tmp; \ |
n = outcount; \ |
} \ |
} \ |
} while (0) |
#define LINE_CLIP(PLANE, A, B, C, D ) \ |
do { \ |
if (mask & PLANE) { \ |
GLfloat dpI = CLIP_DOTPROD( ii, A, B, C, D ); \ |
GLfloat dpJ = CLIP_DOTPROD( jj, A, B, C, D ); \ |
\ |
if (DIFFERENT_SIGNS(dpI, dpJ)) { \ |
GLuint newvert = VB->LastClipped++; \ |
VB->ClipMask[newvert] = 0; \ |
if (NEGATIVE(dpJ)) { \ |
GLfloat t = dpI / (dpI - dpJ); \ |
VB->ClipMask[jj] |= PLANE; \ |
INTERP_4F( t, coord[newvert], coord[ii], coord[jj] ); \ |
interp( ctx, t, newvert, ii, jj, GL_FALSE ); \ |
jj = newvert; \ |
} else { \ |
GLfloat t = dpJ / (dpJ - dpI); \ |
VB->ClipMask[ii] |= PLANE; \ |
INTERP_4F( t, coord[newvert], coord[jj], coord[ii] ); \ |
interp( ctx, t, newvert, jj, ii, GL_FALSE ); \ |
ii = newvert; \ |
} \ |
} \ |
else if (NEGATIVE(dpI)) \ |
return; \ |
} \ |
} while (0) |
/* Clip a line against the viewport and user clip planes. |
*/ |
static INLINE void |
TAG(clip_line)( GLcontext *ctx, GLuint i, GLuint j, GLubyte mask ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_buffer *VB = &tnl->vb; |
interp_func interp = tnl->Driver.Render.Interp; |
GLfloat (*coord)[4] = VB->ClipPtr->data; |
GLuint ii = i, jj = j, p; |
VB->LastClipped = VB->FirstClipped; |
if (mask & 0x3f) { |
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<MAX_CLIP_PLANES;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 ((ctx->_TriangleCaps & DD_FLATSHADE) && j != jj) |
tnl->Driver.Render.CopyPV( ctx, jj, j ); |
tnl->Driver.Render.ClippedLine( ctx, ii, jj ); |
} |
/* Clip a triangle against the viewport and user clip planes. |
*/ |
static INLINE void |
TAG(clip_tri)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLubyte mask ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_buffer *VB = &tnl->vb; |
interp_func interp = tnl->Driver.Render.Interp; |
GLfloat (*coord)[4] = VB->ClipPtr->data; |
GLuint pv = v2; |
GLuint vlist[2][MAX_CLIPPED_VERTICES]; |
GLuint *inlist = vlist[0], *outlist = vlist[1]; |
GLuint p; |
GLubyte *clipmask = VB->ClipMask; |
GLuint n = 3; |
ASSIGN_3V(inlist, v2, v0, v1 ); /* pv rotated to slot zero */ |
VB->LastClipped = VB->FirstClipped; |
if (mask & 0x3f) { |
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<MAX_CLIP_PLANES;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->_TriangleCaps & DD_FLATSHADE) { |
if (pv != inlist[0]) { |
ASSERT( inlist[0] >= VB->FirstClipped ); |
tnl->Driver.Render.CopyPV( ctx, inlist[0], pv ); |
} |
} |
tnl->Driver.Render.ClippedPolygon( ctx, inlist, n ); |
} |
/* Clip a quad against the viewport and user clip planes. |
*/ |
static INLINE void |
TAG(clip_quad)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3, |
GLubyte mask ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_buffer *VB = &tnl->vb; |
interp_func interp = tnl->Driver.Render.Interp; |
GLfloat (*coord)[4] = VB->ClipPtr->data; |
GLuint pv = v3; |
GLuint vlist[2][MAX_CLIPPED_VERTICES]; |
GLuint *inlist = vlist[0], *outlist = vlist[1]; |
GLuint p; |
GLubyte *clipmask = VB->ClipMask; |
GLuint n = 4; |
ASSIGN_4V(inlist, v3, v0, v1, v2 ); /* pv rotated to slot zero */ |
VB->LastClipped = VB->FirstClipped; |
if (mask & 0x3f) { |
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<MAX_CLIP_PLANES;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->_TriangleCaps & DD_FLATSHADE) { |
if (pv != inlist[0]) { |
ASSERT( inlist[0] >= VB->FirstClipped ); |
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 |
/shark/trunk/ports/mesa/src/tnl/t_vb_render.c |
---|
0,0 → 1,425 |
/* $Id: t_vb_render.c,v 1.1 2003-02-28 11:48:07 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 4.0.1 |
* |
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included |
* in all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
* |
* Authors: |
* Keith Whitwell <keith@tungstengraphics.com> |
*/ |
/* |
* Render whole vertex buffers, including projection of vertices from |
* clip space and clipping of primitives. |
* |
* This file makes calls to project vertices and to the point, line |
* and triangle rasterizers via the function pointers: |
* |
* context->Driver.Render.* |
* |
*/ |
#include "glheader.h" |
#include "context.h" |
#include "enums.h" |
#include "macros.h" |
#include "imports.h" |
#include "mtypes.h" |
#include "mmath.h" |
#include "math/m_matrix.h" |
#include "math/m_xform.h" |
#include "t_pipeline.h" |
/**********************************************************************/ |
/* Clip single primitives */ |
/**********************************************************************/ |
#if defined(USE_IEEE) |
#define NEGATIVE(x) (GET_FLOAT_BITS(x) & (1<<31)) |
#define DIFFERENT_SIGNS(x,y) ((GET_FLOAT_BITS(x) ^ GET_FLOAT_BITS(y)) & (1<<31)) |
#else |
#define NEGATIVE(x) (x < 0) |
#define DIFFERENT_SIGNS(x,y) (x * y <= 0 && x - y != 0) |
/* Could just use (x*y<0) except for the flatshading requirements. |
* Maybe there's a better way? |
*/ |
#endif |
#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->_TriangleCaps & DD_TRI_UNFILLED) |
#define EDGEFLAG_GET(idx) VB->EdgeFlag[idx] |
#define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val |
/* 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 & 0x3f)) \ |
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 & 0x3f)) \ |
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 & 0x3f)) \ |
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 line_func LineFunc = tnl->Driver.Render.Line; \ |
const triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \ |
const 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 RESET_OCCLUSION ctx->OcclusionResult = GL_TRUE |
#define PRESERVE_VB_DEFS |
#include "t_vb_rendertmp.h" |
/* Elts, with the possibility of clipping. |
*/ |
#undef ELT |
#undef TAG |
#define ELT(x) elt[x] |
#define TAG(x) clip_##x##_elts |
#include "t_vb_rendertmp.h" |
/* TODO: do this for all primitives, verts and elts: |
*/ |
static void clip_elt_triangles( GLcontext *ctx, |
GLuint start, |
GLuint count, |
GLuint flags ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
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&0x3f)) |
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->_TriangleCaps & DD_TRI_UNFILLED) |
#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 line_func LineFunc = tnl->Driver.Render.Line; \ |
const triangle_func TriangleFunc = tnl->Driver.Render.Triangle; \ |
const 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 RESET_OCCLUSION ctx->OcclusionResult = GL_TRUE |
#define INIT(x) tnl->Driver.Render.PrimitiveNotify( ctx, x ) |
#define RENDER_TAB_QUALIFIER |
#define PRESERVE_VB_DEFS |
#include "t_vb_rendertmp.h" |
/* Elts, no clipping. |
*/ |
#undef ELT |
#define TAG(x) _tnl_##x##_elts |
#define ELT(x) elt[x] |
#include "t_vb_rendertmp.h" |
/**********************************************************************/ |
/* Helper functions for drivers */ |
/**********************************************************************/ |
void _tnl_RenderClippedPolygon( GLcontext *ctx, const GLuint *elts, GLuint n ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_buffer *VB = &tnl->vb; |
GLuint *tmp = VB->Elts; |
VB->Elts = (GLuint *)elts; |
tnl->Driver.Render.PrimTabElts[GL_POLYGON]( ctx, 0, n, PRIM_BEGIN|PRIM_END ); |
VB->Elts = tmp; |
} |
void _tnl_RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
tnl->Driver.Render.Line( ctx, ii, jj ); |
} |
/**********************************************************************/ |
/* Clip and render whole vertex buffers */ |
/**********************************************************************/ |
static GLboolean run_render( GLcontext *ctx, |
struct gl_pipeline_stage *stage ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_buffer *VB = &tnl->vb; |
GLuint new_inputs = stage->changed_inputs; |
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, new_inputs ); |
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, length, flags = 0; |
for (i = VB->FirstPrimitive ; !(flags & PRIM_LAST) ; i += length) |
{ |
flags = VB->Primitive[i]; |
length= VB->PrimitiveLength[i]; |
ASSERT(length || (flags & PRIM_LAST)); |
ASSERT((flags & PRIM_MODE_MASK) <= GL_POLYGON+1); |
if (MESA_VERBOSE & VERBOSE_PRIMS) |
_mesa_debug(NULL, "MESA prim %s %d..%d\n", |
_mesa_lookup_enum_by_nr(flags & PRIM_MODE_MASK), |
i, i+length); |
if (length) |
tab[flags & PRIM_MODE_MASK]( ctx, i, i + length, flags ); |
} |
} while (tnl->Driver.Render.Multipass && |
tnl->Driver.Render.Multipass( ctx, ++pass )); |
tnl->Driver.Render.Finish( ctx ); |
/* _swrast_flush(ctx); */ |
/* usleep(1000000); */ |
return GL_FALSE; /* finished the pipe */ |
} |
/**********************************************************************/ |
/* Render pipeline stage */ |
/**********************************************************************/ |
/* Quite a bit of work involved in finding out the inputs for the |
* render stage. |
*/ |
static void check_render( GLcontext *ctx, struct gl_pipeline_stage *stage ) |
{ |
GLuint inputs = VERT_BIT_CLIP; |
GLuint i; |
if (ctx->Visual.rgbMode) { |
inputs |= VERT_BIT_COLOR0; |
if (ctx->_TriangleCaps & DD_SEPARATE_SPECULAR) |
inputs |= VERT_BIT_COLOR1; |
if (ctx->Texture._EnabledUnits) { |
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) { |
if (ctx->Texture.Unit[i]._ReallyEnabled) |
inputs |= VERT_BIT_TEX(i); |
} |
} |
} |
else { |
inputs |= VERT_BIT_INDEX; |
} |
if (ctx->Point._Attenuated) |
inputs |= VERT_BIT_POINT_SIZE; |
/* How do drivers turn this off? |
*/ |
if (ctx->Fog.Enabled) |
inputs |= VERT_BIT_FOG; |
if (ctx->_TriangleCaps & DD_TRI_UNFILLED) |
inputs |= VERT_BIT_EDGEFLAG; |
if (ctx->RenderMode==GL_FEEDBACK) |
inputs |= VERT_BITS_TEX_ANY; |
stage->inputs = inputs; |
} |
static void dtr( struct gl_pipeline_stage *stage ) |
{ |
} |
const struct gl_pipeline_stage _tnl_render_stage = |
{ |
"render", /* name */ |
(_NEW_BUFFERS | |
_DD_NEW_SEPARATE_SPECULAR | |
_DD_NEW_FLATSHADE | |
_NEW_TEXTURE| |
_NEW_LIGHT| |
_NEW_POINT| |
_NEW_FOG| |
_DD_NEW_TRI_UNFILLED | |
_NEW_RENDERMODE), /* re-check (new inputs, interp function) */ |
0, /* re-run (always runs) */ |
GL_TRUE, /* active? */ |
0, /* inputs (set in check_render) */ |
0, /* outputs */ |
0, /* changed_inputs */ |
NULL, /* private data */ |
dtr, /* destructor */ |
check_render, /* check */ |
run_render /* run */ |
}; |
/shark/trunk/ports/mesa/src/tnl/t_array_import.c |
---|
0,0 → 1,432 |
/* $Id: t_array_import.c,v 1.1 2003-02-28 11:48:06 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 "context.h" |
#include "macros.h" |
#include "imports.h" |
#include "mmath.h" |
#include "state.h" |
#include "mtypes.h" |
#include "array_cache/acache.h" |
#include "math/m_translate.h" |
#include "t_array_import.h" |
#include "t_context.h" |
#include "t_imm_debug.h" |
static void _tnl_import_vertex( GLcontext *ctx, |
GLboolean writeable, |
GLboolean stride ) |
{ |
struct gl_client_array *tmp; |
GLboolean is_writeable = 0; |
struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; |
tmp = _ac_import_vertex(ctx, |
GL_FLOAT, |
stride ? 4*sizeof(GLfloat) : 0, |
0, |
writeable, |
&is_writeable); |
inputs->Obj.data = (GLfloat (*)[4]) tmp->Ptr; |
inputs->Obj.start = (GLfloat *) tmp->Ptr; |
inputs->Obj.stride = tmp->StrideB; |
inputs->Obj.size = tmp->Size; |
inputs->Obj.flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE); |
if (inputs->Obj.stride != 4*sizeof(GLfloat)) |
inputs->Obj.flags |= VEC_BAD_STRIDE; |
if (!is_writeable) |
inputs->Obj.flags |= VEC_NOT_WRITEABLE; |
} |
static void _tnl_import_normal( GLcontext *ctx, |
GLboolean writeable, |
GLboolean stride ) |
{ |
struct gl_client_array *tmp; |
GLboolean is_writeable = 0; |
struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; |
tmp = _ac_import_normal(ctx, GL_FLOAT, |
stride ? 3*sizeof(GLfloat) : 0, writeable, |
&is_writeable); |
inputs->Normal.data = (GLfloat (*)[4]) tmp->Ptr; |
inputs->Normal.start = (GLfloat *) tmp->Ptr; |
inputs->Normal.stride = tmp->StrideB; |
inputs->Normal.flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE); |
if (inputs->Normal.stride != 3*sizeof(GLfloat)) |
inputs->Normal.flags |= VEC_BAD_STRIDE; |
if (!is_writeable) |
inputs->Normal.flags |= VEC_NOT_WRITEABLE; |
} |
static void _tnl_import_color( GLcontext *ctx, |
GLenum type, |
GLboolean writeable, |
GLboolean stride ) |
{ |
struct gl_client_array *tmp; |
GLboolean is_writeable = 0; |
struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; |
tmp = _ac_import_color(ctx, |
type, |
stride ? 4*sizeof(GLfloat) : 0, |
4, |
writeable, |
&is_writeable); |
inputs->Color = *tmp; |
} |
static void _tnl_import_secondarycolor( GLcontext *ctx, |
GLenum type, |
GLboolean writeable, |
GLboolean stride ) |
{ |
struct gl_client_array *tmp; |
GLboolean is_writeable = 0; |
struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; |
tmp = _ac_import_secondarycolor(ctx, |
type, |
stride ? 4*sizeof(GLfloat) : 0, |
4, |
writeable, |
&is_writeable); |
inputs->SecondaryColor = *tmp; |
} |
static void _tnl_import_fogcoord( GLcontext *ctx, |
GLboolean writeable, |
GLboolean stride ) |
{ |
struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; |
struct gl_client_array *tmp; |
GLboolean is_writeable = 0; |
tmp = _ac_import_fogcoord(ctx, GL_FLOAT, |
stride ? sizeof(GLfloat) : 0, writeable, |
&is_writeable); |
inputs->FogCoord.data = (GLfloat (*)[4]) tmp->Ptr; |
inputs->FogCoord.start = (GLfloat *) tmp->Ptr; |
inputs->FogCoord.stride = tmp->StrideB; |
inputs->FogCoord.flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE); |
if (inputs->FogCoord.stride != sizeof(GLfloat)) |
inputs->FogCoord.flags |= VEC_BAD_STRIDE; |
if (!is_writeable) |
inputs->FogCoord.flags |= VEC_NOT_WRITEABLE; |
} |
static void _tnl_import_index( GLcontext *ctx, |
GLboolean writeable, |
GLboolean stride ) |
{ |
struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; |
struct gl_client_array *tmp; |
GLboolean is_writeable = 0; |
tmp = _ac_import_index(ctx, GL_UNSIGNED_INT, |
stride ? sizeof(GLuint) : 0, writeable, |
&is_writeable); |
inputs->Index.data = (GLuint *) tmp->Ptr; |
inputs->Index.start = (GLuint *) tmp->Ptr; |
inputs->Index.stride = tmp->StrideB; |
inputs->Index.flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE); |
if (inputs->Index.stride != sizeof(GLuint)) |
inputs->Index.flags |= VEC_BAD_STRIDE; |
if (!is_writeable) |
inputs->Index.flags |= VEC_NOT_WRITEABLE; |
} |
static void _tnl_import_texcoord( GLcontext *ctx, |
GLuint unit, |
GLboolean writeable, |
GLboolean stride ) |
{ |
struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; |
struct gl_client_array *tmp; |
GLboolean is_writeable = 0; |
tmp = _ac_import_texcoord(ctx, unit, GL_FLOAT, |
stride ? 4 * sizeof(GLfloat) : 0, |
0, |
writeable, |
&is_writeable); |
inputs->TexCoord[unit].data = (GLfloat (*)[4]) tmp->Ptr; |
inputs->TexCoord[unit].start = (GLfloat *) tmp->Ptr; |
inputs->TexCoord[unit].stride = tmp->StrideB; |
inputs->TexCoord[unit].size = tmp->Size; |
inputs->TexCoord[unit].flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE); |
if (inputs->TexCoord[unit].stride != 4*sizeof(GLfloat)) |
inputs->TexCoord[unit].flags |= VEC_BAD_STRIDE; |
if (!is_writeable) |
inputs->TexCoord[unit].flags |= VEC_NOT_WRITEABLE; |
} |
static void _tnl_import_edgeflag( GLcontext *ctx, |
GLboolean writeable, |
GLboolean stride ) |
{ |
struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; |
struct gl_client_array *tmp; |
GLboolean is_writeable = 0; |
tmp = _ac_import_edgeflag(ctx, GL_UNSIGNED_BYTE, |
stride ? sizeof(GLubyte) : 0, |
0, |
&is_writeable); |
inputs->EdgeFlag.data = (GLubyte *) tmp->Ptr; |
inputs->EdgeFlag.start = (GLubyte *) tmp->Ptr; |
inputs->EdgeFlag.stride = tmp->StrideB; |
inputs->EdgeFlag.flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE); |
if (inputs->EdgeFlag.stride != sizeof(GLubyte)) |
inputs->EdgeFlag.flags |= VEC_BAD_STRIDE; |
if (!is_writeable) |
inputs->EdgeFlag.flags |= VEC_NOT_WRITEABLE; |
} |
static void _tnl_import_attrib( GLcontext *ctx, |
GLuint index, |
GLboolean writeable, |
GLboolean stride ) |
{ |
struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; |
struct gl_client_array *tmp; |
GLboolean is_writeable = 0; |
tmp = _ac_import_attrib(ctx, index, GL_FLOAT, |
stride ? 4 * sizeof(GLfloat) : 0, |
4, /* want GLfloat[4] */ |
writeable, |
&is_writeable); |
inputs->Attribs[index].data = (GLfloat (*)[4]) tmp->Ptr; |
inputs->Attribs[index].start = (GLfloat *) tmp->Ptr; |
inputs->Attribs[index].stride = tmp->StrideB; |
inputs->Attribs[index].size = tmp->Size; |
inputs->Attribs[index].flags &= ~(VEC_BAD_STRIDE|VEC_NOT_WRITEABLE); |
if (inputs->Attribs[index].stride != 4 * sizeof(GLfloat)) |
inputs->Attribs[index].flags |= VEC_BAD_STRIDE; |
if (!is_writeable) |
inputs->Attribs[index].flags |= VEC_NOT_WRITEABLE; |
} |
/** |
* Callback for VB stages that need to improve the quality of arrays |
* bound to the VB. This is only necessary for client arrays which |
* have not been transformed at any point in the pipeline. |
* \param required - bitmask of VERT_*_BIT flags |
* \param flags - bitmask of VEC_* flags (ex: VEC_NOT_WRITABLE) |
*/ |
static void _tnl_upgrade_client_data( GLcontext *ctx, |
GLuint required, |
GLuint flags ) |
{ |
GLuint i; |
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; |
GLboolean writeable = (flags & VEC_NOT_WRITEABLE) != 0; |
GLboolean stride = (flags & VEC_BAD_STRIDE) != 0; |
struct vertex_arrays *inputs = &TNL_CONTEXT(ctx)->array_inputs; |
GLuint ca_flags = 0; |
(void) inputs; |
if (writeable || stride) ca_flags |= CA_CLIENT_DATA; |
if ((required & VERT_BIT_CLIP) && VB->ClipPtr == VB->ObjPtr) |
required |= VERT_BIT_POS; |
/* _tnl_print_vert_flags("_tnl_upgrade_client_data", required); */ |
if ((required & VERT_BIT_POS) && (VB->ObjPtr->flags & flags)) { |
ASSERT(VB->ObjPtr == &inputs->Obj); |
_tnl_import_vertex( ctx, writeable, stride ); |
VB->importable_data &= ~(VERT_BIT_POS|VERT_BIT_CLIP); |
} |
if ((required & VERT_BIT_NORMAL) && (VB->NormalPtr->flags & flags)) { |
ASSERT(VB->NormalPtr == &inputs->Normal); |
_tnl_import_normal( ctx, writeable, stride ); |
VB->importable_data &= ~VERT_BIT_NORMAL; |
} |
if ((required & VERT_BIT_COLOR0) && (VB->ColorPtr[0]->Flags & ca_flags)) { |
ASSERT(VB->ColorPtr[0] == &inputs->Color); |
_tnl_import_color( ctx, GL_FLOAT, writeable, stride ); |
VB->importable_data &= ~VERT_BIT_COLOR0; |
} |
if ((required & VERT_BIT_COLOR1) && |
(VB->SecondaryColorPtr[0]->Flags & ca_flags)) { |
ASSERT(VB->SecondaryColorPtr[0] == &inputs->SecondaryColor); |
_tnl_import_secondarycolor( ctx, GL_FLOAT, writeable, stride ); |
VB->importable_data &= ~VERT_BIT_COLOR1; |
} |
if ((required & VERT_BIT_FOG) |
&& (VB->FogCoordPtr->flags & flags)) { |
ASSERT(VB->FogCoordPtr == &inputs->FogCoord); |
_tnl_import_fogcoord( ctx, writeable, stride ); |
VB->importable_data &= ~VERT_BIT_FOG; |
} |
if ((required & VERT_BIT_INDEX) && (VB->IndexPtr[0]->flags & flags)) { |
ASSERT(VB->IndexPtr[0] == &inputs->Index); |
_tnl_import_index( ctx, writeable, stride ); |
VB->importable_data &= ~VERT_BIT_INDEX; |
} |
if (required & VERT_BITS_TEX_ANY) |
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) |
if ((required & VERT_BIT_TEX(i)) && (VB->TexCoordPtr[i]->flags & flags)) { |
ASSERT(VB->TexCoordPtr[i] == &inputs->TexCoord[i]); |
_tnl_import_texcoord( ctx, i, writeable, stride ); |
VB->importable_data &= ~VERT_BIT_TEX(i); |
} |
/* XXX not sure what to do here for vertex program arrays */ |
} |
void _tnl_vb_bind_arrays( GLcontext *ctx, GLint start, GLsizei count ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_buffer *VB = &tnl->vb; |
GLuint inputs = tnl->pipeline.inputs; |
struct vertex_arrays *tmp = &tnl->array_inputs; |
/* _mesa_debug(ctx, "%s %d..%d // %d..%d\n", __FUNCTION__, */ |
/* start, count, ctx->Array.LockFirst, ctx->Array.LockCount); */ |
/* _tnl_print_vert_flags(" inputs", inputs); */ |
/* _tnl_print_vert_flags(" _Enabled", ctx->Array._Enabled); */ |
/* _tnl_print_vert_flags(" importable", inputs & VERT_BITS_FIXUP); */ |
VB->Count = count - start; |
VB->FirstClipped = VB->Count; |
VB->Elts = NULL; |
VB->MaterialMask = NULL; |
VB->Material = NULL; |
VB->Flag = NULL; |
VB->Primitive = tnl->tmp_primitive; |
VB->PrimitiveLength = tnl->tmp_primitive_length; |
VB->import_data = _tnl_upgrade_client_data; |
VB->importable_data = inputs & VERT_BITS_FIXUP; |
if (ctx->Array.LockCount) { |
ASSERT(start == (GLint) ctx->Array.LockFirst); |
ASSERT(count == (GLint) ctx->Array.LockCount); |
} |
_ac_import_range( ctx, start, count ); |
if (inputs & VERT_BIT_POS) { |
_tnl_import_vertex( ctx, 0, 0 ); |
tmp->Obj.count = VB->Count; |
VB->ObjPtr = &tmp->Obj; |
} |
if (inputs & VERT_BIT_NORMAL) { |
_tnl_import_normal( ctx, 0, 0 ); |
tmp->Normal.count = VB->Count; |
VB->NormalPtr = &tmp->Normal; |
} |
if (inputs & VERT_BIT_COLOR0) { |
_tnl_import_color( ctx, 0, 0, 0 ); |
VB->ColorPtr[0] = &tmp->Color; |
VB->ColorPtr[1] = 0; |
} |
if (inputs & VERT_BITS_TEX_ANY) { |
GLuint unit; |
for (unit = 0; unit < ctx->Const.MaxTextureUnits; unit++) { |
if (inputs & VERT_BIT_TEX(unit)) { |
_tnl_import_texcoord( ctx, unit, GL_FALSE, GL_FALSE ); |
tmp->TexCoord[unit].count = VB->Count; |
VB->TexCoordPtr[unit] = &tmp->TexCoord[unit]; |
} |
} |
} |
if (inputs & (VERT_BIT_INDEX | VERT_BIT_FOG | |
VERT_BIT_EDGEFLAG | VERT_BIT_COLOR1)) { |
if (inputs & VERT_BIT_INDEX) { |
_tnl_import_index( ctx, 0, 0 ); |
tmp->Index.count = VB->Count; |
VB->IndexPtr[0] = &tmp->Index; |
VB->IndexPtr[1] = 0; |
} |
if (inputs & VERT_BIT_FOG) { |
_tnl_import_fogcoord( ctx, 0, 0 ); |
tmp->FogCoord.count = VB->Count; |
VB->FogCoordPtr = &tmp->FogCoord; |
} |
if (inputs & VERT_BIT_EDGEFLAG) { |
_tnl_import_edgeflag( ctx, GL_TRUE, sizeof(GLboolean) ); |
VB->EdgeFlag = (GLboolean *) tmp->EdgeFlag.data; |
} |
if (inputs & VERT_BIT_COLOR1) { |
_tnl_import_secondarycolor( ctx, 0, 0, 0 ); |
VB->SecondaryColorPtr[0] = &tmp->SecondaryColor; |
VB->SecondaryColorPtr[1] = 0; |
} |
} |
/* XXX not 100% sure this is finished. Keith should probably inspect. */ |
if (ctx->VertexProgram.Enabled) { |
GLuint index; |
for (index = 0; index < VERT_ATTRIB_MAX; index++) { |
/* XXX check program->InputsRead to reduce work here */ |
_tnl_import_attrib( ctx, index, GL_FALSE, GL_TRUE ); |
VB->AttribPtr[index] = &tmp->Attribs[index]; |
} |
} |
} |
/shark/trunk/ports/mesa/src/tnl/t_vtx_api.c |
---|
0,0 → 1,808 |
/* $XFree86$ */ |
/************************************************************************** |
Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas. |
All Rights Reserved. |
Permission is hereby granted, free of charge, to any person obtaining a |
copy of this software and associated documentation files (the "Software"), |
to deal in the Software without restriction, including without limitation |
on the rights to use, copy, modify, merge, publish, distribute, sub |
license, and/or sell copies of the Software, and to permit persons to whom |
the Software is furnished to do so, subject to the following conditions: |
The above copyright notice and this permission notice (including the next |
paragraph) shall be included in all copies or substantial portions of the |
Software. |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, |
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
USE OR OTHER DEALINGS IN THE SOFTWARE. |
**************************************************************************/ |
/* |
* Authors: |
* Keith Whitwell <keith@tungstengraphics.com> |
*/ |
#include "mtypes.h" |
#include "colormac.h" |
#include "simple_list.h" |
#include "vtxfmt.h" |
#include "tnl_vtx_api.h" |
/* Fallback versions of all the entrypoints for situations where |
* codegen isn't available. This is slowed significantly by all the |
* gumph necessary to get to the tnl pointer. |
*/ |
/* MultiTexcoord ends up with both of these branches, unfortunately |
* (it may get its own version of the macro after size-tracking is |
* working). |
* |
* Errors (VertexAttribNV when ATTR>15) are handled at a higher level. |
*/ |
#define ATTRF( ATTR, N, A, B, C, D ) \ |
{ \ |
GET_CURRENT_CONTEXT( ctx ); \ |
TNLcontext *tnl = TNL_CONTEXT(ctx); \ |
\ |
if ((ATTR) == 0) { \ |
int i; \ |
\ |
if (N>0) tnl->vbptr[0].f = A; \ |
if (N>1) tnl->vbptr[1].f = B; \ |
if (N>2) tnl->vbptr[2].f = C; \ |
if (N>3) tnl->vbptr[3].f = D; \ |
\ |
for (i = N; i < tnl->vertex_size; i++) \ |
*tnl->vbptr[i].i = tnl->vertex[i].i; \ |
\ |
tnl->vbptr += tnl->vertex_size; \ |
\ |
if (--tnl->counter == 0) \ |
tnl->notify(); \ |
} \ |
else { \ |
GLfloat *dest = tnl->attrptr[ATTR]; \ |
if (N>0) dest[0] = A; \ |
if (N>1) dest[1] = B; \ |
if (N>2) dest[2] = C; \ |
if (N>3) dest[3] = D; \ |
} \ |
} |
#define ATTR4F( ATTR, A, B, C, D ) ATTRF( ATTR, 4, A, B, C, D ) |
#define ATTR3F( ATTR, A, B, C, D ) ATTRF( ATTR, 3, A, B, C, 1 ) |
#define ATTR2F( ATTR, A, B, C, D ) ATTRF( ATTR, 2, A, B, 0, 1 ) |
#define ATTR1F( ATTR, A, B, C, D ) ATTRF( ATTR, 1, A, 0, 0, 1 ) |
#define ATTR3UB( ATTR, A, B, C ) \ |
ATTR3F( ATTR, \ |
UBYTE_TO_FLOAT(A), \ |
UBYTE_TO_FLOAT(B), \ |
UBYTE_TO_FLOAT(C)) |
#define ATTR4UB( ATTR, A, B, C, D ) \ |
ATTR4F( ATTR, \ |
UBYTE_TO_FLOAT(A), \ |
UBYTE_TO_FLOAT(B), \ |
UBYTE_TO_FLOAT(C), \ |
UBYTE_TO_FLOAT(D)) |
/* Vertex |
*/ |
static void tnl_Vertex2f( GLfloat x, GLfloat y ) |
{ |
ATTR2F( VERT_ATTRIB_POS, x, y ); |
} |
static void tnl_Vertex2fv( const GLfloat *v ) |
{ |
ATTR2F( VERT_ATTRIB_POS, v[0], v[1] ); |
} |
static void tnl_Vertex3f( GLfloat x, GLfloat y, GLfloat z ) |
{ |
ATTR3F( VERT_ATTRIB_POS, x, y, z ); |
} |
static void tnl_Vertex3fv( const GLfloat *v ) |
{ |
ATTR3F( VERT_ATTRIB_POS, v[0], v[1], v[2] ); |
} |
static void tnl_Vertex4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) |
{ |
ATTR4F( VERT_ATTRIB_POS, x, y, z, w ); |
} |
static void tnl_Vertex4fv( const GLfloat *v ) |
{ |
ATTR4F( VERT_ATTRIB_POS, v[0], v[1], v[2], v[3] ); |
} |
/* Color |
*/ |
static void tnl_Color3ub( GLubyte r, GLubyte g, GLubyte b ) |
{ |
ATTR3UB( VERT_ATTRIB_COLOR0, r, g, b ); |
} |
static void tnl_Color3ubv( const GLubyte *v ) |
{ |
ATTR3UB( VERT_ATTRIB_COLOR0, v[0], v[1], v[2] ); |
} |
static void tnl_Color4ub( GLubyte r, GLubyte g, GLubyte b, GLubyte a ) |
{ |
ATTR4UB( VERT_ATTRIB_COLOR0, r, g, b, a ); |
} |
static void tnl_Color4ubv( const GLubyte *v ) |
{ |
ATTR4UB( VERT_ATTRIB_COLOR0, v[0], v[1], v[2], v[3] ); |
} |
static void tnl_Color3f( GLfloat r, GLfloat g, GLfloat b ) |
{ |
ATTR3F( VERT_ATTRIB_COLOR0, r, g, b ); |
} |
static void tnl_Color3fv( const GLfloat *v ) |
{ |
ATTR3F( VERT_ATTRIB_COLOR0, v[0], v[1], v[2] ); |
} |
static void tnl_Color4f( GLfloat r, GLfloat g, GLfloat b, GLfloat a ) |
{ |
ATTR4F( VERT_ATTRIB_COLOR0, r, g, b, a ); |
} |
static void tnl_Color4fv( const GLfloat *v ) |
{ |
ATTR4F( VERT_ATTRIB_COLOR0, v[0], v[1], v[2], v[3] ); |
} |
/* Secondary Color |
*/ |
static void tnl_SecondaryColor3ubEXT( GLubyte r, GLubyte g, GLubyte b ) |
{ |
ATTR3UB( VERT_ATTRIB_COLOR1, r, g, b ); |
} |
static void tnl_SecondaryColor3ubvEXT( const GLubyte *v ) |
{ |
ATTR3UB( VERT_ATTRIB_COLOR1, v[0], v[1], v[2] ); |
} |
static void tnl_SecondaryColor3fEXT( GLfloat r, GLfloat g, GLfloat b ) |
{ |
ATTR3F( VERT_ATTRIB_COLOR1, r, g, b ); |
} |
static void tnl_SecondaryColor3fvEXT( const GLfloat *v ) |
{ |
ATTR3F( VERT_ATTRIB_COLOR1, v[0], v[1], v[2] ); |
} |
/* Fog Coord |
*/ |
static void tnl_FogCoordfEXT( GLfloat f ) |
{ |
ATTR1F( VERT_ATTRIB_FOG, f ); |
} |
static void tnl_FogCoordfvEXT( const GLfloat *v ) |
{ |
ATTR1F( VERT_ATTRIB_FOG, v[0] ); |
} |
/* Normal |
*/ |
static void tnl_Normal3f( GLfloat n0, GLfloat n1, GLfloat n2 ) |
{ |
ATTR3F( VERT_ATTRIB_NORMAL, n0, n1, n2 ); |
} |
static void tnl_Normal3fv( const GLfloat *v ) |
{ |
ATTR3F( VERT_ATTRIB_COLOR1, v[0], v[1], v[2] ); |
} |
/* TexCoord |
*/ |
static void tnl_TexCoord1f( GLfloat s ) |
{ |
ATTR1F( VERT_ATTRIB_TEX0, s ); |
} |
static void tnl_TexCoord1fv( const GLfloat *v ) |
{ |
ATTR1F( VERT_ATTRIB_TEX0, v[0] ); |
} |
static void tnl_TexCoord2f( GLfloat s, GLfloat t ) |
{ |
ATTR2F( VERT_ATTRIB_TEX0, s, t ); |
} |
static void tnl_TexCoord2fv( const GLfloat *v ) |
{ |
ATTR2F( VERT_ATTRIB_TEX0, v[0], v[1] ); |
} |
static void tnl_TexCoord3f( GLfloat s, GLfloat t, GLfloat r ) |
{ |
ATTR3F( VERT_ATTRIB_TEX0, s, t, r ); |
} |
static void tnl_TexCoord3fv( const GLfloat *v ) |
{ |
ATTR3F( VERT_ATTRIB_TEX0, v[0], v[1], v[2] ); |
} |
static void tnl_TexCoord4f( GLfloat s, GLfloat t, GLfloat r, GLfloat q ) |
{ |
ATTR4F( VERT_ATTRIB_TEX0, s, t, r, q ); |
} |
static void tnl_TexCoord4fv( const GLfloat *v ) |
{ |
ATTR4F( VERT_ATTRIB_TEX0, v[0], v[1], v[2], v[3] ); |
} |
/* Miscellaneous: |
* |
* These don't alias NV attributes, but still need similar treatment. |
* Basically these are attributes with numbers greater than 16. |
*/ |
static void tnl_EdgeFlag( GLboolean flag ) |
{ |
GLfloat f = flag ? 1 : 0; |
ATTR1F( VERT_ATTRIB_EDGEFLAG, f); |
} |
static void tnl_EdgeFlagv( const GLboolean *flag ) |
{ |
GLfloat f = flag[0] ? 1 : 0; |
ATTR1F( VERT_ATTRIB_EDGEFLAG, f); |
} |
static void tnl_Indexi( GLint idx ) |
{ |
ATTR1F( VERT_ATTRIB_INDEX, idx ); |
} |
static void tnl_Indexiv( const GLint *idx ) |
{ |
ATTR1F( VERT_ATTRIB_INDEX, idx ); |
} |
/* Use dispatch switching to build 'ranges' of eval vertices for each |
* type, avoiding need for flags. (Make |
* evalcoords/evalpoints/vertices/attr0 mutually exclusive) |
*/ |
static void _tnl_EvalCoord1f( GLfloat u ) |
{ |
ATTR1F( VERT_ATTRIB_POS, u ); |
} |
static void _tnl_EvalCoord1fv( const GLfloat *v ) |
{ |
ATTR1F( VERT_ATTRIB_POS, v[0] ); |
} |
static void _tnl_EvalCoord2f( GLfloat u, GLfloat v ) |
{ |
ATTR2F( VERT_ATTRIB_POS, u, v ); |
} |
static void _tnl_EvalCoord2fv( const GLfloat *v ) |
{ |
ATTR2F( VERT_ATTRIB_POS, v[0], v[1] ); |
} |
/* Second level dispatch table for MultiTexCoord, Material and |
* VertexAttribNV. |
* |
* Need this because we want to track things like vertex attribute |
* sizes, presence/otherwise of attribs in recorded vertices, etc, by |
* manipulating the state of dispatch tables. Need therefore a |
* dispatch slot for each value of 'index' or 'unit' in VertexAttribNV |
* and MultiTexCoordARB. Also need a mechnism for keeping this data |
* consistent with what's coming in via the Vertex/Normal/etc api |
* above (where aliasing exists with the traditional entrypoints). |
* Note that MultiTexCoordARB aliases with TexCoord when unit==0. |
* |
* Need presence tracking for material components, too, but not size |
* tracking or help with aliasing. Could move material to seperate |
* dispatch without the "*4" below, or even do the checks every time. |
*/ |
struct attr_dispatch_tab { |
void (*tab[32*4])( void ); |
void (*swapped[32*4])( void ); |
int swapcount; |
int installed_sizes[32]; |
}; |
#define DISPATCH_ATTR1F( ATTR, N, ) |
tnl->vb.attr_dispatch |
/* Result at the back end after second dispatch -- could further |
* specialize for attr zero -- maybe just in the codegen version. |
*/ |
static void tnl_Attr1f( GLint attr, GLfloat s ) |
{ |
ATTR1F( attr, s ); |
} |
static void tnl_Attr1fv( GLint attr, const GLfloat *v ) |
{ |
ATTR1F( attr, v[0] ); |
} |
static void tnl_Attr2f( GLint attr, GLfloat s, GLfloat t ) |
{ |
ATTR2F( attr, s, t ); |
} |
static void tnl_Attr2fv( GLint attr, const GLfloat *v ) |
{ |
ATTR2F( attr, v[0], v[1] ); |
} |
static void tnl_Attr3f( GLint attr, GLfloat s, GLfloat t, GLfloat r ) |
{ |
ATTR3F( attr, s, t, r ); |
} |
static void tnl_Attr3fv( GLint attr, const GLfloat *v ) |
{ |
ATTR3F( attr, v[0], v[1], v[2] ); |
} |
static void tnl_Attr4f( GLint attr, GLfloat s, GLfloat t, GLfloat r, GLfloat q ) |
{ |
ATTR4F( attr, s, t, r, q ); |
} |
static void tnl_Attr4fv( GLint attr, const GLfloat *v ) |
{ |
ATTR4F( attr, v[0], v[1], v[2], v[3] ); |
} |
/* MultiTexcoord: Send through second level dispatch. |
*/ |
static void tnl_MultiTexCoord1fARB( GLenum target, GLfloat s ) |
{ |
GLuint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0; |
if (attr < MAX_VERT_ATTRS) |
DISPATCH_ATTR1F( attr, s ); |
} |
static void tnl_MultiTexCoord1fvARB( GLenum target, const GLfloat *v ) |
{ |
GLuint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0; |
if (attr < MAX_VERT_ATTRS) |
DISPATCH_ATTR1F( attr, v[0] ); |
} |
static void tnl_MultiTexCoord2fARB( GLenum target, GLfloat s, GLfloat t ) |
{ |
GLuint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0; |
if (attr < MAX_VERT_ATTRS) |
DISPATCH_ATTR2F( attr, s, t ); |
} |
static void tnl_MultiTexCoord2fvARB( GLenum target, const GLfloat *v ) |
{ |
GLuint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0; |
if (attr < MAX_VERT_ATTRS) |
DISPATCH_ATTR2F( attr, v[0], v[1] ); |
} |
static void tnl_MultiTexCoord3fARB( GLenum target, GLfloat s, GLfloat t, |
GLfloat r) |
{ |
GLuint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0; |
if (attr < MAX_VERT_ATTRS) |
DISPATCH_ATTR3F( attr, s, t, r ); |
} |
static void tnl_MultiTexCoord3fvARB( GLenum target, const GLfloat *v ) |
{ |
GLuint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0; |
if (attr < MAX_VERT_ATTRS) |
DISPATCH_ATTR3F( attr, v[0], v[1], v[2] ); |
} |
static void tnl_MultiTexCoord4fARB( GLenum target, GLfloat s, GLfloat t, |
GLfloat r, GLfloat q ) |
{ |
GLuint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0; |
if (attr < MAX_VERT_ATTRS) |
DISPATCH_ATTR4F( attr, s, t, r, q ); |
} |
static void tnl_MultiTexCoord4fvARB( GLenum target, const GLfloat *v ) |
{ |
GLuint attr = (target - GL_TEXTURE0_ARB) + VERT_ATTRIB_TEX0; |
if (attr < MAX_VERT_ATTRS) |
DISPATCH_ATTR4F( attr, v[0], v[1], v[2], v[3] ); |
} |
/* NV_vertex_program: |
* |
* Check for errors & reroute through second dispatch layer to get |
* size tracking per-attribute. |
*/ |
static void tnl_VertexAttrib1fNV( GLuint index, GLfloat s ) |
{ |
if (index < MAX_VERT_ATTRS) |
DISPATCH_ATTR1F( index, s ); |
else |
DISPATCH_ERROR; |
} |
static void tnl_VertexAttrib1fvNV( GLuint index, const GLfloat *v ) |
{ |
if (index < MAX_VERT_ATTRS) |
DISPATCH_ATTR1F( index, v[0] ); |
else |
DISPATCH_ERROR; |
} |
static void tnl_VertexAttrib2fNV( GLuint index, GLfloat s, GLfloat t ) |
{ |
if (index < MAX_VERT_ATTRS) |
DISPATCH_ATTR2F( index, s, t ); |
else |
DISPATCH_ERROR; |
} |
static void tnl_VertexAttrib2fvNV( GLuint index, const GLfloat *v ) |
{ |
if (index < MAX_VERT_ATTRS) |
DISPATCH_ATTR2F( index, v[0], v[1] ); |
else |
DISPATCH_ERROR; |
} |
static void tnl_VertexAttrib3fNV( GLuint index, GLfloat s, GLfloat t, |
GLfloat r ) |
{ |
if (index < MAX_VERT_ATTRS) |
DISPATCH_ATTR3F( index, s, t, r ); |
else |
DISPATCH_ERROR; |
} |
static void tnl_VertexAttrib3fvNV( GLuint index, const GLfloat *v ) |
{ |
if (index < MAX_VERT_ATTRS) |
DISPATCH_ATTR3F( index, v[0], v[1], v[2] ); |
else |
DISPATCH_ERROR; |
} |
static void tnl_VertexAttrib4fNV( GLuint index, GLfloat s, GLfloat t, |
GLfloat r, GLfloat q ) |
{ |
if (index < MAX_VERT_ATTRS) |
DISPATCH_ATTR4F( index, s, t, r, q ); |
else |
DISPATCH_ERROR; |
} |
static void tnl_VertexAttrib4fvNV( GLuint index, const GLfloat *v ) |
{ |
if (index < MAX_VERT_ATTRS) |
DISPATCH_ATTR4F( index, v[0], v[1], v[2], v[3] ); |
else |
DISPATCH_ERROR; |
} |
/* Materials: |
* |
* These are treated as per-vertex attributes, at indices above where |
* the NV_vertex_program leaves off. There are a lot of good things |
* about treating materials this way. |
* |
* *** Need a dispatch step (like VertexAttribute GLint attr, and MultiTexCoord) |
* *** to expand vertex size, etc. Use the same second level dispatch |
* *** (keyed by attr number) as above. |
*/ |
#define MAT( ATTR, face, params ) \ |
do { \ |
if (face != GL_BACK) \ |
DISPATCH_ATTRF( ATTR, N, params ); \ |
if (face != GL_FRONT) \ |
DISPATCH_ATTRF( ATTR+7, N, params ); \ |
} while (0) |
/* NOTE: Have to remove/dealwith colormaterial crossovers, probably |
* later on - in the meantime just store everything. |
*/ |
static void _tnl_Materialfv( GLenum face, GLenum pname, |
const GLfloat *params ) |
{ |
switch (pname) { |
case GL_EMISSION: |
MAT( VERT_ATTRIB_FRONT_EMMISSION, 4, face, params ); |
break; |
case GL_AMBIENT: |
MAT( VERT_ATTRIB_FRONT_AMBIENT, 4, face, params ); |
break; |
case GL_DIFFUSE: |
MAT( VERT_ATTRIB_FRONT_DIFFUSE, 4, face, params ); |
break; |
case GL_SPECULAR: |
MAT( VERT_ATTRIB_FRONT_SPECULAR, 4, face, params ); |
break; |
case GL_SHININESS: |
MAT( VERT_ATTRIB_FRONT_SHININESS, 1, face, params ); |
break; |
case GL_COLOR_INDEXES: |
MAT( VERT_ATTRIB_FRONT_EMMISSION, 3, face, params ); |
break; |
case GL_AMBIENT_AND_DIFFUSE: |
MAT( VERT_ATTRIB_FRONT_AMBIENT, 4, face, params ); |
MAT( VERT_ATTRIB_FRONT_DIFFUSE, 4, face, params ); |
break; |
default: |
_mesa_error( ctx, GL_INVALID_ENUM, where ); |
return; |
} |
} |
/* Codegen support |
*/ |
static struct dynfn *lookup( struct dynfn *l, int key ) |
{ |
struct dynfn *f; |
foreach( f, l ) { |
if (f->key == key) |
return f; |
} |
return 0; |
} |
/* Vertex descriptor |
*/ |
struct _tnl_vertex_descriptor { |
GLuint attr_bits[4]; |
}; |
/* Can't use the loopback template for this: |
*/ |
#define CHOOSE(FN, FNTYPE, MASK, ACTIVE, ARGS1, ARGS2 ) \ |
static void choose_##FN ARGS1 \ |
{ \ |
int key = tnl->vertex_format & (MASK|ACTIVE); \ |
struct dynfn *dfn = lookup( &tnl->dfn_cache.FN, key ); \ |
\ |
if (dfn == 0) \ |
dfn = tnl->codegen.FN( &vb, key ); \ |
else if (MESA_VERBOSE & DEBUG_CODEGEN) \ |
_mesa_debug(NULL, "%s -- cached codegen\n", __FUNCTION__ ); \ |
\ |
if (dfn) \ |
tnl->context->Exec->FN = (FNTYPE)(dfn->code); \ |
else { \ |
if (MESA_VERBOSE & DEBUG_CODEGEN) \ |
_mesa_debug(NULL, "%s -- generic version\n", __FUNCTION__ ); \ |
tnl->context->Exec->FN = tnl_##FN; \ |
} \ |
\ |
tnl->context->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; \ |
tnl->context->Exec->FN ARGS2; \ |
} |
CHOOSE(Normal3f, p3f, 3, VERT_ATTRIB_NORMAL, |
(GLfloat a,GLfloat b,GLfloat c), (a,b,c)) |
CHOOSE(Normal3fv, pfv, 3, VERT_ATTRIB_NORMAL, |
(const GLfloat *v), (v)) |
CHOOSE(Color4ub, p4ub, 4, VERT_ATTRIB_COLOR0, |
(GLubyte a,GLubyte b, GLubyte c, GLubyte d), (a,b,c,d)) |
CHOOSE(Color4ubv, pubv, 4, VERT_ATTRIB_COLOR0, |
(const GLubyte *v), (v)) |
CHOOSE(Color3ub, p3ub, 3, VERT_ATTRIB_COLOR0, |
(GLubyte a,GLubyte b, GLubyte c), (a,b,c)) |
CHOOSE(Color3ubv, pubv, 3, VERT_ATTRIB_COLOR0, |
(const GLubyte *v), (v)) |
CHOOSE(Color4f, p4f, 4, VERT_ATTRIB_COLOR0, |
(GLfloat a,GLfloat b, GLfloat c, GLfloat d), (a,b,c,d)) |
CHOOSE(Color4fv, pfv, 4, VERT_ATTRIB_COLOR0, |
(const GLfloat *v), (v)) |
CHOOSE(Color3f, p3f, 3, VERT_ATTRIB_COLOR0, |
(GLfloat a,GLfloat b, GLfloat c), (a,b,c)) |
CHOOSE(Color3fv, pfv, 3, VERT_ATTRIB_COLOR0, |
(const GLfloat *v), (v)) |
CHOOSE(SecondaryColor3ubEXT, p3ub, VERT_ATTRIB_COLOR1, |
(GLubyte a,GLubyte b, GLubyte c), (a,b,c)) |
CHOOSE(SecondaryColor3ubvEXT, pubv, VERT_ATTRIB_COLOR1, |
(const GLubyte *v), (v)) |
CHOOSE(SecondaryColor3fEXT, p3f, VERT_ATTRIB_COLOR1, |
(GLfloat a,GLfloat b, GLfloat c), (a,b,c)) |
CHOOSE(SecondaryColor3fvEXT, pfv, VERT_ATTRIB_COLOR1, |
(const GLfloat *v), (v)) |
CHOOSE(TexCoord2f, p2f, VERT_ATTRIB_TEX0, |
(GLfloat a,GLfloat b), (a,b)) |
CHOOSE(TexCoord2fv, pfv, VERT_ATTRIB_TEX0, |
(const GLfloat *v), (v)) |
CHOOSE(TexCoord1f, p1f, VERT_ATTRIB_TEX0, |
(GLfloat a), (a)) |
CHOOSE(TexCoord1fv, pfv, VERT_ATTRIB_TEX0, |
(const GLfloat *v), (v)) |
CHOOSE(MultiTexCoord2fARB, pe2f, VERT_ATTRIB_TEX0, |
(GLenum u,GLfloat a,GLfloat b), (u,a,b)) |
CHOOSE(MultiTexCoord2fvARB, pefv, MASK_ST_ALL, ACTIVE_ST_ALL, |
(GLenum u,const GLfloat *v), (u,v)) |
CHOOSE(MultiTexCoord1fARB, pe1f, MASK_ST_ALL, ACTIVE_ST_ALL, |
(GLenum u,GLfloat a), (u,a)) |
CHOOSE(MultiTexCoord1fvARB, pefv, MASK_ST_ALL, ACTIVE_ST_ALL, |
(GLenum u,const GLfloat *v), (u,v)) |
CHOOSE(Vertex3f, p3f, VERT_ATTRIB_POS, |
(GLfloat a,GLfloat b,GLfloat c), (a,b,c)) |
CHOOSE(Vertex3fv, pfv, VERT_ATTRIB_POS, |
(const GLfloat *v), (v)) |
CHOOSE(Vertex2f, p2f, VERT_ATTRIB_POS, |
(GLfloat a,GLfloat b), (a,b)) |
CHOOSE(Vertex2fv, pfv, VERT_ATTRIB_POS, |
(const GLfloat *v), (v)) |
void _tnl_InitVtxfmtChoosers( GLvertexformat *vfmt ) |
{ |
vfmt->Color3f = choose_Color3f; |
vfmt->Color3fv = choose_Color3fv; |
vfmt->Color3ub = choose_Color3ub; |
vfmt->Color3ubv = choose_Color3ubv; |
vfmt->Color4f = choose_Color4f; |
vfmt->Color4fv = choose_Color4fv; |
vfmt->Color4ub = choose_Color4ub; |
vfmt->Color4ubv = choose_Color4ubv; |
vfmt->SecondaryColor3fEXT = choose_SecondaryColor3fEXT; |
vfmt->SecondaryColor3fvEXT = choose_SecondaryColor3fvEXT; |
vfmt->SecondaryColor3ubEXT = choose_SecondaryColor3ubEXT; |
vfmt->SecondaryColor3ubvEXT = choose_SecondaryColor3ubvEXT; |
vfmt->MultiTexCoord1fARB = dd_MultiTexCoord1fARB; |
vfmt->MultiTexCoord1fvARB = dd_MultiTexCoord1fvARB; |
vfmt->MultiTexCoord2fARB = dd_MultiTexCoord2fARB; |
vfmt->MultiTexCoord2fvARB = dd_MultiTexCoord2fvARB; |
vfmt->MultiTexCoord3fARB = dd_MultiTexCoord3fARB; |
vfmt->MultiTexCoord3fvARB = dd_MultiTexCoord3fvARB; |
vfmt->MultiTexCoord4fARB = dd_MultiTexCoord4fARB; |
vfmt->MultiTexCoord4fvARB = dd_MultiTexCoord4fvARB; |
vfmt->Normal3f = choose_Normal3f; |
vfmt->Normal3fv = choose_Normal3fv; |
vfmt->TexCoord1f = choose_TexCoord1f; |
vfmt->TexCoord1fv = choose_TexCoord1fv; |
vfmt->TexCoord2f = choose_TexCoord2f; |
vfmt->TexCoord2fv = choose_TexCoord2fv; |
vfmt->TexCoord3f = choose_TexCoord3f; |
vfmt->TexCoord3fv = choose_TexCoord3fv; |
vfmt->TexCoord4f = choose_TexCoord4f; |
vfmt->TexCoord4fv = choose_TexCoord4fv; |
vfmt->Vertex2f = choose_Vertex2f; |
vfmt->Vertex2fv = choose_Vertex2fv; |
vfmt->Vertex3f = choose_Vertex3f; |
vfmt->Vertex3fv = choose_Vertex3fv; |
vfmt->Vertex4f = choose_Vertex4f; |
vfmt->Vertex4fv = choose_Vertex4fv; |
vfmt->FogCoordfvEXT = choose_FogCoordfvEXT; |
vfmt->FogCoordfEXT = choose_FogCoordfEXT; |
vfmt->EdgeFlag = choose_EdgeFlag; |
vfmt->EdgeFlagv = choose_EdgeFlagv; |
vfmt->Indexi = choose_Indexi; |
vfmt->Indexiv = choose_Indexiv; |
vfmt->EvalCoord1f = choose_EvalCoord1f; |
vfmt->EvalCoord1fv = choose_EvalCoord1fv; |
vfmt->EvalCoord2f = choose_EvalCoord2f; |
vfmt->EvalCoord2fv = choose_EvalCoord2fv; |
vfmt->Materialfv = dd_Materialfv; |
} |
static struct dynfn *codegen_noop( struct _vb *vb, int key ) |
{ |
(void) vb; (void) key; |
return 0; |
} |
void _tnl_InitCodegen( struct dfn_generators *gen ) |
{ |
/* Generate an attribute or vertex command. |
*/ |
gen->Attr1f = codegen_noop; |
gen->Attr1fv = codegen_noop; |
gen->Attr2f = codegen_noop; |
gen->Attr2fv = codegen_noop; |
gen->Attr3f = codegen_noop; |
gen->Attr3fv = codegen_noop; |
gen->Attr4f = codegen_noop; |
gen->Attr4fv = codegen_noop; |
/* Index is never zero for these... |
*/ |
gen->Attr3ub = codegen_noop; |
gen->Attr3ubv = codegen_noop; |
gen->Attr4ub = codegen_noop; |
gen->Attr4ubv = codegen_noop; |
/* As above, but deal with the extra (redundant by now) index |
* argument to the generated function. |
*/ |
gen->NVAttr1f = codegen_noop; |
gen->NVAttr1fv = codegen_noop; |
gen->NVAttr2f = codegen_noop; |
gen->NVAttr2fv = codegen_noop; |
gen->NVAttr3f = codegen_noop; |
gen->NVAttr3fv = codegen_noop; |
gen->NVAttr4f = codegen_noop; |
gen->NVAttr4fv = codegen_noop; |
if (!getenv("MESA_NO_CODEGEN")) { |
#if defined(USE_X86_ASM) |
_tnl_InitX86Codegen( gen ); |
#endif |
#if defined(USE_SSE_ASM) |
_tnl_InitSSECodegen( gen ); |
#endif |
#if defined(USE_3DNOW_ASM) |
#endif |
#if defined(USE_SPARC_ASM) |
#endif |
} |
} |
/shark/trunk/ports/mesa/src/tnl/t_imm_api.c |
---|
0,0 → 1,1368 |
/* $Id: t_imm_api.c,v 1.1 2003-02-28 11:48:06 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 4.1 |
* |
* Copyright (C) 1999-2001 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 "context.h" |
#include "dlist.h" |
#include "enums.h" |
#include "light.h" |
#include "imports.h" |
#include "state.h" |
#include "colormac.h" |
#include "macros.h" |
#include "vtxfmt.h" |
#include "t_context.h" |
#include "t_imm_api.h" |
#include "t_imm_elt.h" |
#include "t_imm_exec.h" |
#include "t_imm_dlist.h" |
/* A cassette is full or flushed on a statechange. |
*/ |
void _tnl_flush_immediate( GLcontext *ctx, struct immediate *IM ) |
{ |
if (!ctx) { |
/* We were called by glVertex, glEvalCoord, glArrayElement, etc. |
* The current context is corresponds to the IM structure. |
*/ |
GET_CURRENT_CONTEXT(context); |
ctx = context; |
} |
if (MESA_VERBOSE & VERBOSE_IMMEDIATE) |
_mesa_debug(ctx, "_tnl_flush_immediate IM: %d compiling: %d\n", |
IM->id, ctx->CompileFlag); |
if (IM->FlushElt == FLUSH_ELT_EAGER) { |
_tnl_translate_array_elts( ctx, IM, IM->LastPrimitive, IM->Count ); |
} |
/* Mark the last primitive: |
*/ |
IM->PrimitiveLength[IM->LastPrimitive] = IM->Count - IM->LastPrimitive; |
IM->Primitive[IM->LastPrimitive] |= PRIM_LAST; |
if (ctx->CompileFlag) |
_tnl_compile_cassette( ctx, IM ); |
else |
_tnl_execute_cassette( ctx, IM ); |
} |
/* Hook for ctx->Driver.FlushVertices: |
*/ |
void _tnl_flush_vertices( GLcontext *ctx, GLuint flags ) |
{ |
struct immediate *IM = TNL_CURRENT_IM(ctx); |
if (MESA_VERBOSE & VERBOSE_IMMEDIATE) |
_mesa_debug(ctx, |
"_tnl_flush_vertices flags %x IM(%d) %d..%d Flag[%d]: %x\n", |
flags, IM->id, IM->Start, IM->Count, IM->Start, |
IM->Flag[IM->Start]); |
if (IM->Flag[IM->Start]) { |
if ((flags & FLUSH_UPDATE_CURRENT) || |
IM->Count > IM->Start || |
(IM->Flag[IM->Start] & (VERT_BIT_BEGIN | VERT_BIT_END))) { |
_tnl_flush_immediate( ctx, IM ); |
} |
} |
} |
void |
_tnl_save_Begin( GLenum mode ) |
{ |
GET_CURRENT_CONTEXT(ctx); |
struct immediate *IM = TNL_CURRENT_IM(ctx); |
GLuint inflags, state; |
/* _mesa_debug(ctx, "%s: before: %x\n", __FUNCTION__, IM->BeginState); */ |
if (mode > GL_POLYGON) { |
_mesa_compile_error( ctx, GL_INVALID_ENUM, "_tnl_Begin" ); |
return; |
} |
if (ctx->NewState) |
_mesa_update_state(ctx); |
#if 000 |
/* if only a very few slots left, might as well flush now |
*/ |
if (IM->Count > IMM_MAXDATA-8) { |
_tnl_flush_immediate( ctx, IM ); |
IM = TNL_CURRENT_IM(ctx); |
} |
#endif |
/* Check for and flush buffered vertices from internal operations. |
*/ |
if (IM->SavedBeginState) { |
_tnl_flush_immediate( ctx, IM ); |
IM = TNL_CURRENT_IM(ctx); |
IM->BeginState = IM->SavedBeginState; |
IM->SavedBeginState = 0; |
} |
state = IM->BeginState; |
inflags = state & (VERT_BEGIN_0|VERT_BEGIN_1); |
state |= inflags << 2; /* set error conditions */ |
if (inflags != (VERT_BEGIN_0|VERT_BEGIN_1)) |
{ |
GLuint count = IM->Count; |
GLuint last = IM->LastPrimitive; |
state |= (VERT_BEGIN_0|VERT_BEGIN_1); |
IM->Flag[count] |= VERT_BIT_BEGIN; |
IM->Primitive[count] = mode | PRIM_BEGIN; |
IM->PrimitiveLength[IM->LastPrimitive] = count - IM->LastPrimitive; |
IM->LastPrimitive = count; |
/* Not quite right. Need to use the fallback '_aa_ArrayElement' |
* when not known to be inside begin/end and arrays are |
* unlocked. |
*/ |
if (IM->FlushElt == FLUSH_ELT_EAGER) { |
_tnl_translate_array_elts( ctx, IM, last, count ); |
} |
} |
ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; |
IM->BeginState = state; |
/* Update save_primitive now. Don't touch ExecPrimitive as this is |
* updated in the replay of this cassette if we are in |
* COMPILE_AND_EXECUTE mode. |
*/ |
if (ctx->Driver.CurrentSavePrimitive == PRIM_UNKNOWN) |
ctx->Driver.CurrentSavePrimitive = PRIM_INSIDE_UNKNOWN_PRIM; |
else if (ctx->Driver.CurrentSavePrimitive == PRIM_OUTSIDE_BEGIN_END) |
ctx->Driver.CurrentSavePrimitive = mode; |
} |
void |
_tnl_Begin( GLenum mode ) |
{ |
GET_CURRENT_CONTEXT(ctx); |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
ASSERT (!ctx->CompileFlag); |
if (mode > GL_POLYGON) { |
_mesa_error( ctx, GL_INVALID_ENUM, "_tnl_Begin(0x%x)", mode ); |
return; |
} |
if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) { |
_mesa_error( ctx, GL_INVALID_OPERATION, "_tnl_Begin" ); |
return; |
} |
if (ctx->NewState) |
_mesa_update_state(ctx); |
{ |
struct immediate *IM = TNL_CURRENT_IM(ctx); |
GLuint count = IM->Count; |
GLuint last = IM->LastPrimitive; |
if (IM->Start == IM->Count && |
tnl->Driver.NotifyBegin && |
tnl->Driver.NotifyBegin( ctx, mode )) { |
return; |
} |
assert( IM->SavedBeginState == 0 ); |
assert( IM->BeginState == 0 ); |
/* Not quite right. Need to use the fallback '_aa_ArrayElement' |
* when not known to be inside begin/end and arrays are |
* unlocked. |
*/ |
if (IM->FlushElt == FLUSH_ELT_EAGER) { |
_tnl_translate_array_elts( ctx, IM, last, count ); |
} |
IM->Flag[count] |= VERT_BIT_BEGIN; |
IM->Primitive[count] = mode | PRIM_BEGIN; |
IM->PrimitiveLength[last] = count - last; |
IM->LastPrimitive = count; |
IM->BeginState = (VERT_BEGIN_0|VERT_BEGIN_1); |
/* _mesa_debug(ctx, "%s: %x\n", __FUNCTION__, IM->BeginState); */ |
ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; |
ctx->Driver.CurrentExecPrimitive = mode; |
} |
} |
/* Function which allows operations like 'glRectf' to decompose to a |
* begin/end object and vertices without worrying about what happens |
* with display lists. |
*/ |
GLboolean |
_tnl_hard_begin( GLcontext *ctx, GLenum p ) |
{ |
/* _mesa_debug(ctx, "%s\n", __FUNCTION__); */ |
if (!ctx->CompileFlag) { |
/* If not compiling, treat as a normal begin(). |
*/ |
/* _mesa_debug(ctx, "%s: treating as glBegin\n", __FUNCTION__); */ |
glBegin( p ); |
return GL_TRUE; |
} |
else { |
/* Otherwise, need to do special processing to preserve the |
* condition that these vertices will only be replayed outside |
* future begin/end objects. |
*/ |
struct immediate *IM = TNL_CURRENT_IM(ctx); |
if (ctx->NewState) |
_mesa_update_state(ctx); |
if (IM->Count > IMM_MAXDATA-8) { |
_tnl_flush_immediate( ctx, IM ); |
IM = TNL_CURRENT_IM(ctx); |
} |
/* A lot depends on the degree to which the display list has |
* constrained the possible begin/end states at this point: |
*/ |
switch (IM->BeginState & (VERT_BEGIN_0|VERT_BEGIN_1)) { |
case VERT_BEGIN_0|VERT_BEGIN_1: |
/* This is an immediate known to be inside a begin/end object. |
*/ |
ASSERT(ctx->Driver.CurrentSavePrimitive <= GL_POLYGON); |
IM->BeginState |= (VERT_ERROR_1|VERT_ERROR_0); |
return GL_FALSE; |
case VERT_BEGIN_0: |
case VERT_BEGIN_1: |
/* This is a display-list immediate in an unknown begin/end |
* state. Assert it is empty and convert it to a 'hard' one. |
*/ |
ASSERT(IM->SavedBeginState == 0); |
ASSERT(ctx->Driver.CurrentSavePrimitive == PRIM_UNKNOWN); |
/* Push current beginstate, to be restored later. Don't worry |
* about raising errors. |
*/ |
IM->SavedBeginState = IM->BeginState; |
/* FALLTHROUGH */ |
case 0: |
/* Unless we have fallen through, this is an immediate known to |
* be outside begin/end objects. |
*/ |
ASSERT(ctx->Driver.CurrentSavePrimitive == PRIM_UNKNOWN || |
ctx->Driver.CurrentSavePrimitive == PRIM_OUTSIDE_BEGIN_END); |
ASSERT (IM->FlushElt != FLUSH_ELT_EAGER); |
IM->BeginState |= VERT_BEGIN_0|VERT_BEGIN_1; |
IM->Flag[IM->Count] |= VERT_BIT_BEGIN; |
IM->Primitive[IM->Count] = p | PRIM_BEGIN; |
IM->PrimitiveLength[IM->LastPrimitive] = IM->Count - IM->LastPrimitive; |
IM->LastPrimitive = IM->Count; |
/* This is necessary as this immediate will not be flushed in |
* _tnl_end() -- we leave it active, hoping to pick up more |
* vertices before the next state change. |
*/ |
ctx->Driver.NeedFlush |= FLUSH_STORED_VERTICES; |
return GL_TRUE; |
default: |
assert (0); |
return GL_TRUE; |
} |
} |
} |
/* Both streams now outside begin/end. |
* |
* Leave SavedBeginState untouched -- attempt to gather several |
* rects/arrays together in a single immediate struct. |
*/ |
void |
_tnl_end( GLcontext *ctx ) |
{ |
struct immediate *IM = TNL_CURRENT_IM(ctx); |
GLuint state = IM->BeginState; |
GLuint inflags = (~state) & (VERT_BEGIN_0|VERT_BEGIN_1); |
assert( ctx->Driver.NeedFlush & FLUSH_STORED_VERTICES ); |
state |= inflags << 2; /* errors */ |
if (inflags != (VERT_BEGIN_0|VERT_BEGIN_1)) |
{ |
GLuint count = IM->Count; |
GLuint last = IM->LastPrimitive; |
state &= ~(VERT_BEGIN_0|VERT_BEGIN_1); /* update state */ |
IM->Flag[count] |= VERT_BIT_END; |
IM->Primitive[last] |= PRIM_END; |
IM->PrimitiveLength[last] = count - last; |
IM->Primitive[count] = PRIM_OUTSIDE_BEGIN_END; /* removes PRIM_BEGIN |
* flag if length == 0 |
*/ |
IM->LastPrimitive = count; |
if (IM->FlushElt == FLUSH_ELT_EAGER) { |
_tnl_translate_array_elts( ctx, IM, last, count ); |
} |
} |
IM->BeginState = state; |
if (!ctx->CompileFlag) { |
if (ctx->Driver.CurrentExecPrimitive == PRIM_OUTSIDE_BEGIN_END) |
_mesa_error( ctx, GL_INVALID_OPERATION, "_tnl_End" ); |
else |
ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; |
} |
/* You can set this flag to get the old 'flush_vb on glEnd()' |
* behaviour. |
*/ |
if (MESA_DEBUG_FLAGS & DEBUG_ALWAYS_FLUSH) |
_tnl_flush_immediate( ctx, IM ); |
} |
void |
_tnl_End(void) |
{ |
GET_CURRENT_CONTEXT(ctx); |
_tnl_end( ctx ); |
/* Need to keep save primitive uptodate in COMPILE and |
* COMPILE_AND_EXEC modes, need to keep exec primitive uptodate |
* otherwise. |
*/ |
if (ctx->CompileFlag) |
ctx->Driver.CurrentSavePrimitive = PRIM_OUTSIDE_BEGIN_END; |
} |
#define COLOR( r, g, b, a ) \ |
{ \ |
GET_IMMEDIATE; \ |
GLuint count = IM->Count; \ |
GLfloat *color = IM->Attrib[VERT_ATTRIB_COLOR0][count]; \ |
IM->Flag[count] |= VERT_BIT_COLOR0; \ |
color[0] = r; \ |
color[1] = g; \ |
color[2] = b; \ |
color[3] = a; \ |
} |
static void |
_tnl_Color3f( GLfloat red, GLfloat green, GLfloat blue ) |
{ |
COLOR( red, green, blue, 1.0 ); |
} |
static void |
_tnl_Color3ub( GLubyte red, GLubyte green, GLubyte blue ) |
{ |
COLOR(UBYTE_TO_FLOAT(red), |
UBYTE_TO_FLOAT(green), |
UBYTE_TO_FLOAT(blue), |
1.0); |
} |
static void |
_tnl_Color4f( GLfloat red, GLfloat green, GLfloat blue, GLfloat alpha ) |
{ |
COLOR( red, green, blue, alpha ); |
} |
static void |
_tnl_Color4ub( GLubyte red, GLubyte green, GLubyte blue, GLubyte alpha ) |
{ |
COLOR(UBYTE_TO_FLOAT(red), |
UBYTE_TO_FLOAT(green), |
UBYTE_TO_FLOAT(blue), |
UBYTE_TO_FLOAT(alpha)); |
} |
static void |
_tnl_Color3fv( const GLfloat *v ) |
{ |
COLOR( v[0], v[1], v[2], 1.0 ); |
} |
static void |
_tnl_Color3ubv( const GLubyte *v ) |
{ |
COLOR(UBYTE_TO_FLOAT(v[0]), |
UBYTE_TO_FLOAT(v[1]), |
UBYTE_TO_FLOAT(v[2]), |
1.0 ); |
} |
static void |
_tnl_Color4fv( const GLfloat *v ) |
{ |
COLOR( v[0], v[1], v[2], v[3] ); |
} |
static void |
_tnl_Color4ubv( const GLubyte *v) |
{ |
COLOR(UBYTE_TO_FLOAT(v[0]), |
UBYTE_TO_FLOAT(v[1]), |
UBYTE_TO_FLOAT(v[2]), |
UBYTE_TO_FLOAT(v[3])); |
} |
#define SECONDARY_COLOR( r, g, b ) \ |
{ \ |
GLuint count; \ |
GET_IMMEDIATE; \ |
count = IM->Count; \ |
IM->Flag[count] |= VERT_BIT_COLOR1; \ |
IM->Attrib[VERT_ATTRIB_COLOR1][count][0] = r; \ |
IM->Attrib[VERT_ATTRIB_COLOR1][count][1] = g; \ |
IM->Attrib[VERT_ATTRIB_COLOR1][count][2] = b; \ |
} |
static void |
_tnl_SecondaryColor3fEXT( GLfloat red, GLfloat green, GLfloat blue ) |
{ |
SECONDARY_COLOR( red, green, blue ); |
} |
static void |
_tnl_SecondaryColor3ubEXT( GLubyte red, GLubyte green, GLubyte blue ) |
{ |
SECONDARY_COLOR(UBYTE_TO_FLOAT(red), |
UBYTE_TO_FLOAT(green), |
UBYTE_TO_FLOAT(blue)); |
} |
static void |
_tnl_SecondaryColor3fvEXT( const GLfloat *v ) |
{ |
SECONDARY_COLOR( v[0], v[1], v[2] ); |
} |
static void |
_tnl_SecondaryColor3ubvEXT( const GLubyte *v ) |
{ |
SECONDARY_COLOR(UBYTE_TO_FLOAT(v[0]), |
UBYTE_TO_FLOAT(v[1]), |
UBYTE_TO_FLOAT(v[2])); |
} |
static void |
_tnl_EdgeFlag( GLboolean flag ) |
{ |
GLuint count; |
GET_IMMEDIATE; |
count = IM->Count; |
IM->EdgeFlag[count] = flag; |
IM->Flag[count] |= VERT_BIT_EDGEFLAG; |
} |
static void |
_tnl_EdgeFlagv( const GLboolean *flag ) |
{ |
GLuint count; |
GET_IMMEDIATE; |
count = IM->Count; |
IM->EdgeFlag[count] = *flag; |
IM->Flag[count] |= VERT_BIT_EDGEFLAG; |
} |
static void |
_tnl_FogCoordfEXT( GLfloat f ) |
{ |
GLuint count; |
GET_IMMEDIATE; |
count = IM->Count; |
IM->Attrib[VERT_ATTRIB_FOG][count][0] = f; /*FogCoord[count] = f;*/ |
IM->Flag[count] |= VERT_BIT_FOG; |
} |
static void |
_tnl_FogCoordfvEXT( const GLfloat *v ) |
{ |
GLuint count; |
GET_IMMEDIATE; |
count = IM->Count; |
IM->Attrib[VERT_ATTRIB_FOG][count][0] = v[0]; /*FogCoord[count] = v[0];*/ |
IM->Flag[count] |= VERT_BIT_FOG; |
} |
static void |
_tnl_Indexi( GLint c ) |
{ |
GLuint count; |
GET_IMMEDIATE; |
count = IM->Count; |
IM->Index[count] = c; |
IM->Flag[count] |= VERT_BIT_INDEX; |
} |
static void |
_tnl_Indexiv( const GLint *c ) |
{ |
GLuint count; |
GET_IMMEDIATE; |
count = IM->Count; |
IM->Index[count] = *c; |
IM->Flag[count] |= VERT_BIT_INDEX; |
} |
#define NORMAL( x, y, z ) \ |
{ \ |
GLuint count; \ |
GLfloat *normal; \ |
GET_IMMEDIATE; \ |
count = IM->Count; \ |
IM->Flag[count] |= VERT_BIT_NORMAL; \ |
normal = IM->Attrib[VERT_ATTRIB_NORMAL][count]; \ |
ASSIGN_3V(normal, x,y,z); \ |
} |
#if defined(USE_IEEE) |
#define NORMALF( x, y, z ) \ |
{ \ |
GLuint count; \ |
fi_type *normal; \ |
GET_IMMEDIATE; \ |
count = IM->Count; \ |
IM->Flag[count] |= VERT_BIT_NORMAL; \ |
normal = (fi_type *)IM->Attrib[VERT_ATTRIB_NORMAL][count]; \ |
normal[0].i = ((fi_type *)&(x))->i; \ |
normal[1].i = ((fi_type *)&(y))->i; \ |
normal[2].i = ((fi_type *)&(z))->i; \ |
} |
#else |
#define NORMALF NORMAL |
#endif |
static void |
_tnl_Normal3f( GLfloat nx, GLfloat ny, GLfloat nz ) |
{ |
NORMALF(nx, ny, nz); |
} |
static void |
_tnl_Normal3fv( const GLfloat *v ) |
{ |
NORMALF( v[0], v[1], v[2] ); |
/* struct immediate *IM = (struct immediate *)(((GLcontext *) _glapi_Context)->swtnl_im); */ |
/* IM->Flag[IM->Count] = VERT_NORM; */ |
} |
#define TEXCOORD1(s) \ |
{ \ |
GLuint count; \ |
GLfloat *tc; \ |
GET_IMMEDIATE; \ |
count = IM->Count; \ |
IM->Flag[count] |= VERT_BIT_TEX0; \ |
tc = IM->Attrib[VERT_ATTRIB_TEX0][count]; \ |
ASSIGN_4V(tc,s,0,0,1); \ |
} |
#define TEXCOORD2(s, t) \ |
{ \ |
GLuint count; \ |
GLfloat *tc; \ |
GET_IMMEDIATE; \ |
count = IM->Count; \ |
IM->Flag[count] |= VERT_BIT_TEX0; \ |
tc = IM->Attrib[VERT_ATTRIB_TEX0][count]; \ |
ASSIGN_4V(tc, s, t, 0, 1); \ |
} |
#define TEXCOORD3(s, t, u) \ |
{ \ |
GLuint count; \ |
GLfloat *tc; \ |
GET_IMMEDIATE; \ |
count = IM->Count; \ |
IM->Flag[count] |= VERT_BIT_TEX0; \ |
IM->TexSize |= TEX_0_SIZE_3; \ |
tc = IM->Attrib[VERT_ATTRIB_TEX0][count]; \ |
ASSIGN_4V(tc, s, t, u, 1); \ |
} |
#define TEXCOORD4(s, t, u, v) \ |
{ \ |
GLuint count; \ |
GLfloat *tc; \ |
GET_IMMEDIATE; \ |
count = IM->Count; \ |
IM->Flag[count] |= VERT_BIT_TEX0; \ |
IM->TexSize |= TEX_0_SIZE_4; \ |
tc = IM->Attrib[VERT_ATTRIB_TEX0][count]; \ |
ASSIGN_4V(tc, s, t, u, v); \ |
} |
#if defined(USE_IEEE) |
#define TEXCOORD2F(s, t) \ |
{ \ |
GLuint count; \ |
fi_type *tc; \ |
GET_IMMEDIATE; \ |
count = IM->Count; \ |
IM->Flag[count] |= VERT_BIT_TEX0; \ |
tc = (fi_type *)IM->Attrib[VERT_ATTRIB_TEX0][count]; \ |
tc[0].i = ((fi_type *)&(s))->i; \ |
tc[1].i = ((fi_type *)&(t))->i; \ |
tc[2].i = 0; \ |
tc[3].i = IEEE_ONE; \ |
} |
#else |
#define TEXCOORD2F TEXCOORD2 |
#endif |
static void |
_tnl_TexCoord1f( GLfloat s ) |
{ |
TEXCOORD1(s); |
} |
static void |
_tnl_TexCoord2f( GLfloat s, GLfloat t ) |
{ |
TEXCOORD2F(s, t); |
} |
static void |
_tnl_TexCoord3f( GLfloat s, GLfloat t, GLfloat r ) |
{ |
TEXCOORD3(s, t, r); |
} |
static void |
_tnl_TexCoord4f( GLfloat s, GLfloat t, GLfloat r, GLfloat q ) |
{ |
TEXCOORD4(s, t, r, q) |
} |
static void |
_tnl_TexCoord1fv( const GLfloat *v ) |
{ |
TEXCOORD1(v[0]); |
} |
static void |
_tnl_TexCoord2fv( const GLfloat *v ) |
{ |
TEXCOORD2F(v[0], v[1]); |
} |
static void |
_tnl_TexCoord3fv( const GLfloat *v ) |
{ |
TEXCOORD3(v[0], v[1], v[2]); |
} |
static void |
_tnl_TexCoord4fv( const GLfloat *v ) |
{ |
TEXCOORD4(v[0], v[1], v[2], v[3]); |
} |
/* KW: Run into bad problems in vertex copying if we don't fully pad |
* the incoming vertices. |
*/ |
#define VERTEX2(IM, x,y) \ |
{ \ |
GLuint count = IM->Count++; \ |
GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \ |
IM->Flag[count] |= VERT_BIT_POS; \ |
ASSIGN_4V(dest, x, y, 0, 1); \ |
/* ASSERT(IM->Flag[IM->Count]==0); */ \ |
if (count == IMM_MAXDATA - 1) \ |
_tnl_flush_immediate( NULL, IM ); \ |
} |
#define VERTEX3(IM,x,y,z) \ |
{ \ |
GLuint count = IM->Count++; \ |
GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \ |
IM->Flag[count] |= VERT_BITS_OBJ_23; \ |
ASSIGN_4V(dest, x, y, z, 1); \ |
/* ASSERT(IM->Flag[IM->Count]==0); */ \ |
if (count == IMM_MAXDATA - 1) \ |
_tnl_flush_immediate( NULL, IM ); \ |
} |
#define VERTEX4(IM, x,y,z,w) \ |
{ \ |
GLuint count = IM->Count++; \ |
GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \ |
IM->Flag[count] |= VERT_BITS_OBJ_234; \ |
ASSIGN_4V(dest, x, y, z, w); \ |
if (count == IMM_MAXDATA - 1) \ |
_tnl_flush_immediate( NULL, IM ); \ |
} |
#if defined(USE_IEEE) |
#define VERTEX2F(IM, x, y) \ |
{ \ |
GLuint count = IM->Count++; \ |
fi_type *dest = (fi_type *)IM->Attrib[VERT_ATTRIB_POS][count]; \ |
IM->Flag[count] |= VERT_BIT_POS; \ |
dest[0].i = ((fi_type *)&(x))->i; \ |
dest[1].i = ((fi_type *)&(y))->i; \ |
dest[2].i = 0; \ |
dest[3].i = IEEE_ONE; \ |
/* ASSERT(IM->Flag[IM->Count]==0); */ \ |
if (count == IMM_MAXDATA - 1) \ |
_tnl_flush_immediate( NULL, IM ); \ |
} |
#else |
#define VERTEX2F VERTEX2 |
#endif |
#if defined(USE_IEEE) |
#define VERTEX3F(IM, x, y, z) \ |
{ \ |
GLuint count = IM->Count++; \ |
fi_type *dest = (fi_type *)IM->Attrib[VERT_ATTRIB_POS][count]; \ |
IM->Flag[count] |= VERT_BITS_OBJ_23; \ |
dest[0].i = ((fi_type *)&(x))->i; \ |
dest[1].i = ((fi_type *)&(y))->i; \ |
dest[2].i = ((fi_type *)&(z))->i; \ |
dest[3].i = IEEE_ONE; \ |
/* ASSERT(IM->Flag[IM->Count]==0); */ \ |
if (count == IMM_MAXDATA - 1) \ |
_tnl_flush_immediate( NULL, IM ); \ |
} |
#else |
#define VERTEX3F VERTEX3 |
#endif |
#if defined(USE_IEEE) |
#define VERTEX4F(IM, x, y, z, w) \ |
{ \ |
GLuint count = IM->Count++; \ |
fi_type *dest = (fi_type *)IM->Attrib[VERT_ATTRIB_POS][count]; \ |
IM->Flag[count] |= VERT_BITS_OBJ_234; \ |
dest[0].i = ((fi_type *)&(x))->i; \ |
dest[1].i = ((fi_type *)&(y))->i; \ |
dest[2].i = ((fi_type *)&(z))->i; \ |
dest[3].i = ((fi_type *)&(w))->i; \ |
if (count == IMM_MAXDATA - 1) \ |
_tnl_flush_immediate( NULL, IM ); \ |
} |
#else |
#define VERTEX4F VERTEX4 |
#endif |
static void |
_tnl_Vertex2f( GLfloat x, GLfloat y ) |
{ |
GET_IMMEDIATE; |
VERTEX2F( IM, x, y ); |
} |
static void |
_tnl_Vertex3f( GLfloat x, GLfloat y, GLfloat z ) |
{ |
GET_IMMEDIATE; |
VERTEX3F( IM, x, y, z ); |
} |
static void |
_tnl_Vertex4f( GLfloat x, GLfloat y, GLfloat z, GLfloat w ) |
{ |
GET_IMMEDIATE; |
VERTEX4F( IM, x, y, z, w ); |
} |
static void |
_tnl_Vertex2fv( const GLfloat *v ) |
{ |
GET_IMMEDIATE; |
VERTEX2F( IM, v[0], v[1] ); |
} |
static void |
_tnl_Vertex3fv( const GLfloat *v ) |
{ |
GET_IMMEDIATE; |
VERTEX3F( IM, v[0], v[1], v[2] ); |
} |
static void |
_tnl_Vertex4fv( const GLfloat *v ) |
{ |
GET_IMMEDIATE; |
VERTEX4F( IM, v[0], v[1], v[2], v[3] ); |
} |
/* |
* GL_ARB_multitexture |
* |
* Note: the multitexture spec says that specifying an invalid target |
* has undefined results and does not have to generate an error. Just |
* don't crash. We no-op on invalid targets. |
*/ |
#define MAX_TARGET (GL_TEXTURE0_ARB + MAX_TEXTURE_UNITS) |
#define MULTI_TEXCOORD1(target, s) \ |
{ \ |
GET_IMMEDIATE; \ |
GLuint texunit = target - GL_TEXTURE0_ARB; \ |
if (texunit < IM->MaxTextureUnits) { \ |
GLuint count = IM->Count; \ |
GLfloat *tc = IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count]; \ |
ASSIGN_4V(tc, s, 0.0F, 0.0F, 1.0F); \ |
IM->Flag[count] |= VERT_BIT_TEX(texunit); \ |
} \ |
} |
#define MULTI_TEXCOORD2(target, s, t) \ |
{ \ |
GET_IMMEDIATE; \ |
GLuint texunit = target - GL_TEXTURE0_ARB; \ |
if (texunit < IM->MaxTextureUnits) { \ |
GLuint count = IM->Count; \ |
GLfloat *tc = IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count]; \ |
ASSIGN_4V(tc, s, t, 0.0F, 1.0F); \ |
IM->Flag[count] |= VERT_BIT_TEX(texunit); \ |
} \ |
} |
#define MULTI_TEXCOORD3(target, s, t, u) \ |
{ \ |
GET_IMMEDIATE; \ |
GLuint texunit = target - GL_TEXTURE0_ARB; \ |
if (texunit < IM->MaxTextureUnits) { \ |
GLuint count = IM->Count; \ |
GLfloat *tc = IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count]; \ |
ASSIGN_4V(tc, s, t, u, 1.0F); \ |
IM->Flag[count] |= VERT_BIT_TEX(texunit); \ |
IM->TexSize |= TEX_SIZE_3(texunit); \ |
} \ |
} |
#define MULTI_TEXCOORD4(target, s, t, u, v) \ |
{ \ |
GET_IMMEDIATE; \ |
GLuint texunit = target - GL_TEXTURE0_ARB; \ |
if (texunit < IM->MaxTextureUnits) { \ |
GLuint count = IM->Count; \ |
GLfloat *tc = IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count]; \ |
ASSIGN_4V(tc, s, t, u, v); \ |
IM->Flag[count] |= VERT_BIT_TEX(texunit); \ |
IM->TexSize |= TEX_SIZE_4(texunit); \ |
} \ |
} |
#if defined(USE_IEEE) |
#define MULTI_TEXCOORD2F(target, s, t) \ |
{ \ |
GET_IMMEDIATE; \ |
GLuint texunit = target - GL_TEXTURE0_ARB; \ |
if (texunit < IM->MaxTextureUnits) { \ |
GLuint count = IM->Count; \ |
fi_type *tc = (fi_type *)IM->Attrib[VERT_ATTRIB_TEX0 + texunit][count];\ |
IM->Flag[count] |= VERT_BIT_TEX(texunit); \ |
tc[0].i = ((fi_type *)&(s))->i; \ |
tc[1].i = ((fi_type *)&(t))->i; \ |
tc[2].i = 0; \ |
tc[3].i = IEEE_ONE; \ |
} \ |
} |
#else |
#define MULTI_TEXCOORD2F MULTI_TEXCOORD2 |
#endif |
static void |
_tnl_MultiTexCoord1fARB(GLenum target, GLfloat s) |
{ |
MULTI_TEXCOORD1( target, s ); |
} |
static void |
_tnl_MultiTexCoord1fvARB(GLenum target, const GLfloat *v) |
{ |
MULTI_TEXCOORD1( target, v[0] ); |
} |
static void |
_tnl_MultiTexCoord2fARB(GLenum target, GLfloat s, GLfloat t) |
{ |
MULTI_TEXCOORD2F( target, s, t ); |
} |
static void |
_tnl_MultiTexCoord2fvARB(GLenum target, const GLfloat *v) |
{ |
MULTI_TEXCOORD2F( target, v[0], v[1] ); |
} |
static void |
_tnl_MultiTexCoord3fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r) |
{ |
MULTI_TEXCOORD3( target, s, t, r ); |
} |
static void |
_tnl_MultiTexCoord3fvARB(GLenum target, const GLfloat *v) |
{ |
MULTI_TEXCOORD3( target, v[0], v[1], v[2] ); |
} |
static void |
_tnl_MultiTexCoord4fARB(GLenum target, GLfloat s, GLfloat t, GLfloat r, GLfloat q) |
{ |
MULTI_TEXCOORD4( target, s, t, r, q ); |
} |
static void |
_tnl_MultiTexCoord4fvARB(GLenum target, const GLfloat *v) |
{ |
MULTI_TEXCOORD4( target, v[0], v[1], v[2], v[3] ); |
} |
/* KW: Because the eval values don't become 'current', fixup will flow |
* through these vertices, and then evaluation will write on top |
* of the fixup results. |
* |
* Note: using Obj to hold eval coord data. |
*/ |
#define EVALCOORD1(IM, x) \ |
{ \ |
GLuint count = IM->Count++; \ |
GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \ |
IM->Flag[count] |= VERT_BIT_EVAL_C1; \ |
ASSIGN_4V(dest, x, 0, 0, 1); \ |
if (count == IMM_MAXDATA-1) \ |
_tnl_flush_immediate( NULL, IM ); \ |
} |
#define EVALCOORD2(IM, x, y) \ |
{ \ |
GLuint count = IM->Count++; \ |
GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \ |
IM->Flag[count] |= VERT_BIT_EVAL_C2; \ |
ASSIGN_4V(dest, x, y, 0, 1); \ |
if (count == IMM_MAXDATA-1) \ |
_tnl_flush_immediate( NULL, IM ); \ |
} |
#define EVALPOINT1(IM, x) \ |
{ \ |
GLuint count = IM->Count++; \ |
GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \ |
IM->Flag[count] |= VERT_BIT_EVAL_P1; \ |
ASSIGN_4V(dest, x, 0, 0, 1); \ |
if (count == IMM_MAXDATA-1) \ |
_tnl_flush_immediate( NULL, IM ); \ |
} |
#define EVALPOINT2(IM, x, y) \ |
{ \ |
GLuint count = IM->Count++; \ |
GLfloat *dest = IM->Attrib[VERT_ATTRIB_POS][count]; \ |
IM->Flag[count] |= VERT_BIT_EVAL_P2; \ |
ASSIGN_4V(dest, x, y, 0, 1); \ |
if (count == IMM_MAXDATA-1) \ |
_tnl_flush_immediate( NULL, IM ); \ |
} |
static void |
_tnl_EvalCoord1f( GLfloat u ) |
{ |
GET_IMMEDIATE; |
EVALCOORD1( IM, u ); |
} |
static void |
_tnl_EvalCoord1fv( const GLfloat *u ) |
{ |
GET_IMMEDIATE; |
EVALCOORD1( IM, (GLfloat) *u ); |
} |
static void |
_tnl_EvalCoord2f( GLfloat u, GLfloat v ) |
{ |
GET_IMMEDIATE; |
EVALCOORD2( IM, u, v ); |
} |
static void |
_tnl_EvalCoord2fv( const GLfloat *u ) |
{ |
GET_IMMEDIATE; |
EVALCOORD2( IM, u[0], u[1] ); |
} |
static void |
_tnl_EvalPoint1( GLint i ) |
{ |
GET_IMMEDIATE; |
EVALPOINT1( IM, (GLfloat) i ); |
} |
static void |
_tnl_EvalPoint2( GLint i, GLint j ) |
{ |
GET_IMMEDIATE; |
EVALPOINT2( IM, (GLfloat) i, (GLfloat) j ); |
} |
/* Need to use the default array-elt outside begin/end for strict |
* conformance. |
*/ |
#define ARRAY_ELT( IM, i ) \ |
{ \ |
GLuint count = IM->Count; \ |
IM->Elt[count] = i; \ |
IM->Flag[count] &= IM->ArrayEltFlags; \ |
IM->Flag[count] |= VERT_BIT_ELT; \ |
IM->FlushElt = IM->ArrayEltFlush; \ |
IM->Count += IM->ArrayEltIncr; \ |
if (IM->Count == IMM_MAXDATA) \ |
_tnl_flush_immediate( NULL, IM ); \ |
} |
static void |
_tnl_ArrayElement( GLint i ) |
{ |
GET_IMMEDIATE; |
ARRAY_ELT( IM, i ); |
} |
/* Internal functions. These are safe to use providing either: |
* |
* - It is determined that a display list is not being compiled, or |
* if so that these commands won't be compiled into the list (see |
* t_eval.c for an example). |
* |
* - _tnl_hard_begin() is used instead of _tnl_[bB]egin, and tested |
* for a GL_TRUE return value. See _tnl_Rectf, below. |
*/ |
void |
_tnl_eval_coord1f( GLcontext *CC, GLfloat u ) |
{ |
struct immediate *i = TNL_CURRENT_IM(CC); |
EVALCOORD1( i, u ); |
} |
void |
_tnl_eval_coord2f( GLcontext *CC, GLfloat u, GLfloat v ) |
{ |
struct immediate *i = TNL_CURRENT_IM(CC); |
EVALCOORD2( i, u, v ); |
} |
/* |
* NV_vertex_program |
*/ |
static void |
_tnl_VertexAttrib4fNV( GLuint index, GLfloat x, GLfloat y, GLfloat z, GLfloat w ) |
{ |
if (index < 16) { |
GET_IMMEDIATE; |
const GLuint count = IM->Count; |
GLfloat *attrib = IM->Attrib[index][count]; |
ASSIGN_4V(attrib, x, y, z, w); |
IM->Flag[count] |= (1 << index); |
if (index == 0) { |
IM->Count++; |
if (count == IMM_MAXDATA - 1) |
_tnl_flush_immediate( NULL, IM ); |
} |
} |
else { |
GET_CURRENT_CONTEXT(ctx); |
_mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribNV(index > 15)"); |
} |
} |
static void |
_tnl_VertexAttrib4fvNV( GLuint index, const GLfloat *v ) |
{ |
if (index < 16) { |
GET_IMMEDIATE; |
const GLuint count = IM->Count; |
GLfloat *attrib = IM->Attrib[index][count]; |
COPY_4V(attrib, v); |
IM->Flag[count] |= (1 << index); |
if (index == 0) { |
IM->Count++; |
if (count == IMM_MAXDATA - 1) |
_tnl_flush_immediate( NULL, IM ); |
} |
} |
else { |
GET_CURRENT_CONTEXT(ctx); |
_mesa_error(ctx, GL_INVALID_VALUE, "glVertexAttribNV(index > 15)"); |
} |
} |
/* Execute a glRectf() function. _tnl_hard_begin() ensures the check |
* on outside_begin_end is executed even in compiled lists. These |
* vertices can now participate in the same immediate as regular ones, |
* even in most display lists. |
*/ |
static void |
_tnl_Rectf( GLfloat x1, GLfloat y1, GLfloat x2, GLfloat y2 ) |
{ |
GET_CURRENT_CONTEXT(ctx); |
if (_tnl_hard_begin( ctx, GL_QUADS )) { |
glVertex2f( x1, y1 ); |
glVertex2f( x2, y1 ); |
glVertex2f( x2, y2 ); |
glVertex2f( x1, y2 ); |
glEnd(); |
} |
} |
static void |
_tnl_Materialfv( GLenum face, GLenum pname, const GLfloat *params ) |
{ |
GET_CURRENT_CONTEXT(ctx); |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct immediate *IM = TNL_CURRENT_IM(ctx); |
GLuint count = IM->Count; |
struct gl_material *mat; |
GLuint bitmask = _mesa_material_bitmask(ctx, face, pname, ~0, "Materialfv"); |
if (bitmask == 0) |
return; |
if (MESA_VERBOSE & VERBOSE_API) |
_mesa_debug(ctx, "_tnl_Materialfv\n"); |
if (tnl->IsolateMaterials && |
!(IM->BeginState & VERT_BEGIN_1)) /* heuristic */ |
{ |
_tnl_flush_immediate( ctx, IM ); |
IM = TNL_CURRENT_IM(ctx); |
count = IM->Count; |
} |
if (!(IM->Flag[count] & VERT_BIT_MATERIAL)) { |
if (!IM->Material) { |
IM->Material = (struct gl_material (*)[2]) |
MALLOC( sizeof(struct gl_material) * IMM_SIZE * 2 ); |
IM->MaterialMask = (GLuint *) MALLOC( sizeof(GLuint) * IMM_SIZE ); |
IM->MaterialMask[IM->LastMaterial] = 0; |
} |
else if (IM->MaterialOrMask & ~bitmask) { |
_mesa_copy_material_pairs( IM->Material[count], |
IM->Material[IM->LastMaterial], |
IM->MaterialOrMask & ~bitmask ); |
} |
IM->Flag[count] |= VERT_BIT_MATERIAL; |
IM->MaterialMask[count] = 0; |
IM->MaterialAndMask &= IM->MaterialMask[IM->LastMaterial]; |
IM->LastMaterial = count; |
} |
IM->MaterialOrMask |= bitmask; |
IM->MaterialMask[count] |= bitmask; |
mat = IM->Material[count]; |
if (bitmask & FRONT_AMBIENT_BIT) { |
COPY_4FV( mat[0].Ambient, params ); |
} |
if (bitmask & BACK_AMBIENT_BIT) { |
COPY_4FV( mat[1].Ambient, params ); |
} |
if (bitmask & FRONT_DIFFUSE_BIT) { |
COPY_4FV( mat[0].Diffuse, params ); |
} |
if (bitmask & BACK_DIFFUSE_BIT) { |
COPY_4FV( mat[1].Diffuse, params ); |
} |
if (bitmask & FRONT_SPECULAR_BIT) { |
COPY_4FV( mat[0].Specular, params ); |
} |
if (bitmask & BACK_SPECULAR_BIT) { |
COPY_4FV( mat[1].Specular, params ); |
} |
if (bitmask & FRONT_EMISSION_BIT) { |
COPY_4FV( mat[0].Emission, params ); |
} |
if (bitmask & BACK_EMISSION_BIT) { |
COPY_4FV( mat[1].Emission, params ); |
} |
if (bitmask & FRONT_SHININESS_BIT) { |
GLfloat shininess = CLAMP( params[0], 0.0F, 128.0F ); |
mat[0].Shininess = shininess; |
} |
if (bitmask & BACK_SHININESS_BIT) { |
GLfloat shininess = CLAMP( params[0], 0.0F, 128.0F ); |
mat[1].Shininess = shininess; |
} |
if (bitmask & FRONT_INDEXES_BIT) { |
mat[0].AmbientIndex = params[0]; |
mat[0].DiffuseIndex = params[1]; |
mat[0].SpecularIndex = params[2]; |
} |
if (bitmask & BACK_INDEXES_BIT) { |
mat[1].AmbientIndex = params[0]; |
mat[1].DiffuseIndex = params[1]; |
mat[1].SpecularIndex = params[2]; |
} |
if (tnl->IsolateMaterials && |
!(IM->BeginState & VERT_BEGIN_1)) /* heuristic */ |
{ |
_tnl_flush_immediate( ctx, IM ); |
} |
} |
void _tnl_imm_vtxfmt_init( GLcontext *ctx ) |
{ |
GLvertexformat *vfmt = &(TNL_CONTEXT(ctx)->vtxfmt); |
/* All begin/end operations are handled by this vertex format: |
*/ |
vfmt->ArrayElement = _tnl_ArrayElement; |
vfmt->Begin = _tnl_Begin; |
vfmt->Color3f = _tnl_Color3f; |
vfmt->Color3fv = _tnl_Color3fv; |
vfmt->Color3ub = _tnl_Color3ub; |
vfmt->Color3ubv = _tnl_Color3ubv; |
vfmt->Color4f = _tnl_Color4f; |
vfmt->Color4fv = _tnl_Color4fv; |
vfmt->Color4ub = _tnl_Color4ub; |
vfmt->Color4ubv = _tnl_Color4ubv; |
vfmt->EdgeFlag = _tnl_EdgeFlag; |
vfmt->EdgeFlagv = _tnl_EdgeFlagv; |
vfmt->End = _tnl_End; |
vfmt->EvalCoord1f = _tnl_EvalCoord1f; |
vfmt->EvalCoord1fv = _tnl_EvalCoord1fv; |
vfmt->EvalCoord2f = _tnl_EvalCoord2f; |
vfmt->EvalCoord2fv = _tnl_EvalCoord2fv; |
vfmt->EvalPoint1 = _tnl_EvalPoint1; |
vfmt->EvalPoint2 = _tnl_EvalPoint2; |
vfmt->FogCoordfEXT = _tnl_FogCoordfEXT; |
vfmt->FogCoordfvEXT = _tnl_FogCoordfvEXT; |
vfmt->Indexi = _tnl_Indexi; |
vfmt->Indexiv = _tnl_Indexiv; |
vfmt->Materialfv = _tnl_Materialfv; |
vfmt->MultiTexCoord1fARB = _tnl_MultiTexCoord1fARB; |
vfmt->MultiTexCoord1fvARB = _tnl_MultiTexCoord1fvARB; |
vfmt->MultiTexCoord2fARB = _tnl_MultiTexCoord2fARB; |
vfmt->MultiTexCoord2fvARB = _tnl_MultiTexCoord2fvARB; |
vfmt->MultiTexCoord3fARB = _tnl_MultiTexCoord3fARB; |
vfmt->MultiTexCoord3fvARB = _tnl_MultiTexCoord3fvARB; |
vfmt->MultiTexCoord4fARB = _tnl_MultiTexCoord4fARB; |
vfmt->MultiTexCoord4fvARB = _tnl_MultiTexCoord4fvARB; |
vfmt->Normal3f = _tnl_Normal3f; |
vfmt->Normal3fv = _tnl_Normal3fv; |
vfmt->SecondaryColor3fEXT = _tnl_SecondaryColor3fEXT; |
vfmt->SecondaryColor3fvEXT = _tnl_SecondaryColor3fvEXT; |
vfmt->SecondaryColor3ubEXT = _tnl_SecondaryColor3ubEXT; |
vfmt->SecondaryColor3ubvEXT = _tnl_SecondaryColor3ubvEXT; |
vfmt->TexCoord1f = _tnl_TexCoord1f; |
vfmt->TexCoord1fv = _tnl_TexCoord1fv; |
vfmt->TexCoord2f = _tnl_TexCoord2f; |
vfmt->TexCoord2fv = _tnl_TexCoord2fv; |
vfmt->TexCoord3f = _tnl_TexCoord3f; |
vfmt->TexCoord3fv = _tnl_TexCoord3fv; |
vfmt->TexCoord4f = _tnl_TexCoord4f; |
vfmt->TexCoord4fv = _tnl_TexCoord4fv; |
vfmt->Vertex2f = _tnl_Vertex2f; |
vfmt->Vertex2fv = _tnl_Vertex2fv; |
vfmt->Vertex3f = _tnl_Vertex3f; |
vfmt->Vertex3fv = _tnl_Vertex3fv; |
vfmt->Vertex4f = _tnl_Vertex4f; |
vfmt->Vertex4fv = _tnl_Vertex4fv; |
vfmt->VertexAttrib4fNV = _tnl_VertexAttrib4fNV; |
vfmt->VertexAttrib4fvNV = _tnl_VertexAttrib4fvNV; |
/* Outside begin/end functions (from t_varray.c, t_eval.c, ...): |
*/ |
vfmt->Rectf = _tnl_Rectf; |
/* Just use the core function: |
*/ |
vfmt->CallList = _mesa_CallList; |
vfmt->prefer_float_colors = GL_FALSE; |
} |
/shark/trunk/ports/mesa/src/tnl/t_array_import.h |
---|
0,0 → 1,37 |
/* $Id: t_array_import.h,v 1.1 2003-02-28 11:48:06 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 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. |
*/ |
#ifndef _T_ARRAY_IMPORT_H |
#define _T_ARRAY_IMPORT_H |
#include "mtypes.h" |
#include "t_context.h" |
extern void _tnl_vb_bind_arrays( GLcontext *ctx, GLint start, GLsizei count ); |
extern void _tnl_array_import_init( GLcontext *ctx ); |
#endif |
/shark/trunk/ports/mesa/src/tnl/tnl.h |
---|
0,0 → 1,78 |
/* $Id: tnl.h,v 1.1 2003-02-28 11:48:08 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included |
* in all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
* |
* Authors: |
* Keith Whitwell <keith@tungstengraphics.com> |
*/ |
#ifndef _TNL_H |
#define _TNL_H |
#include "mtypes.h" |
/* These are the public-access functions exported from tnl. (A few |
* more are currently hooked into dispatch directly by the module |
* itself.) |
*/ |
extern GLboolean |
_tnl_CreateContext( GLcontext *ctx ); |
extern void |
_tnl_DestroyContext( GLcontext *ctx ); |
extern void |
_tnl_InvalidateState( GLcontext *ctx, GLuint new_state ); |
/* Functions to revive the tnl module after being unhooked from |
* dispatch and/or driver callbacks. |
*/ |
/* Restore just the ctx->Exec table: |
*/ |
extern void |
_tnl_wakeup_exec( GLcontext *ctx ); |
/* Restore both ctx->Exec and ctx->Save: |
*/ |
extern void |
_tnl_wakeup_save_exec( GLcontext *ctx ); |
/* Driver configuration options: |
*/ |
extern void |
_tnl_need_projected_coords( GLcontext *ctx, GLboolean flag ); |
extern void |
_tnl_need_dlist_loopback( GLcontext *ctx, GLboolean flag ); |
extern void |
_tnl_need_dlist_norm_lengths( GLcontext *ctx, GLboolean flag ); |
extern void |
_tnl_isolate_materials( GLcontext *ctx, GLboolean flag ); |
#endif |
/shark/trunk/ports/mesa/src/tnl/t_vtx_api.h |
---|
0,0 → 1,234 |
/* $XFree86$ */ |
/************************************************************************** |
Copyright 2002 Tungsten Graphics Inc., Cedar Park, Texas. |
All Rights Reserved. |
Permission is hereby granted, free of charge, to any person obtaining a |
copy of this software and associated documentation files (the "Software"), |
to deal in the Software without restriction, including without limitation |
on the rights to use, copy, modify, merge, publish, distribute, sub |
license, and/or sell copies of the Software, and to permit persons to whom |
the Software is furnished to do so, subject to the following conditions: |
The above copyright notice and this permission notice (including the next |
paragraph) shall be included in all copies or substantial portions of the |
Software. |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL |
TUNGSTEN GRAPHICS AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, |
DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE |
USE OR OTHER DEALINGS IN THE SOFTWARE. |
**************************************************************************/ |
/* |
* Authors: |
* Keith Whitwell <keith@tungstengraphics.com> |
* |
*/ |
#ifndef __RADEON_VTXFMT_H__ |
#define __RADEON_VTXFMT_H__ |
#ifdef GLX_DIRECT_RENDERING |
#include "_tnl__context.h" |
extern void _tnl_UpdateVtxfmt( GLcontext *ctx ); |
extern void _tnl_InitVtxfmt( GLcontext *ctx ); |
extern void _tnl_InvalidateVtxfmt( GLcontext *ctx ); |
extern void _tnl_DestroyVtxfmt( GLcontext *ctx ); |
typedef void (*p4f)( GLfloat, GLfloat, GLfloat, GLfloat ); |
typedef void (*p3f)( GLfloat, GLfloat, GLfloat ); |
typedef void (*p2f)( GLfloat, GLfloat ); |
typedef void (*p1f)( GLfloat ); |
typedef void (*pe2f)( GLenum, GLfloat, GLfloat ); |
typedef void (*pe1f)( GLenum, GLfloat ); |
typedef void (*p4ub)( GLubyte, GLubyte, GLubyte, GLubyte ); |
typedef void (*p3ub)( GLubyte, GLubyte, GLubyte ); |
typedef void (*pfv)( const GLfloat * ); |
typedef void (*pefv)( GLenum, const GLfloat * ); |
typedef void (*pubv)( const GLubyte * ); |
/* Want to keep a cache of these around. Each is parameterized by |
* only a single value which has only a small range. Only expect a |
* few, so just rescan the list each time? |
*/ |
struct dynfn { |
struct dynfn *next, *prev; |
int key; |
char *code; |
}; |
struct dfn_lists { |
struct dynfn Vertex2f; |
struct dynfn Vertex2fv; |
struct dynfn Vertex3f; |
struct dynfn Vertex3fv; |
struct dynfn Color4ub; |
struct dynfn Color4ubv; |
struct dynfn Color3ub; |
struct dynfn Color3ubv; |
struct dynfn Color4f; |
struct dynfn Color4fv; |
struct dynfn Color3f; |
struct dynfn Color3fv; |
struct dynfn SecondaryColor3ubEXT; |
struct dynfn SecondaryColor3ubvEXT; |
struct dynfn SecondaryColor3fEXT; |
struct dynfn SecondaryColor3fvEXT; |
struct dynfn Normal3f; |
struct dynfn Normal3fv; |
struct dynfn TexCoord2f; |
struct dynfn TexCoord2fv; |
struct dynfn TexCoord1f; |
struct dynfn TexCoord1fv; |
struct dynfn MultiTexCoord2fARB; |
struct dynfn MultiTexCoord2fvARB; |
struct dynfn MultiTexCoord1fARB; |
struct dynfn MultiTexCoord1fvARB; |
}; |
struct _vb; |
struct dfn_generators { |
struct dynfn *(*Vertex2f)( struct _vb *, int ); |
struct dynfn *(*Vertex2fv)( struct _vb *, int ); |
struct dynfn *(*Vertex3f)( struct _vb *, int ); |
struct dynfn *(*Vertex3fv)( struct _vb *, int ); |
struct dynfn *(*Color4ub)( struct _vb *, int ); |
struct dynfn *(*Color4ubv)( struct _vb *, int ); |
struct dynfn *(*Color3ub)( struct _vb *, int ); |
struct dynfn *(*Color3ubv)( struct _vb *, int ); |
struct dynfn *(*Color4f)( struct _vb *, int ); |
struct dynfn *(*Color4fv)( struct _vb *, int ); |
struct dynfn *(*Color3f)( struct _vb *, int ); |
struct dynfn *(*Color3fv)( struct _vb *, int ); |
struct dynfn *(*SecondaryColor3ubEXT)( struct _vb *, int ); |
struct dynfn *(*SecondaryColor3ubvEXT)( struct _vb *, int ); |
struct dynfn *(*SecondaryColor3fEXT)( struct _vb *, int ); |
struct dynfn *(*SecondaryColor3fvEXT)( struct _vb *, int ); |
struct dynfn *(*Normal3f)( struct _vb *, int ); |
struct dynfn *(*Normal3fv)( struct _vb *, int ); |
struct dynfn *(*TexCoord2f)( struct _vb *, int ); |
struct dynfn *(*TexCoord2fv)( struct _vb *, int ); |
struct dynfn *(*TexCoord1f)( struct _vb *, int ); |
struct dynfn *(*TexCoord1fv)( struct _vb *, int ); |
struct dynfn *(*MultiTexCoord2fARB)( struct _vb *, int ); |
struct dynfn *(*MultiTexCoord2fvARB)( struct _vb *, int ); |
struct dynfn *(*MultiTexCoord1fARB)( struct _vb *, int ); |
struct dynfn *(*MultiTexCoord1fvARB)( struct _vb *, int ); |
}; |
struct prim { |
GLuint start; |
GLuint end; |
GLuint prim; |
}; |
#define _TNL__MAX_PRIMS 64 |
struct tnl_vbinfo { |
/* Keep these first: referenced from codegen templates: |
*/ |
GLint counter; |
GLint *dmaptr; |
void (*notify)( void ); |
union { float f; int i; GLubyte ub4[4]; } vertex[16*4]; |
GLfloat *attrptr[16]; |
GLuint size[16]; |
GLenum *prim; /* &ctx->Driver.CurrentExecPrimitive */ |
GLuint primflags; |
GLboolean installed; |
GLboolean recheck; |
GLint vertex_size; |
GLint initial_counter; |
GLint nrverts; |
GLuint vertex_format; |
GLuint installed_vertex_format; |
struct prim primlist[RADEON_MAX_PRIMS]; |
int nrprims; |
struct dfn_lists dfn_cache; |
struct dfn_generators codegen; |
GLvertexformat vtxfmt; |
}; |
extern void _tnl_InitVtxfmtChoosers( GLvertexformat *vfmt ); |
#define FIXUP( CODE, OFFSET, CHECKVAL, NEWVAL ) \ |
do { \ |
int *icode = (int *)(CODE+OFFSET); \ |
assert (*icode == CHECKVAL); \ |
*icode = (int)NEWVAL; \ |
} while (0) |
/* Useful for figuring out the offsets: |
*/ |
#define FIXUP2( CODE, OFFSET, CHECKVAL, NEWVAL ) \ |
do { \ |
while (*(int *)(CODE+OFFSET) != CHECKVAL) OFFSET++; \ |
fprintf(stderr, "%s/%d CVAL %x OFFSET %d\n", __FUNCTION__, \ |
__LINE__, CHECKVAL, OFFSET); \ |
*(int *)(CODE+OFFSET) = (int)NEWVAL; \ |
OFFSET += 4; \ |
} while (0) |
/* |
*/ |
void _tnl_InitCodegen( struct dfn_generators *gen ); |
void _tnl_InitX86Codegen( struct dfn_generators *gen ); |
void _tnl_InitSSECodegen( struct dfn_generators *gen ); |
void _tnl_copy_to_current( GLcontext *ctx ); |
/* Defined in tnl_vtxfmt_c.c. |
*/ |
struct dynfn *tnl_makeX86Vertex2f( TNLcontext *, int ); |
struct dynfn *tnl_makeX86Vertex2fv( TNLcontext *, int ); |
struct dynfn *tnl_makeX86Vertex3f( TNLcontext *, int ); |
struct dynfn *tnl_makeX86Vertex3fv( TNLcontext *, int ); |
struct dynfn *tnl_makeX86Color4ub( TNLcontext *, int ); |
struct dynfn *tnl_makeX86Color4ubv( TNLcontext *, int ); |
struct dynfn *tnl_makeX86Color3ub( TNLcontext *, int ); |
struct dynfn *tnl_makeX86Color3ubv( TNLcontext *, int ); |
struct dynfn *tnl_makeX86Color4f( TNLcontext *, int ); |
struct dynfn *tnl_makeX86Color4fv( TNLcontext *, int ); |
struct dynfn *tnl_makeX86Color3f( TNLcontext *, int ); |
struct dynfn *tnl_makeX86Color3fv( TNLcontext *, int ); |
struct dynfn *tnl_makeX86SecondaryColor3ubEXT( TNLcontext *, int ); |
struct dynfn *tnl_makeX86SecondaryColor3ubvEXT( TNLcontext *, int ); |
struct dynfn *tnl_makeX86SecondaryColor3fEXT( TNLcontext *, int ); |
struct dynfn *tnl_makeX86SecondaryColor3fvEXT( TNLcontext *, int ); |
struct dynfn *tnl_makeX86Normal3f( TNLcontext *, int ); |
struct dynfn *tnl_makeX86Normal3fv( TNLcontext *, int ); |
struct dynfn *tnl_makeX86TexCoord2f( TNLcontext *, int ); |
struct dynfn *tnl_makeX86TexCoord2fv( TNLcontext *, int ); |
struct dynfn *tnl_makeX86TexCoord1f( TNLcontext *, int ); |
struct dynfn *tnl_makeX86TexCoord1fv( TNLcontext *, int ); |
struct dynfn *tnl_makeX86MultiTexCoord2fARB( TNLcontext *, int ); |
struct dynfn *tnl_makeX86MultiTexCoord2fvARB( TNLcontext *, int ); |
struct dynfn *tnl_makeX86MultiTexCoord1fARB( TNLcontext *, int ); |
struct dynfn *tnl_makeX86MultiTexCoord1fvARB( TNLcontext *, int ); |
#endif |
#endif |
/shark/trunk/ports/mesa/src/tnl/t_imm_api.h |
---|
0,0 → 1,57 |
/* $Id: t_imm_api.h,v 1.1 2003-02-28 11:48:06 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 4.1 |
* |
* Copyright (C) 1999-2001 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. |
*/ |
#ifndef _T_VTXFMT_H |
#define _T_VTXFMT_H |
#include "mtypes.h" |
#include "t_context.h" |
extern void _tnl_save_Begin( GLenum mode ); |
extern void _tnl_Begin( GLenum mode ); |
extern void _tnl_Begin( GLenum mode ); |
extern void _tnl_End(void); |
/* TNL-private internal functions for building higher-level operations: |
*/ |
extern GLboolean _tnl_hard_begin( GLcontext *ctx, GLenum p ); |
extern void _tnl_end( GLcontext *ctx ); |
extern void _tnl_vertex2f( GLcontext *ctx, GLfloat x, GLfloat y ); |
extern void _tnl_eval_coord1f( GLcontext *CC, GLfloat u ); |
extern void _tnl_eval_coord2f( GLcontext *CC, GLfloat u, GLfloat v ); |
extern void _tnl_array_element( GLcontext *CC, GLint i ); |
/* Initialize our part of the vtxfmt struct: |
*/ |
extern void _tnl_imm_vtxfmt_init( GLcontext *ctx ); |
#endif |
/shark/trunk/ports/mesa/src/tnl/t_imm_dlist.c |
---|
0,0 → 1,656 |
/* $Id: t_imm_dlist.c,v 1.1 2003-02-28 11:48:06 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 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 "context.h" |
#include "dlist.h" |
#include "debug.h" |
#include "mmath.h" |
#include "imports.h" |
#include "state.h" |
#include "t_context.h" |
#include "t_imm_api.h" |
#include "t_imm_elt.h" |
#include "t_imm_alloc.h" |
#include "t_imm_dlist.h" |
#include "t_imm_debug.h" |
#include "t_imm_exec.h" |
#include "t_imm_fixup.h" |
#include "t_pipeline.h" |
typedef struct { |
struct immediate *IM; |
GLuint Start; |
GLuint Count; |
GLuint BeginState; |
GLuint SavedBeginState; |
GLuint OrFlag; |
GLuint AndFlag; |
GLuint TexSize; |
GLuint LastData; |
GLuint LastPrimitive; |
GLuint LastMaterial; |
GLuint MaterialOrMask; |
GLuint MaterialAndMask; |
} TNLvertexcassette; |
static void execute_compiled_cassette( GLcontext *ctx, void *data ); |
static void loopback_compiled_cassette( GLcontext *ctx, struct immediate *IM ); |
static void build_normal_lengths( struct immediate *IM ) |
{ |
GLuint i; |
GLfloat len; |
GLfloat (*data)[4] = IM->Attrib[VERT_ATTRIB_NORMAL] + IM->Start; |
GLfloat *dest = IM->NormalLengthPtr; |
GLuint *flags = IM->Flag + IM->Start; |
GLuint count = IM->Count - IM->Start; |
if (!dest) { |
dest = IM->NormalLengthPtr = (GLfloat *) ALIGN_MALLOC( IMM_SIZE*sizeof(GLfloat), 32 ); |
if (!dest) return; |
} |
dest += IM->Start; |
len = (GLfloat) LEN_3FV( data[0] ); |
if (len > 0.0F) len = 1.0F / len; |
for (i = 0 ; i < count ; ) { |
dest[i] = len; |
if (flags[++i] & VERT_BIT_NORMAL) { |
len = (GLfloat) LEN_3FV( data[i] ); |
if (len > 0.0F) len = 1.0F / len; |
} |
} |
} |
static void fixup_normal_lengths( struct immediate *IM ) |
{ |
GLuint i; |
GLfloat len = 1.0F; /* just to silence warnings */ |
GLfloat (*data)[4] = IM->Attrib[VERT_ATTRIB_NORMAL]; |
GLfloat *dest = IM->NormalLengthPtr; |
GLuint *flags = IM->Flag; |
for (i = IM->CopyStart ; i <= IM->Start ; i++) { |
len = (GLfloat) LEN_3FV( data[i] ); |
if (len > 0.0F) len = 1.0F / len; |
dest[i] = len; |
} |
if (i < IM->Count) { |
while (!(flags[i] & (VERT_BIT_NORMAL|VERT_BIT_END_VB))) { |
dest[i] = len; |
i++; |
} |
} |
} |
/* Insert the active immediate struct onto the display list currently |
* being built. |
*/ |
void |
_tnl_compile_cassette( GLcontext *ctx, struct immediate *IM ) |
{ |
struct immediate *im = TNL_CURRENT_IM(ctx); |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
TNLvertexcassette *node; |
GLuint new_beginstate; |
if (MESA_VERBOSE & VERBOSE_DISPLAY_LIST) |
_mesa_debug(ctx, "_tnl_compiled_cassette IM: %d\n", IM->id); |
if (IM->FlushElt) { |
ASSERT (IM->FlushElt == FLUSH_ELT_LAZY); |
_tnl_translate_array_elts( ctx, IM, IM->Start, IM->Count ); |
} |
_tnl_compute_orflag( IM, IM->Start ); |
/* Need to clear this flag, or fixup gets confused. (The |
* array-elements have been translated away by now, so it's ok to |
* remove it.) |
*/ |
IM->OrFlag &= ~VERT_BIT_ELT; |
IM->AndFlag &= ~VERT_BIT_ELT; |
_tnl_fixup_input( ctx, IM ); |
node = (TNLvertexcassette *) |
_mesa_alloc_instruction(ctx, |
tnl->opcode_vertex_cassette, |
sizeof(TNLvertexcassette)); |
if (!node) |
return; |
node->IM = im; im->ref_count++; |
node->Start = im->Start; |
node->Count = im->Count; |
node->BeginState = im->BeginState; |
node->SavedBeginState = im->SavedBeginState; |
node->OrFlag = im->OrFlag; |
node->TexSize = im->TexSize; |
node->AndFlag = im->AndFlag; |
node->LastData = im->LastData; |
node->LastPrimitive = im->LastPrimitive; |
node->LastMaterial = im->LastMaterial; |
node->MaterialOrMask = im->MaterialOrMask; |
node->MaterialAndMask = im->MaterialAndMask; |
if (tnl->CalcDListNormalLengths) { |
build_normal_lengths( im ); |
} |
if (ctx->ExecuteFlag) { |
execute_compiled_cassette( ctx, (void *)node ); |
} |
/* Discard any errors raised in the last cassette. |
*/ |
new_beginstate = node->BeginState & (VERT_BEGIN_0|VERT_BEGIN_1); |
/* Decide whether this immediate struct is full, or can be used for |
* the next batch of vertices as well. |
*/ |
if (im->Count > IMM_MAXDATA - 16) { |
/* Call it full... |
*/ |
struct immediate *new_im = _tnl_alloc_immediate(ctx); |
new_im->ref_count++; |
im->ref_count--; /* remove CURRENT_IM reference */ |
ASSERT(im->ref_count > 0); /* it is compiled into a display list */ |
SET_IMMEDIATE( ctx, new_im ); |
_tnl_reset_compile_input( ctx, IMM_MAX_COPIED_VERTS, |
new_beginstate, node->SavedBeginState ); |
} else { |
/* Still some room in the current immediate. |
*/ |
_tnl_reset_compile_input( ctx, im->Count+1+IMM_MAX_COPIED_VERTS, |
new_beginstate, node->SavedBeginState); |
} |
} |
static void fixup_compiled_primitives( GLcontext *ctx, struct immediate *IM ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
/* Can potentially overwrite primitive details - need to save the |
* first slot: |
*/ |
tnl->DlistPrimitive = IM->Primitive[IM->Start]; |
tnl->DlistPrimitiveLength = IM->PrimitiveLength[IM->Start]; |
tnl->DlistLastPrimitive = IM->LastPrimitive; |
/* The first primitive may be different from what was recorded in |
* the immediate struct. Consider an immediate that starts with a |
* glBegin, compiled in a display list, which is called from within |
* an existing Begin/End object. |
*/ |
if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) { |
GLuint i; |
if (IM->BeginState & VERT_ERROR_1) |
_mesa_error( ctx, GL_INVALID_OPERATION, "glBegin/glEnd"); |
for (i = IM->Start ; i <= IM->Count ; i += IM->PrimitiveLength[i]) |
if (IM->Flag[i] & (VERT_BIT_BEGIN|VERT_BIT_END_VB)) |
break; |
/* Would like to just ignore vertices upto this point. Can't |
* set copystart because it might skip materials? |
*/ |
ASSERT(IM->Start == IM->CopyStart); |
if (i > IM->CopyStart || !(IM->Flag[IM->Start] & VERT_BIT_BEGIN)) { |
IM->Primitive[IM->CopyStart] = GL_POLYGON+1; |
IM->PrimitiveLength[IM->CopyStart] = i - IM->CopyStart; |
if (IM->Flag[i] & VERT_BIT_END_VB) { |
IM->Primitive[IM->CopyStart] |= PRIM_LAST; |
IM->LastPrimitive = IM->CopyStart; |
} |
} |
} else { |
GLuint i; |
if (IM->BeginState & VERT_ERROR_0) |
_mesa_error( ctx, GL_INVALID_OPERATION, "glBegin/glEnd"); |
if (IM->CopyStart == IM->Start && |
IM->Flag[IM->Start] & (VERT_BIT_END | VERT_BIT_END_VB)) |
{ |
} |
else |
{ |
IM->Primitive[IM->CopyStart] = ctx->Driver.CurrentExecPrimitive; |
if (tnl->ExecParity) |
IM->Primitive[IM->CopyStart] |= PRIM_PARITY; |
/* one of these should be true, else we'll be in an infinite loop |
*/ |
ASSERT(IM->PrimitiveLength[IM->Start] > 0 || |
IM->Flag[IM->Start] & (VERT_BIT_END | VERT_BIT_END_VB)); |
for (i = IM->Start ; i <= IM->Count ; i += IM->PrimitiveLength[i]) |
if (IM->Flag[i] & (VERT_BIT_END | VERT_BIT_END_VB)) { |
IM->PrimitiveLength[IM->CopyStart] = i - IM->CopyStart; |
if (IM->Flag[i] & VERT_BIT_END_VB) { |
IM->Primitive[IM->CopyStart] |= PRIM_LAST; |
IM->LastPrimitive = IM->CopyStart; |
} |
if (IM->Flag[i] & VERT_BIT_END) { |
IM->Primitive[IM->CopyStart] |= PRIM_END; |
} |
break; |
} |
} |
} |
} |
/* Undo any changes potentially made to the immediate in the range |
* IM->Start..IM->Count above. |
*/ |
static void restore_compiled_primitives( GLcontext *ctx, struct immediate *IM ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
IM->Primitive[IM->Start] = tnl->DlistPrimitive; |
IM->PrimitiveLength[IM->Start] = tnl->DlistPrimitiveLength; |
} |
static void |
execute_compiled_cassette( GLcontext *ctx, void *data ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
TNLvertexcassette *node = (TNLvertexcassette *)data; |
struct immediate *IM = node->IM; |
/* _mesa_debug("%s\n", __FUNCTION__); */ |
IM->Start = node->Start; |
IM->CopyStart = node->Start; |
IM->Count = node->Count; |
IM->BeginState = node->BeginState; |
IM->SavedBeginState = node->SavedBeginState; |
IM->OrFlag = node->OrFlag; |
IM->TexSize = node->TexSize; |
IM->AndFlag = node->AndFlag; |
IM->LastData = node->LastData; |
IM->LastPrimitive = node->LastPrimitive; |
IM->LastMaterial = node->LastMaterial; |
IM->MaterialOrMask = node->MaterialOrMask; |
IM->MaterialAndMask = node->MaterialAndMask; |
if ((MESA_VERBOSE & VERBOSE_DISPLAY_LIST) && |
(MESA_VERBOSE & VERBOSE_IMMEDIATE)) |
_tnl_print_cassette( IM ); |
if (MESA_VERBOSE & VERBOSE_DISPLAY_LIST) { |
_mesa_debug(ctx, "Run cassette %d, rows %d..%d, beginstate %x ", |
IM->id, IM->Start, IM->Count, IM->BeginState); |
_tnl_print_vert_flags("orflag", IM->OrFlag); |
} |
/* Need to respect 'HardBeginEnd' even if the commands are looped |
* back to a driver tnl module. |
*/ |
if (IM->SavedBeginState) { |
if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) |
tnl->ReplayHardBeginEnd = 1; |
if (!tnl->ReplayHardBeginEnd) { |
/* This is a user error. Whatever operation (like glRectf) |
* decomposed to this hard begin/end pair is now being run |
* inside a begin/end object -- illegally. Reject it and |
* raise an error. |
*/ |
_mesa_error(ctx, GL_INVALID_OPERATION, "hard replay"); |
return; |
} |
} |
if (tnl->LoopbackDListCassettes) { |
/* (tnl->IsolateMaterials && (IM->OrFlag & VERT_MATERIAL)) ) { */ |
fixup_compiled_primitives( ctx, IM ); |
loopback_compiled_cassette( ctx, IM ); |
restore_compiled_primitives( ctx, IM ); |
} |
else { |
if (ctx->NewState) |
_mesa_update_state(ctx); |
if (tnl->pipeline.build_state_changes) |
_tnl_validate_pipeline( ctx ); |
_tnl_fixup_compiled_cassette( ctx, IM ); |
fixup_compiled_primitives( ctx, IM ); |
if (IM->Primitive[IM->LastPrimitive] & PRIM_END) |
ctx->Driver.CurrentExecPrimitive = GL_POLYGON+1; |
else if ((IM->Primitive[IM->LastPrimitive] & PRIM_BEGIN) || |
(IM->Primitive[IM->LastPrimitive] & PRIM_MODE_MASK) == |
PRIM_OUTSIDE_BEGIN_END) { |
ctx->Driver.CurrentExecPrimitive = |
IM->Primitive[IM->LastPrimitive] & PRIM_MODE_MASK; |
} |
_tnl_get_exec_copy_verts( ctx, IM ); |
if (IM->NormalLengthPtr) |
fixup_normal_lengths( IM ); |
if (IM->Count == IM->Start) |
_tnl_copy_to_current( ctx, IM, IM->OrFlag, IM->LastData ); |
else { |
/* _tnl_print_cassette( IM ); */ |
_tnl_run_cassette( ctx, IM ); |
} |
restore_compiled_primitives( ctx, IM ); |
} |
if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) |
tnl->ReplayHardBeginEnd = 0; |
} |
static void |
destroy_compiled_cassette( GLcontext *ctx, void *data ) |
{ |
TNLvertexcassette *node = (TNLvertexcassette *)data; |
if ( --node->IM->ref_count == 0 ) |
_tnl_free_immediate( ctx, node->IM ); |
} |
static void |
print_compiled_cassette( GLcontext *ctx, void *data ) |
{ |
TNLvertexcassette *node = (TNLvertexcassette *)data; |
struct immediate *IM = node->IM; |
_mesa_debug(ctx, "TNL-VERTEX-CASSETTE, id %u, rows %u..%u\n", |
node->IM->id, node->Start, node->Count); |
IM->Start = node->Start; |
IM->CopyStart = node->Start; |
IM->Count = node->Count; |
IM->BeginState = node->BeginState; |
IM->OrFlag = node->OrFlag; |
IM->TexSize = node->TexSize; |
IM->AndFlag = node->AndFlag; |
IM->LastData = node->LastData; |
IM->LastPrimitive = node->LastPrimitive; |
IM->LastMaterial = node->LastMaterial; |
IM->MaterialOrMask = node->MaterialOrMask; |
IM->MaterialAndMask = node->MaterialAndMask; |
_tnl_print_cassette( node->IM ); |
} |
void |
_tnl_BeginCallList( GLcontext *ctx, GLuint list ) |
{ |
(void) ctx; |
(void) list; |
FLUSH_CURRENT(ctx, 0); |
} |
/* Called at the tail of a CallList. Make current immediate aware of |
* any new to-be-copied vertices. |
*/ |
void |
_tnl_EndCallList( GLcontext *ctx ) |
{ |
GLuint beginstate = 0; |
if (ctx->Driver.CurrentExecPrimitive != PRIM_OUTSIDE_BEGIN_END) |
beginstate = VERT_BEGIN_0|VERT_BEGIN_1; |
_tnl_reset_exec_input( ctx, TNL_CURRENT_IM(ctx)->Start, beginstate, 0 ); |
} |
void |
_tnl_EndList( GLcontext *ctx ) |
{ |
struct immediate *IM = TNL_CURRENT_IM(ctx); |
ctx->swtnl_im = 0; |
IM->ref_count--; |
/* outside begin/end, even in COMPILE_AND_EXEC, |
* so no vertices to copy, right? |
*/ |
ASSERT(TNL_CONTEXT(ctx)->ExecCopyCount == 0); |
/* If this one isn't free, get a clean one. (Otherwise we'll be |
* using one that's already half full). |
*/ |
if (IM->ref_count != 0) |
IM = _tnl_alloc_immediate( ctx ); |
ASSERT(IM->ref_count == 0); |
SET_IMMEDIATE( ctx, IM ); |
IM->ref_count++; |
_tnl_reset_exec_input( ctx, IMM_MAX_COPIED_VERTS, 0, 0 ); |
} |
void |
_tnl_NewList( GLcontext *ctx, GLuint list, GLenum mode ) |
{ |
struct immediate *IM = TNL_CURRENT_IM(ctx); |
/* Use the installed immediate struct. No vertices in the current |
* immediate, no copied vertices in the system. |
*/ |
ASSERT(TNL_CURRENT_IM(ctx)); |
ASSERT(TNL_CURRENT_IM(ctx)->Start == IMM_MAX_COPIED_VERTS); |
ASSERT(TNL_CURRENT_IM(ctx)->Start == TNL_CURRENT_IM(ctx)->Count); |
ASSERT(TNL_CONTEXT(ctx)->ExecCopyCount == 0); |
/* Set current Begin/End state to unknown: |
*/ |
IM->BeginState = VERT_BEGIN_0; |
ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN; |
} |
void |
_tnl_dlist_init( GLcontext *ctx ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
tnl->opcode_vertex_cassette = |
_mesa_alloc_opcode( ctx, |
sizeof(TNLvertexcassette), |
execute_compiled_cassette, |
destroy_compiled_cassette, |
print_compiled_cassette ); |
} |
static void emit_material( struct gl_material *src, GLuint bitmask ) |
{ |
if (bitmask & FRONT_EMISSION_BIT) |
glMaterialfv( GL_FRONT, GL_EMISSION, src[0].Emission ); |
if (bitmask & BACK_EMISSION_BIT) |
glMaterialfv( GL_BACK, GL_EMISSION, src[1].Emission ); |
if (bitmask & FRONT_AMBIENT_BIT) |
glMaterialfv( GL_FRONT, GL_AMBIENT, src[0].Ambient ); |
if (bitmask & BACK_AMBIENT_BIT) |
glMaterialfv( GL_BACK, GL_AMBIENT, src[1].Ambient ); |
if (bitmask & FRONT_DIFFUSE_BIT) |
glMaterialfv( GL_FRONT, GL_DIFFUSE, src[0].Diffuse ); |
if (bitmask & BACK_DIFFUSE_BIT) |
glMaterialfv( GL_BACK, GL_DIFFUSE, src[1].Diffuse ); |
if (bitmask & FRONT_SPECULAR_BIT) |
glMaterialfv( GL_FRONT, GL_SPECULAR, src[0].Specular ); |
if (bitmask & BACK_SPECULAR_BIT) |
glMaterialfv( GL_BACK, GL_SPECULAR, src[1].Specular ); |
if (bitmask & FRONT_SHININESS_BIT) |
glMaterialfv( GL_FRONT, GL_SHININESS, &src[0].Shininess ); |
if (bitmask & BACK_SHININESS_BIT) |
glMaterialfv( GL_BACK, GL_SHININESS, &src[1].Shininess ); |
if (bitmask & FRONT_INDEXES_BIT) { |
GLfloat ind[3]; |
ind[0] = src[0].AmbientIndex; |
ind[1] = src[0].DiffuseIndex; |
ind[2] = src[0].SpecularIndex; |
glMaterialfv( GL_FRONT, GL_COLOR_INDEXES, ind ); |
} |
if (bitmask & BACK_INDEXES_BIT) { |
GLfloat ind[3]; |
ind[0] = src[1].AmbientIndex; |
ind[1] = src[1].DiffuseIndex; |
ind[2] = src[1].SpecularIndex; |
glMaterialfv( GL_BACK, GL_COLOR_INDEXES, ind ); |
} |
} |
/* Low-performance helper function to allow driver-supplied tnl |
* modules to process tnl display lists. This is primarily supplied |
* to avoid fallbacks if CallList is invoked inside a Begin/End pair. |
* For higher performance, drivers should fallback to tnl (if outside |
* begin/end), or (for tnl hardware) implement their own display list |
* mechanism. |
*/ |
static void loopback_compiled_cassette( GLcontext *ctx, struct immediate *IM ) |
{ |
GLuint i; |
GLuint *flags = IM->Flag; |
GLuint orflag = IM->OrFlag; |
GLuint j; |
void (GLAPIENTRY *vertex)( const GLfloat * ); |
void (GLAPIENTRY *texcoordfv[MAX_TEXTURE_UNITS])( GLenum, const GLfloat * ); |
GLuint maxtex = 0; |
GLuint p, length, prim = 0; |
if (orflag & VERT_BITS_OBJ_234) |
vertex = (void (GLAPIENTRY *)(const GLfloat *)) glVertex4fv; |
else |
vertex = (void (GLAPIENTRY *)(const GLfloat *)) glVertex3fv; |
if (orflag & VERT_BITS_TEX_ANY) { |
for (j = 0 ; j < ctx->Const.MaxTextureUnits ; j++) { |
if (orflag & VERT_BIT_TEX(j)) { |
maxtex = j+1; |
if ((IM->TexSize & TEX_SIZE_4(j)) == TEX_SIZE_4(j)) |
texcoordfv[j] = glMultiTexCoord4fvARB; |
else if (IM->TexSize & TEX_SIZE_3(j)) |
texcoordfv[j] = glMultiTexCoord3fvARB; |
else |
texcoordfv[j] = glMultiTexCoord2fvARB; |
} |
} |
} |
for (p = IM->Start ; !(prim & PRIM_LAST) ; p += length) |
{ |
prim = IM->Primitive[p]; |
length= IM->PrimitiveLength[p]; |
ASSERT(length || (prim & PRIM_LAST)); |
ASSERT((prim & PRIM_MODE_MASK) <= GL_POLYGON+1); |
if (prim & PRIM_BEGIN) { |
glBegin(prim & PRIM_MODE_MASK); |
} |
for ( i = p ; i <= p+length ; i++) { |
if (flags[i] & VERT_BITS_TEX_ANY) { |
GLuint k; |
for (k = 0 ; k < maxtex ; k++) { |
if (flags[i] & VERT_BIT_TEX(k)) { |
texcoordfv[k]( GL_TEXTURE0_ARB + k, |
IM->Attrib[VERT_ATTRIB_TEX0 + k][i] ); |
} |
} |
} |
if (flags[i] & VERT_BIT_NORMAL) |
glNormal3fv(IM->Attrib[VERT_ATTRIB_NORMAL][i]); |
if (flags[i] & VERT_BIT_COLOR0) |
glColor4fv( IM->Attrib[VERT_ATTRIB_COLOR0][i] ); |
if (flags[i] & VERT_BIT_COLOR1) |
_glapi_Dispatch->SecondaryColor3fvEXT( IM->Attrib[VERT_ATTRIB_COLOR1][i] ); |
if (flags[i] & VERT_BIT_FOG) |
_glapi_Dispatch->FogCoordfEXT( IM->Attrib[VERT_ATTRIB_FOG][i][0] ); |
if (flags[i] & VERT_BIT_INDEX) |
glIndexi( IM->Index[i] ); |
if (flags[i] & VERT_BIT_EDGEFLAG) |
glEdgeFlag( IM->EdgeFlag[i] ); |
if (flags[i] & VERT_BIT_MATERIAL) |
emit_material( IM->Material[i], IM->MaterialMask[i] ); |
if (flags[i]&VERT_BITS_OBJ_234) |
vertex( IM->Attrib[VERT_ATTRIB_POS][i] ); |
else if (flags[i] & VERT_BIT_EVAL_C1) |
glEvalCoord1f( IM->Attrib[VERT_ATTRIB_POS][i][0] ); |
else if (flags[i] & VERT_BIT_EVAL_P1) |
glEvalPoint1( (GLint) IM->Attrib[VERT_ATTRIB_POS][i][0] ); |
else if (flags[i] & VERT_BIT_EVAL_C2) |
glEvalCoord2f( IM->Attrib[VERT_ATTRIB_POS][i][0], |
IM->Attrib[VERT_ATTRIB_POS][i][1] ); |
else if (flags[i] & VERT_BIT_EVAL_P2) |
glEvalPoint2( (GLint) IM->Attrib[VERT_ATTRIB_POS][i][0], |
(GLint) IM->Attrib[VERT_ATTRIB_POS][i][1] ); |
} |
if (prim & PRIM_END) { |
glEnd(); |
} |
} |
} |
/shark/trunk/ports/mesa/src/tnl/t_vb_texgen.c |
---|
0,0 → 1,692 |
/* $Id: t_vb_texgen.c,v 1.1 2003-02-28 11:48:08 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included |
* in all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
* |
* Authors: |
* Brian Paul |
* Keith Whitwell <keith@tungstengraphics.com> |
*/ |
#include "glheader.h" |
#include "colormac.h" |
#include "context.h" |
#include "macros.h" |
#include "mmath.h" |
#include "imports.h" |
#include "mtypes.h" |
#include "math/m_xform.h" |
#include "t_context.h" |
#include "t_pipeline.h" |
/*********************************************************************** |
* Automatic texture coordinate generation (texgen) code. |
*/ |
struct texgen_stage_data; |
typedef void (*texgen_func)( GLcontext *ctx, |
struct texgen_stage_data *store, |
GLuint unit); |
struct texgen_stage_data { |
/* Per-texunit derived state. |
*/ |
GLuint TexgenSize[MAX_TEXTURE_UNITS]; |
GLuint TexgenHoles[MAX_TEXTURE_UNITS]; |
texgen_func TexgenFunc[MAX_TEXTURE_UNITS]; |
/* Temporary values used in texgen. |
*/ |
GLfloat (*tmp_f)[3]; |
GLfloat *tmp_m; |
/* Buffered outputs of the stage. |
*/ |
GLvector4f texcoord[MAX_TEXTURE_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 / (GLfloat) GL_SQRT(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 / (GLfloat) GL_SQRT(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] = { |
0, |
0, |
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] = { |
0, |
0, |
build_f2, |
build_f3, |
build_f3 |
}; |
/* Special case texgen functions. |
*/ |
static void texgen_reflection_map_nv( GLcontext *ctx, |
struct texgen_stage_data *store, |
GLuint unit ) |
{ |
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; |
GLvector4f *in = VB->TexCoordPtr[unit]; |
GLvector4f *out = &store->texcoord[unit]; |
build_f_tab[VB->EyePtr->size]( out->start, |
out->stride, |
VB->NormalPtr, |
VB->EyePtr ); |
if (in) { |
out->flags |= (in->flags & VEC_SIZE_FLAGS) | VEC_SIZE_3; |
out->count = in->count; |
out->size = MAX2(in->size, 3); |
if (in->size == 4) |
_mesa_copy_tab[0x8]( out, in ); |
} |
else { |
out->flags |= VEC_SIZE_3; |
out->size = 3; |
out->count = in->count; |
} |
} |
static void texgen_normal_map_nv( GLcontext *ctx, |
struct texgen_stage_data *store, |
GLuint unit ) |
{ |
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; |
GLvector4f *in = VB->TexCoordPtr[unit]; |
GLvector4f *out = &store->texcoord[unit]; |
GLvector4f *normal = VB->NormalPtr; |
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]; |
} |
if (in) { |
out->flags |= (in->flags & VEC_SIZE_FLAGS) | VEC_SIZE_3; |
out->count = in->count; |
out->size = MAX2(in->size, 3); |
if (in->size == 4) |
_mesa_copy_tab[0x8]( out, in ); |
} |
else { |
out->flags |= VEC_SIZE_3; |
out->size = 3; |
out->count = in->count; |
} |
} |
static void texgen_sphere_map( GLcontext *ctx, |
struct texgen_stage_data *store, |
GLuint unit ) |
{ |
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; |
GLvector4f *in = VB->TexCoordPtr[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; |
/* _mesa_debug(NULL, "%s normstride %d eyestride %d\n", */ |
/* __FUNCTION__, VB->NormalPtr->stride, */ |
/* VB->EyePtr->stride); */ |
(build_m_tab[VB->EyePtr->size])( store->tmp_f, |
store->tmp_m, |
VB->NormalPtr, |
VB->EyePtr ); |
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; |
} |
if (in) { |
out->size = MAX2(in->size,2); |
out->count = in->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 ); |
} else { |
out->size = 2; |
out->flags |= VEC_SIZE_2; |
out->count = in->count; |
} |
} |
static void texgen( GLcontext *ctx, |
struct texgen_stage_data *store, |
GLuint unit ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_buffer *VB = &tnl->vb; |
GLvector4f *in = VB->TexCoordPtr[unit]; |
GLvector4f *out = &store->texcoord[unit]; |
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[unit]; |
const GLvector4f *obj = VB->ObjPtr; |
const GLvector4f *eye = VB->EyePtr; |
const GLvector4f *normal = VB->NormalPtr; |
GLfloat (*texcoord)[4] = (GLfloat (*)[4])out->data; |
GLfloat *indata; |
GLuint count = VB->Count; |
GLfloat (*f)[3] = store->tmp_f; |
GLfloat *m = store->tmp_m; |
GLuint holes = 0; |
if (texUnit->_GenFlags & TEXGEN_NEED_M) { |
build_m_tab[in->size]( store->tmp_f, store->tmp_m, normal, eye ); |
} else if (texUnit->_GenFlags & TEXGEN_NEED_F) { |
build_f_tab[in->size]( (GLfloat *)store->tmp_f, 3, normal, eye ); |
} |
if (!in) { |
ASSERT(0); |
in = out; |
in->count = VB->Count; |
out->size = store->TexgenSize[unit]; |
out->flags |= texUnit->TexGenEnabled; |
out->count = VB->Count; |
holes = store->TexgenHoles[unit]; |
} |
else { |
GLuint copy = (all_bits[in->size] & ~texUnit->TexGenEnabled); |
if (copy) |
_mesa_copy_tab[copy]( out, in ); |
out->size = MAX2(in->size, store->TexgenSize[unit]); |
out->flags |= (in->flags & VEC_SIZE_FLAGS) | texUnit->TexGenEnabled; |
out->count = in->count; |
holes = ~all_bits[in->size] & store->TexgenHoles[unit]; |
} |
if (holes) { |
if (holes & VEC_DIRTY_2) _mesa_vector4f_clean_elem(out, count, 2); |
if (holes & VEC_DIRTY_1) _mesa_vector4f_clean_elem(out, count, 1); |
if (holes & VEC_DIRTY_0) _mesa_vector4f_clean_elem(out, count, 0); |
} |
if (texUnit->TexGenEnabled & S_BIT) { |
GLuint i; |
switch (texUnit->GenModeS) { |
case GL_OBJECT_LINEAR: |
_mesa_dotprod_tab[obj->size]( (GLfloat *)out->data, |
sizeof(out->data[0]), obj, |
texUnit->ObjectPlaneS ); |
break; |
case GL_EYE_LINEAR: |
_mesa_dotprod_tab[eye->size]( (GLfloat *)out->data, |
sizeof(out->data[0]), eye, |
texUnit->EyePlaneS ); |
break; |
case GL_SPHERE_MAP: |
for (indata=in->start,i=0 ; i<count ;i++, STRIDE_F(indata,in->stride)) |
texcoord[i][0] = indata[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->GenModeT) { |
case GL_OBJECT_LINEAR: |
_mesa_dotprod_tab[obj->size]( &(out->data[0][1]), |
sizeof(out->data[0]), obj, |
texUnit->ObjectPlaneT ); |
break; |
case GL_EYE_LINEAR: |
_mesa_dotprod_tab[eye->size]( &(out->data[0][1]), |
sizeof(out->data[0]), eye, |
texUnit->EyePlaneT ); |
break; |
case GL_SPHERE_MAP: |
for (indata=in->start,i=0; i<count ;i++,STRIDE_F(indata,in->stride)) |
texcoord[i][1] = indata[1] * 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][1] = norm[1]; |
} |
break; |
} |
default: |
_mesa_problem(ctx, "Bad T texgen"); |
} |
} |
if (texUnit->TexGenEnabled & R_BIT) { |
GLuint i; |
switch (texUnit->GenModeR) { |
case GL_OBJECT_LINEAR: |
_mesa_dotprod_tab[obj->size]( &(out->data[0][2]), |
sizeof(out->data[0]), obj, |
texUnit->ObjectPlaneR ); |
break; |
case GL_EYE_LINEAR: |
_mesa_dotprod_tab[eye->size]( &(out->data[0][2]), |
sizeof(out->data[0]), eye, |
texUnit->EyePlaneR ); |
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->GenModeQ) { |
case GL_OBJECT_LINEAR: |
_mesa_dotprod_tab[obj->size]( &(out->data[0][3]), |
sizeof(out->data[0]), obj, |
texUnit->ObjectPlaneQ ); |
break; |
case GL_EYE_LINEAR: |
_mesa_dotprod_tab[eye->size]( &(out->data[0][3]), |
sizeof(out->data[0]), eye, |
texUnit->EyePlaneQ ); |
break; |
default: |
_mesa_problem(ctx, "Bad Q texgen"); |
} |
} |
} |
static GLboolean run_texgen_stage( GLcontext *ctx, |
struct gl_pipeline_stage *stage ) |
{ |
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; |
struct texgen_stage_data *store = TEXGEN_STAGE_DATA( stage ); |
GLuint i; |
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) |
if (ctx->Texture._TexGenEnabled & ENABLE_TEXGEN(i)) { |
if (stage->changed_inputs & (VERT_BIT_EYE | VERT_BIT_NORMAL | VERT_BIT_TEX(i))) |
store->TexgenFunc[i]( ctx, store, i ); |
VB->TexCoordPtr[i] = &store->texcoord[i]; |
} |
return GL_TRUE; |
} |
static GLboolean run_validate_texgen_stage( GLcontext *ctx, |
struct gl_pipeline_stage *stage ) |
{ |
struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage); |
GLuint i; |
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) { |
struct gl_texture_unit *texUnit = &ctx->Texture.Unit[i]; |
if (texUnit->TexGenEnabled) { |
GLuint sz; |
if (texUnit->TexGenEnabled & R_BIT) |
sz = 4; |
else if (texUnit->TexGenEnabled & Q_BIT) |
sz = 3; |
else if (texUnit->TexGenEnabled & T_BIT) |
sz = 2; |
else |
sz = 1; |
store->TexgenSize[i] = sz; |
store->TexgenHoles[i] = (all_bits[sz] & ~texUnit->TexGenEnabled); |
store->TexgenFunc[i] = texgen; |
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; |
} |
} |
} |
stage->run = run_texgen_stage; |
return stage->run( ctx, stage ); |
} |
static void check_texgen( GLcontext *ctx, struct gl_pipeline_stage *stage ) |
{ |
GLuint i; |
stage->active = 0; |
if (ctx->Texture._TexGenEnabled && !ctx->VertexProgram.Enabled) { |
GLuint inputs = 0; |
GLuint outputs = 0; |
if (ctx->Texture._GenFlags & TEXGEN_OBJ_LINEAR) |
inputs |= VERT_BIT_POS; |
if (ctx->Texture._GenFlags & TEXGEN_NEED_EYE_COORD) |
inputs |= VERT_BIT_EYE; |
if (ctx->Texture._GenFlags & TEXGEN_NEED_NORMALS) |
inputs |= VERT_BIT_NORMAL; |
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) |
if (ctx->Texture._TexGenEnabled & ENABLE_TEXGEN(i)) |
{ |
outputs |= VERT_BIT_TEX(i); |
/* Need the original input in case it contains a Q coord: |
* (sigh) |
*/ |
inputs |= VERT_BIT_TEX(i); |
/* Something for Feedback? */ |
} |
if (stage->privatePtr) |
stage->run = run_validate_texgen_stage; |
stage->active = 1; |
stage->inputs = inputs; |
stage->outputs = outputs; |
} |
} |
/* Called the first time stage->run() is invoked. |
*/ |
static GLboolean alloc_texgen_data( GLcontext *ctx, |
struct gl_pipeline_stage *stage ) |
{ |
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; |
struct texgen_stage_data *store; |
GLuint i; |
stage->privatePtr = CALLOC(sizeof(*store)); |
store = TEXGEN_STAGE_DATA(stage); |
if (!store) |
return GL_FALSE; |
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) |
_mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 ); |
store->tmp_f = (GLfloat (*)[3]) MALLOC(VB->Size * sizeof(GLfloat) * 3); |
store->tmp_m = (GLfloat *) MALLOC(VB->Size * sizeof(GLfloat)); |
/* Now validate and run the stage. |
*/ |
stage->run = run_validate_texgen_stage; |
return stage->run( ctx, stage ); |
} |
static void free_texgen_data( struct gl_pipeline_stage *stage ) |
{ |
struct texgen_stage_data *store = TEXGEN_STAGE_DATA(stage); |
GLuint i; |
if (store) { |
for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++) |
if (store->texcoord[i].data) |
_mesa_vector4f_free( &store->texcoord[i] ); |
if (store->tmp_f) FREE( store->tmp_f ); |
if (store->tmp_m) FREE( store->tmp_m ); |
FREE( store ); |
stage->privatePtr = NULL; |
} |
} |
const struct gl_pipeline_stage _tnl_texgen_stage = |
{ |
"texgen", /* name */ |
_NEW_TEXTURE, /* when to call check() */ |
_NEW_TEXTURE, /* when to invalidate stored data */ |
GL_FALSE, /* active? */ |
0, /* inputs */ |
0, /* outputs */ |
0, /* changed_inputs */ |
NULL, /* private data */ |
free_texgen_data, /* destructor */ |
check_texgen, /* check */ |
alloc_texgen_data /* run -- initially set to alloc data */ |
}; |
/shark/trunk/ports/mesa/src/tnl/t_vb_lighttmp.h |
---|
0,0 → 1,1003 |
/* $Id: t_vb_lighttmp.h,v 1.1 2003-02-28 11:48:07 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 4.1 |
* |
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included |
* in all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
* |
* |
* Authors: |
* Brian Paul |
* Keith Whitwell <keith@tungstengraphics.com> |
*/ |
#if (IDX & LIGHT_FLAGS) |
# define VSTRIDE (4 * sizeof(GLfloat)) |
# define NSTRIDE nstride /*(3 * sizeof(GLfloat))*/ |
# define CHECK_MATERIAL(x) (flags[x] & VERT_BIT_MATERIAL) |
# define CHECK_END_VB(x) (flags[x] & VERT_BIT_END_VB) |
# if (IDX & LIGHT_COLORMATERIAL) |
# define CMSTRIDE STRIDE_F(CMcolor, CMstride) |
# define CHECK_COLOR_MATERIAL(x) (flags[x] & VERT_BIT_COLOR0) |
# define CHECK_VALIDATE(x) (flags[x] & (VERT_BIT_COLOR0|VERT_BIT_MATERIAL)) |
# define DO_ANOTHER_NORMAL(x) \ |
((flags[x] & (VERT_BIT_COLOR0|VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == VERT_BIT_NORMAL) |
# define REUSE_LIGHT_RESULTS(x) \ |
((flags[x] & (VERT_BIT_COLOR0|VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == 0) |
# else |
# define CMSTRIDE (void)0 |
# define CHECK_COLOR_MATERIAL(x) 0 |
# define CHECK_VALIDATE(x) (flags[x] & (VERT_BIT_MATERIAL)) |
# define DO_ANOTHER_NORMAL(x) \ |
((flags[x] & (VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == VERT_BIT_NORMAL) |
# define REUSE_LIGHT_RESULTS(x) \ |
((flags[x] & (VERT_BIT_NORMAL|VERT_BIT_END_VB|VERT_BIT_MATERIAL)) == 0) |
# endif |
#else |
# define VSTRIDE vstride |
# define NSTRIDE nstride |
# define CHECK_MATERIAL(x) 0 /* no materials on array paths */ |
# define CHECK_END_VB(XX) (XX >= nr) |
# if (IDX & LIGHT_COLORMATERIAL) |
# define CMSTRIDE STRIDE_F(CMcolor, CMstride) |
# define CHECK_COLOR_MATERIAL(x) (x < nr) /* always have colormaterial */ |
# define CHECK_VALIDATE(x) (x < nr) |
# define DO_ANOTHER_NORMAL(x) 0 /* always stop to recalc colormat */ |
# else |
# define CMSTRIDE (void)0 |
# define CHECK_COLOR_MATERIAL(x) 0 /* no colormaterial */ |
# define CHECK_VALIDATE(x) (0) |
# define DO_ANOTHER_NORMAL(XX) (XX < nr) /* keep going to end of vb */ |
# endif |
# define REUSE_LIGHT_RESULTS(x) 0 /* always have a new normal */ |
#endif |
#if (IDX & LIGHT_TWOSIDE) |
# define NR_SIDES 2 |
#else |
# define NR_SIDES 1 |
#endif |
/* define TRACE if to trace lighting code */ |
/* |
* ctx is the current context |
* VB is the vertex buffer |
* stage is the lighting stage-private data |
* input is the vector of eye or object-space vertex coordinates |
*/ |
static void TAG(light_rgba_spec)( GLcontext *ctx, |
struct vertex_buffer *VB, |
struct gl_pipeline_stage *stage, |
GLvector4f *input ) |
{ |
struct light_stage_data *store = LIGHT_STAGE_DATA(stage); |
GLfloat (*base)[3] = ctx->Light._BaseColor; |
GLchan sumA[2]; |
GLuint j; |
const GLuint vstride = input->stride; |
const GLfloat *vertex = (GLfloat *)input->data; |
const GLuint nstride = VB->NormalPtr->stride; |
const GLfloat *normal = (GLfloat *)VB->NormalPtr->data; |
GLfloat *CMcolor; |
GLuint CMstride; |
GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr; |
GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr; |
GLchan (*Fspec)[4] = (GLchan (*)[4]) store->LitSecondary[0].Ptr; |
GLchan (*Bspec)[4] = (GLchan (*)[4]) store->LitSecondary[1].Ptr; |
const GLuint nr = VB->Count; |
const GLuint *flags = VB->Flag; |
struct gl_material (*new_material)[2] = VB->Material; |
const GLuint *new_material_mask = VB->MaterialMask; |
(void) flags; |
(void) nstride; |
(void) vstride; |
#ifdef TRACE |
fprintf(stderr, "%s\n", __FUNCTION__ ); |
#endif |
if (IDX & LIGHT_COLORMATERIAL) { |
if (VB->ColorPtr[0]->Type != GL_FLOAT || |
VB->ColorPtr[0]->Size != 4) |
import_color_material( ctx, stage ); |
CMcolor = (GLfloat *) VB->ColorPtr[0]->Ptr; |
CMstride = VB->ColorPtr[0]->StrideB; |
} |
VB->ColorPtr[0] = &store->LitColor[0]; |
VB->SecondaryColorPtr[0] = &store->LitSecondary[0]; |
UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]); |
if (IDX & LIGHT_TWOSIDE) { |
VB->ColorPtr[1] = &store->LitColor[1]; |
VB->SecondaryColorPtr[1] = &store->LitSecondary[1]; |
UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]); |
} |
/* Side-effects done, can we finish now? |
*/ |
if (stage->changed_inputs == 0) |
return; |
for ( j=0 ; |
j<nr ; |
j++,STRIDE_F(vertex,VSTRIDE),STRIDE_F(normal,NSTRIDE),CMSTRIDE) |
{ |
GLfloat sum[2][3], spec[2][3]; |
struct gl_light *light; |
if ( CHECK_COLOR_MATERIAL(j) ) |
_mesa_update_color_material( ctx, CMcolor ); |
if ( CHECK_MATERIAL(j) ) |
_mesa_update_material( ctx, new_material[j], new_material_mask[j] ); |
if ( CHECK_VALIDATE(j) ) { |
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx ); |
UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]); |
if (IDX & LIGHT_TWOSIDE) |
UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]); |
} |
COPY_3V(sum[0], base[0]); |
ZERO_3V(spec[0]); |
if (IDX & LIGHT_TWOSIDE) { |
COPY_3V(sum[1], base[1]); |
ZERO_3V(spec[1]); |
} |
/* 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->_NormDirection); |
if (PV_dot_dir<light->_CosCutoff) { |
continue; /* this light makes no contribution */ |
} |
else { |
GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1); |
GLint k = (GLint) x; |
GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0] |
+ (x-k)*light->_SpotExpTable[k][1]); |
attenuation *= spot; |
} |
} |
} |
if (attenuation < 1e-3) |
continue; /* this light makes no contribution */ |
/* Compute dot product or normal and vector from V to light pos */ |
n_dot_VP = DOT3( normal, VP ); |
/* Which side gets the diffuse & specular terms? */ |
if (n_dot_VP < 0.0F) { |
ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]); |
if (!(IDX & LIGHT_TWOSIDE)) { |
continue; |
} |
side = 1; |
correction = -1; |
n_dot_VP = -n_dot_VP; |
} |
else { |
if (IDX & LIGHT_TWOSIDE) { |
ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]); |
} |
side = 0; |
correction = 1; |
} |
/* diffuse term */ |
COPY_3V(contrib, light->_MatAmbient[side]); |
ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]); |
ACC_SCALE_SCALAR_3V(sum[side], attenuation, contrib ); |
/* specular term - cannibalize VP... */ |
if (ctx->Light.Model.LocalViewer) { |
GLfloat v[3]; |
COPY_3V(v, vertex); |
NORMALIZE_3FV(v); |
SUB_3V(VP, VP, v); /* h = VP + VPe */ |
h = VP; |
NORMALIZE_3FV(h); |
} |
else if (light->_Flags & LIGHT_POSITIONAL) { |
h = VP; |
ACC_3V(h, ctx->_EyeZDir); |
NORMALIZE_3FV(h); |
} |
else { |
h = light->_h_inf_norm; |
} |
n_dot_h = correction * DOT3(normal, h); |
if (n_dot_h > 0.0F) { |
GLfloat spec_coef; |
struct gl_shine_tab *tab = ctx->_ShineTable[side]; |
GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef ); |
if (spec_coef > 1.0e-10) { |
spec_coef *= attenuation; |
ACC_SCALE_SCALAR_3V( spec[side], spec_coef, |
light->_MatSpecular[side]); |
} |
} |
} /*loop over lights*/ |
UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] ); |
UNCLAMPED_FLOAT_TO_RGB_CHAN( Fspec[j], spec[0] ); |
Fcolor[j][3] = sumA[0]; |
if (IDX & LIGHT_TWOSIDE) { |
UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] ); |
UNCLAMPED_FLOAT_TO_RGB_CHAN( Bspec[j], spec[1] ); |
Bcolor[j][3] = sumA[1]; |
} |
} |
} |
static void TAG(light_rgba)( GLcontext *ctx, |
struct vertex_buffer *VB, |
struct gl_pipeline_stage *stage, |
GLvector4f *input ) |
{ |
struct light_stage_data *store = LIGHT_STAGE_DATA(stage); |
GLuint j; |
GLfloat (*base)[3] = ctx->Light._BaseColor; |
GLchan sumA[2]; |
const GLuint vstride = input->stride; |
const GLfloat *vertex = (GLfloat *) input->data; |
const GLuint nstride = VB->NormalPtr->stride; |
const GLfloat *normal = (GLfloat *)VB->NormalPtr->data; |
GLfloat *CMcolor; |
GLuint CMstride; |
GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr; |
GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr; |
GLchan (*color[2])[4]; |
const GLuint *flags = VB->Flag; |
struct gl_material (*new_material)[2] = VB->Material; |
const GLuint *new_material_mask = VB->MaterialMask; |
const GLuint nr = VB->Count; |
#ifdef TRACE |
fprintf(stderr, "%s\n", __FUNCTION__ ); |
#endif |
(void) flags; |
(void) nstride; |
(void) vstride; |
color[0] = Fcolor; |
color[1] = Bcolor; |
if (IDX & LIGHT_COLORMATERIAL) { |
if (VB->ColorPtr[0]->Type != GL_FLOAT || |
VB->ColorPtr[0]->Size != 4) |
import_color_material( ctx, stage ); |
CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr; |
CMstride = VB->ColorPtr[0]->StrideB; |
} |
VB->ColorPtr[0] = &store->LitColor[0]; |
UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]); |
if (IDX & LIGHT_TWOSIDE) { |
VB->ColorPtr[1] = &store->LitColor[1]; |
UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]); |
} |
if (stage->changed_inputs == 0) |
return; |
for ( j=0 ; |
j<nr ; |
j++,STRIDE_F(vertex,VSTRIDE), STRIDE_F(normal,NSTRIDE),CMSTRIDE) |
{ |
GLfloat sum[2][3]; |
struct gl_light *light; |
if ( CHECK_COLOR_MATERIAL(j) ) |
_mesa_update_color_material( ctx, CMcolor ); |
if ( CHECK_MATERIAL(j) ) |
_mesa_update_material( ctx, new_material[j], new_material_mask[j] ); |
if ( CHECK_VALIDATE(j) ) { |
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx ); |
UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]); |
if (IDX & LIGHT_TWOSIDE) |
UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]); |
} |
COPY_3V(sum[0], base[0]); |
if ( IDX & LIGHT_TWOSIDE ) |
COPY_3V(sum[1], base[1]); |
/* 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->_NormDirection); |
if (PV_dot_dir<light->_CosCutoff) { |
continue; /* this light makes no contribution */ |
} |
else { |
GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1); |
GLint k = (GLint) x; |
GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0] |
+ (x-k)*light->_SpotExpTable[k][1]); |
attenuation *= spot; |
} |
} |
} |
if (attenuation < 1e-3) |
continue; /* this light makes no contribution */ |
/* Compute dot product or normal and vector from V to light pos */ |
n_dot_VP = DOT3( normal, VP ); |
/* which side are we lighting? */ |
if (n_dot_VP < 0.0F) { |
ACC_SCALE_SCALAR_3V(sum[0], attenuation, light->_MatAmbient[0]); |
if (!(IDX & LIGHT_TWOSIDE)) |
continue; |
side = 1; |
correction = -1; |
n_dot_VP = -n_dot_VP; |
} |
else { |
if (IDX & LIGHT_TWOSIDE) { |
ACC_SCALE_SCALAR_3V( sum[1], attenuation, light->_MatAmbient[1]); |
} |
side = 0; |
correction = 1; |
} |
COPY_3V(contrib, light->_MatAmbient[side]); |
/* diffuse term */ |
ACC_SCALE_SCALAR_3V(contrib, n_dot_VP, light->_MatDiffuse[side]); |
/* specular term - cannibalize VP... */ |
{ |
if (ctx->Light.Model.LocalViewer) { |
GLfloat v[3]; |
COPY_3V(v, vertex); |
NORMALIZE_3FV(v); |
SUB_3V(VP, VP, v); /* h = VP + VPe */ |
h = VP; |
NORMALIZE_3FV(h); |
} |
else if (light->_Flags & LIGHT_POSITIONAL) { |
h = VP; |
ACC_3V(h, ctx->_EyeZDir); |
NORMALIZE_3FV(h); |
} |
else { |
h = light->_h_inf_norm; |
} |
n_dot_h = correction * DOT3(normal, h); |
if (n_dot_h > 0.0F) |
{ |
GLfloat spec_coef; |
struct gl_shine_tab *tab = ctx->_ShineTable[side]; |
GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef ); |
ACC_SCALE_SCALAR_3V( contrib, spec_coef, |
light->_MatSpecular[side]); |
} |
} |
ACC_SCALE_SCALAR_3V( sum[side], attenuation, contrib ); |
} |
UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] ); |
Fcolor[j][3] = sumA[0]; |
if (IDX & LIGHT_TWOSIDE) { |
UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] ); |
Bcolor[j][3] = sumA[1]; |
} |
} |
} |
/* As below, but with just a single light. |
*/ |
static void TAG(light_fast_rgba_single)( GLcontext *ctx, |
struct vertex_buffer *VB, |
struct gl_pipeline_stage *stage, |
GLvector4f *input ) |
{ |
struct light_stage_data *store = LIGHT_STAGE_DATA(stage); |
const GLuint nstride = VB->NormalPtr->stride; |
const GLfloat *normal = (GLfloat *)VB->NormalPtr->data; |
GLfloat *CMcolor; |
GLuint CMstride; |
GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr; |
GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr; |
const struct gl_light *light = ctx->Light.EnabledList.next; |
const GLuint *flags = VB->Flag; |
GLchan basechan[2][4]; |
GLuint j = 0; |
struct gl_material (*new_material)[2] = VB->Material; |
const GLuint *new_material_mask = VB->MaterialMask; |
GLfloat base[2][3]; |
const GLuint nr = VB->Count; |
#ifdef TRACE |
fprintf(stderr, "%s\n", __FUNCTION__ ); |
#endif |
(void) input; /* doesn't refer to Eye or Obj */ |
(void) flags; |
(void) nr; |
(void) nstride; |
if (IDX & LIGHT_COLORMATERIAL) { |
if (VB->ColorPtr[0]->Type != GL_FLOAT || |
VB->ColorPtr[0]->Size != 4) |
import_color_material( ctx, stage ); |
CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr; |
CMstride = VB->ColorPtr[0]->StrideB; |
} |
VB->ColorPtr[0] = &store->LitColor[0]; |
if (IDX & LIGHT_TWOSIDE) |
VB->ColorPtr[1] = &store->LitColor[1]; |
if (stage->changed_inputs == 0) |
return; |
do { |
if ( CHECK_COLOR_MATERIAL(j) ) { |
_mesa_update_color_material( ctx, CMcolor ); |
} |
if ( CHECK_MATERIAL(j) ) |
_mesa_update_material( ctx, new_material[j], new_material_mask[j] ); |
if ( CHECK_VALIDATE(j) ) |
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx ); |
/* No attenuation, so incoporate _MatAmbient into base color. |
*/ |
COPY_3V(base[0], light->_MatAmbient[0]); |
ACC_3V(base[0], ctx->Light._BaseColor[0] ); |
UNCLAMPED_FLOAT_TO_RGB_CHAN( basechan[0], base[0] ); |
UNCLAMPED_FLOAT_TO_CHAN(basechan[0][3], |
ctx->Light.Material[0].Diffuse[3]); |
if (IDX & LIGHT_TWOSIDE) { |
COPY_3V(base[1], light->_MatAmbient[1]); |
ACC_3V(base[1], ctx->Light._BaseColor[1]); |
UNCLAMPED_FLOAT_TO_RGB_CHAN( basechan[1], base[1]); |
UNCLAMPED_FLOAT_TO_CHAN(basechan[1][3], |
ctx->Light.Material[1].Diffuse[3]); |
} |
do { |
GLfloat n_dot_VP = DOT3(normal, light->_VP_inf_norm); |
if (n_dot_VP < 0.0F) { |
if (IDX & LIGHT_TWOSIDE) { |
GLfloat n_dot_h = -DOT3(normal, light->_h_inf_norm); |
GLfloat sum[3]; |
COPY_3V(sum, base[1]); |
ACC_SCALE_SCALAR_3V(sum, -n_dot_VP, light->_MatDiffuse[1]); |
if (n_dot_h > 0.0F) { |
GLfloat spec; |
GET_SHINE_TAB_ENTRY( ctx->_ShineTable[1], n_dot_h, spec ); |
ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[1]); |
} |
UNCLAMPED_FLOAT_TO_RGB_CHAN(Bcolor[j], sum ); |
Bcolor[j][3] = basechan[1][3]; |
} |
COPY_CHAN4(Fcolor[j], basechan[0]); |
} |
else { |
GLfloat n_dot_h = DOT3(normal, light->_h_inf_norm); |
GLfloat sum[3]; |
COPY_3V(sum, base[0]); |
ACC_SCALE_SCALAR_3V(sum, n_dot_VP, light->_MatDiffuse[0]); |
if (n_dot_h > 0.0F) { |
GLfloat spec; |
GET_SHINE_TAB_ENTRY( ctx->_ShineTable[0], n_dot_h, spec ); |
ACC_SCALE_SCALAR_3V(sum, spec, light->_MatSpecular[0]); |
} |
UNCLAMPED_FLOAT_TO_RGB_CHAN(Fcolor[j], sum ); |
Fcolor[j][3] = basechan[0][3]; |
if (IDX & LIGHT_TWOSIDE) COPY_CHAN4(Bcolor[j], basechan[1]); |
} |
j++; |
CMSTRIDE; |
STRIDE_F(normal, NSTRIDE); |
} while (DO_ANOTHER_NORMAL(j)); |
for ( ; REUSE_LIGHT_RESULTS(j) ; j++, CMSTRIDE, STRIDE_F(normal,NSTRIDE)) |
{ |
COPY_CHAN4(Fcolor[j], Fcolor[j-1]); |
if (IDX & LIGHT_TWOSIDE) |
COPY_CHAN4(Bcolor[j], Bcolor[j-1]); |
} |
} while (!CHECK_END_VB(j)); |
} |
/* Light infinite lights |
*/ |
static void TAG(light_fast_rgba)( GLcontext *ctx, |
struct vertex_buffer *VB, |
struct gl_pipeline_stage *stage, |
GLvector4f *input ) |
{ |
struct light_stage_data *store = LIGHT_STAGE_DATA(stage); |
GLchan sumA[2]; |
const GLuint nstride = VB->NormalPtr->stride; |
const GLfloat *normal = (GLfloat *)VB->NormalPtr->data; |
GLfloat *CMcolor; |
GLuint CMstride; |
GLchan (*Fcolor)[4] = (GLchan (*)[4]) store->LitColor[0].Ptr; |
GLchan (*Bcolor)[4] = (GLchan (*)[4]) store->LitColor[1].Ptr; |
const GLuint *flags = VB->Flag; |
GLuint j = 0; |
struct gl_material (*new_material)[2] = VB->Material; |
GLuint *new_material_mask = VB->MaterialMask; |
const GLuint nr = VB->Count; |
const struct gl_light *light; |
#ifdef TRACE |
fprintf(stderr, "%s\n", __FUNCTION__ ); |
#endif |
(void) flags; |
(void) input; |
(void) nr; |
(void) nstride; |
UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]); |
UNCLAMPED_FLOAT_TO_CHAN(sumA[1], ctx->Light.Material[1].Diffuse[3]); |
if (IDX & LIGHT_COLORMATERIAL) { |
if (VB->ColorPtr[0]->Type != GL_FLOAT || |
VB->ColorPtr[0]->Size != 4) |
import_color_material( ctx, stage ); |
CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr; |
CMstride = VB->ColorPtr[0]->StrideB; |
} |
VB->ColorPtr[0] = &store->LitColor[0]; |
if (IDX & LIGHT_TWOSIDE) |
VB->ColorPtr[1] = &store->LitColor[1]; |
if (stage->changed_inputs == 0) |
return; |
do { |
do { |
GLfloat sum[2][3]; |
if ( CHECK_COLOR_MATERIAL(j) ) |
_mesa_update_color_material( ctx, CMcolor ); |
if ( CHECK_MATERIAL(j) ) |
_mesa_update_material( ctx, new_material[j], new_material_mask[j] ); |
if ( CHECK_VALIDATE(j) ) { |
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx ); |
UNCLAMPED_FLOAT_TO_CHAN(sumA[0], ctx->Light.Material[0].Diffuse[3]); |
if (IDX & LIGHT_TWOSIDE) |
UNCLAMPED_FLOAT_TO_CHAN(sumA[1], |
ctx->Light.Material[1].Diffuse[3]); |
} |
COPY_3V(sum[0], ctx->Light._BaseColor[0]); |
if (IDX & LIGHT_TWOSIDE) |
COPY_3V(sum[1], ctx->Light._BaseColor[1]); |
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]); |
n_dot_VP = DOT3(normal, light->_VP_inf_norm); |
if (n_dot_VP > 0.0F) { |
ACC_SCALE_SCALAR_3V(sum[0], n_dot_VP, light->_MatDiffuse[0]); |
n_dot_h = DOT3(normal, light->_h_inf_norm); |
if (n_dot_h > 0.0F) { |
struct gl_shine_tab *tab = ctx->_ShineTable[0]; |
GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec ); |
ACC_SCALE_SCALAR_3V( sum[0], spec, |
light->_MatSpecular[0]); |
} |
} |
else if (IDX & LIGHT_TWOSIDE) { |
ACC_SCALE_SCALAR_3V(sum[1], -n_dot_VP, light->_MatDiffuse[1]); |
n_dot_h = -DOT3(normal, light->_h_inf_norm); |
if (n_dot_h > 0.0F) { |
struct gl_shine_tab *tab = ctx->_ShineTable[1]; |
GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec ); |
ACC_SCALE_SCALAR_3V( sum[1], spec, |
light->_MatSpecular[1]); |
} |
} |
} |
UNCLAMPED_FLOAT_TO_RGB_CHAN( Fcolor[j], sum[0] ); |
Fcolor[j][3] = sumA[0]; |
if (IDX & LIGHT_TWOSIDE) { |
UNCLAMPED_FLOAT_TO_RGB_CHAN( Bcolor[j], sum[1] ); |
Bcolor[j][3] = sumA[1]; |
} |
j++; |
CMSTRIDE; |
STRIDE_F(normal, NSTRIDE); |
} while (DO_ANOTHER_NORMAL(j)); |
/* Reuse the shading results while there is no change to |
* normal or material values. |
*/ |
for ( ; REUSE_LIGHT_RESULTS(j) ; j++, CMSTRIDE, STRIDE_F(normal, NSTRIDE)) |
{ |
COPY_CHAN4(Fcolor[j], Fcolor[j-1]); |
if (IDX & LIGHT_TWOSIDE) |
COPY_CHAN4(Bcolor[j], Bcolor[j-1]); |
} |
} while (!CHECK_END_VB(j)); |
} |
/* |
* Use current lighting/material settings to compute the color indexes |
* for an array of vertices. |
* Input: n - number of vertices to light |
* side - 0=use front material, 1=use back material |
* vertex - array of [n] vertex position in eye coordinates |
* normal - array of [n] surface normal vector |
* Output: indexResult - resulting array of [n] color indexes |
*/ |
static void TAG(light_ci)( GLcontext *ctx, |
struct vertex_buffer *VB, |
struct gl_pipeline_stage *stage, |
GLvector4f *input ) |
{ |
struct light_stage_data *store = LIGHT_STAGE_DATA(stage); |
GLuint j; |
const GLuint vstride = input->stride; |
const GLfloat *vertex = (GLfloat *) input->data; |
const GLuint nstride = VB->NormalPtr->stride; |
const GLfloat *normal = (GLfloat *)VB->NormalPtr->data; |
GLfloat *CMcolor; |
GLuint CMstride; |
const GLuint *flags = VB->Flag; |
GLuint *indexResult[2]; |
struct gl_material (*new_material)[2] = VB->Material; |
GLuint *new_material_mask = VB->MaterialMask; |
const GLuint nr = VB->Count; |
#ifdef TRACE |
fprintf(stderr, "%s\n", __FUNCTION__ ); |
#endif |
(void) flags; |
(void) nstride; |
(void) vstride; |
VB->IndexPtr[0] = &store->LitIndex[0]; |
if (IDX & LIGHT_TWOSIDE) |
VB->IndexPtr[1] = &store->LitIndex[1]; |
if (stage->changed_inputs == 0) |
return; |
indexResult[0] = VB->IndexPtr[0]->data; |
if (IDX & LIGHT_TWOSIDE) |
indexResult[1] = VB->IndexPtr[1]->data; |
if (IDX & LIGHT_COLORMATERIAL) { |
if (VB->ColorPtr[0]->Type != GL_FLOAT || |
VB->ColorPtr[0]->Size != 4) |
import_color_material( ctx, stage ); |
CMcolor = (GLfloat *)VB->ColorPtr[0]->Ptr; |
CMstride = VB->ColorPtr[0]->StrideB; |
} |
/* loop over vertices */ |
for ( j=0 ; |
j<nr ; |
j++,STRIDE_F(vertex,VSTRIDE),STRIDE_F(normal, NSTRIDE), CMSTRIDE) |
{ |
GLfloat diffuse[2], specular[2]; |
GLuint side = 0; |
struct gl_light *light; |
if ( CHECK_COLOR_MATERIAL(j) ) |
_mesa_update_color_material( ctx, CMcolor ); |
if ( CHECK_MATERIAL(j) ) |
_mesa_update_material( ctx, new_material[j], new_material_mask[j] ); |
if ( CHECK_VALIDATE(j) ) |
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx ); |
diffuse[0] = specular[0] = 0.0F; |
if ( IDX & LIGHT_TWOSIDE ) { |
diffuse[1] = specular[1] = 0.0F; |
} |
/* Accumulate diffuse and specular from each light source */ |
foreach (light, &ctx->Light.EnabledList) { |
GLfloat attenuation = 1.0F; |
GLfloat VP[3]; /* unit vector from vertex to light */ |
GLfloat n_dot_VP; /* dot product of l and n */ |
GLfloat *h, n_dot_h, correction = 1.0; |
/* compute l and attenuation */ |
if (!(light->_Flags & LIGHT_POSITIONAL)) { |
/* directional light */ |
COPY_3V(VP, light->_VP_inf_norm); |
} |
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->_NormDirection); |
if (PV_dot_dir < light->_CosCutoff) { |
continue; /* this light makes no contribution */ |
} |
else { |
GLdouble x = PV_dot_dir * (EXP_TABLE_SIZE-1); |
GLint k = (GLint) x; |
GLfloat spot = (GLfloat) (light->_SpotExpTable[k][0] |
+ (x-k)*light->_SpotExpTable[k][1]); |
attenuation *= spot; |
} |
} |
} |
if (attenuation < 1e-3) |
continue; /* this light makes no contribution */ |
n_dot_VP = DOT3( normal, VP ); |
/* which side are we lighting? */ |
if (n_dot_VP < 0.0F) { |
if (!(IDX & LIGHT_TWOSIDE)) |
continue; |
side = 1; |
correction = -1; |
n_dot_VP = -n_dot_VP; |
} |
/* accumulate diffuse term */ |
diffuse[side] += n_dot_VP * light->_dli * attenuation; |
/* specular term */ |
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; |
/* Strangely, disabling this addition fixes a conformance |
* problem. If this code is enabled, l_sed.c fails. |
*/ |
/*ACC_3V(h, ctx->_EyeZDir);*/ |
NORMALIZE_3FV(h); |
} |
else { |
h = light->_h_inf_norm; |
} |
n_dot_h = correction * DOT3(normal, h); |
if (n_dot_h > 0.0F) { |
GLfloat spec_coef; |
struct gl_shine_tab *tab = ctx->_ShineTable[side]; |
GET_SHINE_TAB_ENTRY( tab, n_dot_h, spec_coef); |
specular[side] += spec_coef * light->_sli * attenuation; |
} |
} /*loop over lights*/ |
/* Now compute final color index */ |
for (side = 0 ; side < NR_SIDES ; side++) { |
struct gl_material *mat = &ctx->Light.Material[side]; |
GLfloat index; |
if (specular[side] > 1.0F) { |
index = mat->SpecularIndex; |
} |
else { |
GLfloat d_a = mat->DiffuseIndex - mat->AmbientIndex; |
GLfloat s_a = mat->SpecularIndex - mat->AmbientIndex; |
index = mat->AmbientIndex |
+ diffuse[side] * (1.0F-specular[side]) * d_a |
+ specular[side] * s_a; |
if (index > mat->SpecularIndex) { |
index = mat->SpecularIndex; |
} |
} |
indexResult[side][j] = (GLuint) (GLint) index; |
} |
} /*for vertex*/ |
} |
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); |
_tnl_light_ci_tab[IDX] = TAG(light_ci); |
} |
#undef TAG |
#undef IDX |
#undef NR_SIDES |
#undef NSTRIDE |
#undef VSTRIDE |
#undef CHECK_MATERIAL |
#undef CHECK_END_VB |
#undef DO_ANOTHER_NORMAL |
#undef REUSE_LIGHT_RESULTS |
#undef CMSTRIDE |
#undef CHECK_COLOR_MATERIAL |
#undef CHECK_VALIDATE |
/shark/trunk/ports/mesa/src/tnl/t_context.c |
---|
0,0 → 1,244 |
/* $Id: t_context.c,v 1.1 2003-02-28 11:48:06 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 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 "imports.h" |
#include "macros.h" |
#include "mtypes.h" |
#include "dlist.h" |
#include "light.h" |
#include "vtxfmt.h" |
#include "t_context.h" |
#include "t_array_api.h" |
#include "t_eval_api.h" |
#include "t_imm_alloc.h" |
#include "t_imm_api.h" |
#include "t_imm_exec.h" |
#include "t_imm_dlist.h" |
#include "t_pipeline.h" |
#include "tnl.h" |
#ifndef THREADS |
struct immediate *_tnl_CurrentInput = NULL; |
#endif |
void |
_tnl_MakeCurrent( GLcontext *ctx, |
GLframebuffer *drawBuffer, |
GLframebuffer *readBuffer ) |
{ |
#ifndef THREADS |
SET_IMMEDIATE( ctx, TNL_CURRENT_IM(ctx) ); |
#endif |
} |
static void |
install_driver_callbacks( GLcontext *ctx ) |
{ |
ctx->Driver.NewList = _tnl_NewList; |
ctx->Driver.EndList = _tnl_EndList; |
ctx->Driver.FlushVertices = _tnl_flush_vertices; |
ctx->Driver.MakeCurrent = _tnl_MakeCurrent; |
ctx->Driver.BeginCallList = _tnl_BeginCallList; |
ctx->Driver.EndCallList = _tnl_EndCallList; |
} |
GLboolean |
_tnl_CreateContext( GLcontext *ctx ) |
{ |
TNLcontext *tnl; |
/* Create the TNLcontext structure |
*/ |
ctx->swtnl_context = tnl = (TNLcontext *) CALLOC( sizeof(TNLcontext) ); |
if (!tnl) { |
return GL_FALSE; |
} |
/* Initialize the VB. |
*/ |
tnl->vb.Size = MAX2( IMM_SIZE, |
ctx->Const.MaxArrayLockSize + MAX_CLIPPED_VERTICES); |
/* Initialize tnl state and tnl->vtxfmt. |
*/ |
_tnl_dlist_init( ctx ); |
_tnl_array_init( ctx ); |
_tnl_imm_init( ctx ); |
_tnl_eval_init( ctx ); |
_tnl_install_pipeline( ctx, _tnl_default_pipeline ); |
tnl->NeedNdcCoords = GL_TRUE; |
tnl->LoopbackDListCassettes = GL_FALSE; |
tnl->CalcDListNormalLengths = GL_TRUE; |
/* Hook our functions into exec and compile dispatch tables. |
*/ |
_mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt ); |
tnl->save_vtxfmt = tnl->vtxfmt; |
tnl->save_vtxfmt.CallList = _mesa_save_CallList; |
tnl->save_vtxfmt.EvalMesh1 = _mesa_save_EvalMesh1; |
tnl->save_vtxfmt.EvalMesh2 = _mesa_save_EvalMesh2; |
tnl->save_vtxfmt.Begin = _tnl_save_Begin; |
_mesa_install_save_vtxfmt( ctx, &tnl->save_vtxfmt ); |
/* Set a few default values in the driver struct. |
*/ |
install_driver_callbacks(ctx); |
ctx->Driver.NeedFlush = FLUSH_UPDATE_CURRENT; |
ctx->Driver.CurrentExecPrimitive = PRIM_OUTSIDE_BEGIN_END; |
ctx->Driver.CurrentSavePrimitive = PRIM_UNKNOWN; |
tnl->Driver.Render.PrimTabElts = _tnl_render_tab_elts; |
tnl->Driver.Render.PrimTabVerts = _tnl_render_tab_verts; |
tnl->Driver.NotifyMaterialChange = _mesa_validate_all_lighting_tables; |
return GL_TRUE; |
} |
void |
_tnl_DestroyContext( GLcontext *ctx ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
_tnl_array_destroy( ctx ); |
_tnl_imm_destroy( ctx ); |
_tnl_destroy_pipeline( ctx ); |
_tnl_free_immediate( ctx, tnl->freed_immediate ); |
FREE(tnl); |
ctx->swtnl_context = 0; |
} |
void |
_tnl_InvalidateState( GLcontext *ctx, GLuint new_state ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
if (new_state & _NEW_ARRAY) { |
struct immediate *IM = TNL_CURRENT_IM(ctx); |
IM->ArrayEltFlags = ~ctx->Array._Enabled; |
IM->ArrayEltFlush = (ctx->Array.LockCount |
? FLUSH_ELT_LAZY : FLUSH_ELT_EAGER); |
IM->ArrayEltIncr = ctx->Array.Vertex.Enabled ? 1 : 0; |
tnl->pipeline.run_input_changes |= ctx->Array.NewState; /* overkill */ |
} |
tnl->pipeline.run_state_changes |= new_state; |
tnl->pipeline.build_state_changes |= (new_state & |
tnl->pipeline.build_state_trigger); |
tnl->eval.EvalNewState |= new_state; |
} |
void |
_tnl_wakeup_exec( GLcontext *ctx ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
install_driver_callbacks(ctx); |
ctx->Driver.NeedFlush |= FLUSH_UPDATE_CURRENT; |
/* Hook our functions into exec and compile dispatch tables. |
*/ |
_mesa_install_exec_vtxfmt( ctx, &tnl->vtxfmt ); |
/* Call all appropriate driver callbacks to revive state. |
*/ |
_tnl_MakeCurrent( ctx, ctx->DrawBuffer, ctx->ReadBuffer ); |
/* Assume we haven't been getting state updates either: |
*/ |
_tnl_InvalidateState( ctx, ~0 ); |
tnl->pipeline.run_input_changes = ~0; |
if (ctx->Light.ColorMaterialEnabled) { |
_mesa_update_color_material( ctx, ctx->Current.Attrib[VERT_ATTRIB_COLOR0] ); |
} |
} |
void |
_tnl_wakeup_save_exec( GLcontext *ctx ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
_tnl_wakeup_exec( ctx ); |
_mesa_install_save_vtxfmt( ctx, &tnl->save_vtxfmt ); |
} |
void |
_tnl_need_projected_coords( GLcontext *ctx, GLboolean mode ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
if (tnl->NeedNdcCoords != mode) { |
tnl->NeedNdcCoords = mode; |
_tnl_InvalidateState( ctx, _NEW_PROJECTION ); |
} |
} |
void |
_tnl_need_dlist_loopback( GLcontext *ctx, GLboolean mode ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
tnl->LoopbackDListCassettes = mode; |
} |
void |
_tnl_need_dlist_norm_lengths( GLcontext *ctx, GLboolean mode ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
tnl->CalcDListNormalLengths = mode; |
} |
void |
_tnl_isolate_materials( GLcontext *ctx, GLboolean mode ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
tnl->IsolateMaterials = mode; |
} |
/shark/trunk/ports/mesa/src/tnl/t_imm_dlist.h |
---|
0,0 → 1,45 |
/* $Id: t_imm_dlist.h,v 1.1 2003-02-28 11:48:06 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included |
* in all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
* |
* Authors: |
* Keith Whitwell <keith@tungstengraphics.com> |
*/ |
#ifndef _T_DLIST_H |
#define _T_DLIST_H |
#include "mtypes.h" |
#include "t_context.h" |
extern void _tnl_dlist_init( GLcontext *ctx ); |
extern void _tnl_compile_cassette( GLcontext *ctx, struct immediate *IM ); |
extern void _tnl_EndList( GLcontext *ctx ); |
extern void _tnl_NewList( GLcontext *ctx, GLuint list, GLenum mode ); |
extern void _tnl_EndCallList( GLcontext *ctx ); |
extern void _tnl_BeginCallList( GLcontext *ctx, GLuint list ); |
#endif |
/shark/trunk/ports/mesa/src/tnl/t_imm_elt.c |
---|
0,0 → 1,834 |
/* $Id: t_imm_elt.c,v 1.1 2003-02-28 11:48:06 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 "imports.h" |
#include "mmath.h" |
#include "mtypes.h" |
#include "math/m_translate.h" |
#include "t_context.h" |
#include "t_imm_elt.h" |
typedef void (*trans_elt_1f_func)(GLfloat *to, |
CONST void *ptr, |
GLuint stride, |
GLuint *flags, |
GLuint *elts, |
GLuint match, |
GLuint start, |
GLuint n ); |
typedef void (*trans_elt_1ui_func)(GLuint *to, |
CONST void *ptr, |
GLuint stride, |
GLuint *flags, |
GLuint *elts, |
GLuint match, |
GLuint start, |
GLuint n ); |
typedef void (*trans_elt_1ub_func)(GLubyte *to, |
CONST void *ptr, |
GLuint stride, |
GLuint *flags, |
GLuint *elts, |
GLuint match, |
GLuint start, |
GLuint n ); |
typedef void (*trans_elt_4ub_func)(GLubyte (*to)[4], |
CONST void *ptr, |
GLuint stride, |
GLuint *flags, |
GLuint *elts, |
GLuint match, |
GLuint start, |
GLuint n ); |
typedef void (*trans_elt_4us_func)(GLushort (*to)[4], |
CONST void *ptr, |
GLuint stride, |
GLuint *flags, |
GLuint *elts, |
GLuint match, |
GLuint start, |
GLuint n ); |
typedef void (*trans_elt_4f_func)(GLfloat (*to)[4], |
CONST void *ptr, |
GLuint stride, |
GLuint *flags, |
GLuint *elts, |
GLuint match, |
GLuint start, |
GLuint n ); |
typedef void (*trans_elt_3f_func)(GLfloat (*to)[3], |
CONST void *ptr, |
GLuint stride, |
GLuint *flags, |
GLuint *elts, |
GLuint match, |
GLuint start, |
GLuint n ); |
static trans_elt_1f_func _tnl_trans_elt_1f_tab[MAX_TYPES]; |
static trans_elt_1ui_func _tnl_trans_elt_1ui_tab[MAX_TYPES]; |
static trans_elt_1ub_func _tnl_trans_elt_1ub_tab[MAX_TYPES]; |
static trans_elt_3f_func _tnl_trans_elt_3f_tab[MAX_TYPES]; |
static trans_elt_4ub_func _tnl_trans_elt_4ub_tab[5][MAX_TYPES]; |
static trans_elt_4us_func _tnl_trans_elt_4us_tab[5][MAX_TYPES]; |
static trans_elt_4f_func _tnl_trans_elt_4f_tab[5][MAX_TYPES]; |
#define PTR_ELT(ptr, elt) (((SRC *)ptr)[elt]) |
/* Code specific to array element implementation. There is a small |
* subtlety in the bits CHECK() tests, and the way bits are set in |
* glArrayElement which ensures that if, eg, in the case that the |
* vertex array is disabled and normal array is enabled, and we get |
* either sequence: |
* |
* ArrayElement() OR Normal() |
* Normal() ArrayElement() |
* Vertex() Vertex() |
* |
* That the correct value for normal is used. |
*/ |
#define TAB(x) _tnl_trans_elt##x##_tab |
#define ARGS GLuint *flags, GLuint *elts, GLuint match, \ |
GLuint start, GLuint n |
#define SRC_START 0 |
#define DST_START start |
#define CHECK if ((flags[i]&match) == VERT_BIT_ELT) |
#define NEXT_F (void)1 |
#define NEXT_F2 f = first + elts[i] * stride; |
/* GL_BYTE |
*/ |
#define SRC GLbyte |
#define SRC_IDX TYPE_IDX(GL_BYTE) |
#define TRX_3F(f,n) BYTE_TO_FLOAT( PTR_ELT(f,n) ) |
#define TRX_4F(f,n) BYTE_TO_FLOAT( PTR_ELT(f,n) ) |
#define TRX_UB(ub, f,n) ub = BYTE_TO_UBYTE( PTR_ELT(f,n) ) |
#define TRX_US(us, f,n) us = BYTE_TO_USHORT( PTR_ELT(f,n) ) |
#define TRX_UI(f,n) (PTR_ELT(f,n) < 0 ? 0 : (GLuint) PTR_ELT(f,n)) |
#define SZ 4 |
#define INIT init_trans_4_GLbyte_elt |
#define DEST_4F trans_4_GLbyte_4f_elt |
#define DEST_4UB trans_4_GLbyte_4ub_elt |
#define DEST_4US trans_4_GLbyte_4us_elt |
#include "math/m_trans_tmp.h" |
#define SZ 3 |
#define INIT init_trans_3_GLbyte_elt |
#define DEST_4F trans_3_GLbyte_4f_elt |
#define DEST_4UB trans_3_GLbyte_4ub_elt |
#define DEST_4US trans_3_GLbyte_4us_elt |
#define DEST_3F trans_3_GLbyte_3f_elt |
#include "math/m_trans_tmp.h" |
#define SZ 2 |
#define INIT init_trans_2_GLbyte_elt |
#define DEST_4F trans_2_GLbyte_4f_elt |
#include "math/m_trans_tmp.h" |
#define SZ 1 |
#define INIT init_trans_1_GLbyte_elt |
#define DEST_4F trans_1_GLbyte_4f_elt |
#define DEST_1UB trans_1_GLbyte_1ub_elt |
#define DEST_1UI trans_1_GLbyte_1ui_elt |
#include "math/m_trans_tmp.h" |
#undef SRC |
#undef TRX_3F |
#undef TRX_4F |
#undef TRX_UB |
#undef TRX_US |
#undef TRX_UI |
#undef SRC_IDX |
/* GL_UNSIGNED_BYTE |
*/ |
#define SRC GLubyte |
#define SRC_IDX TYPE_IDX(GL_UNSIGNED_BYTE) |
#define TRX_3F(f,n) UBYTE_TO_FLOAT( PTR_ELT(f,n) ) |
#define TRX_4F(f,n) UBYTE_TO_FLOAT( PTR_ELT(f,n) ) |
#define TRX_UB(ub, f,n) ub = PTR_ELT(f,n) |
#define TRX_US(us, f,n) us = PTR_ELT(f,n) |
#define TRX_UI(f,n) (GLuint)PTR_ELT(f,n) |
/* 4ub->4ub handled in special case below. |
*/ |
#define SZ 4 |
#define INIT init_trans_4_GLubyte_elt |
#define DEST_4F trans_4_GLubyte_4f_elt |
#define DEST_4US trans_4_GLubyte_4us_elt |
#include "math/m_trans_tmp.h" |
#define SZ 3 |
#define INIT init_trans_3_GLubyte_elt |
#define DEST_4F trans_3_GLubyte_4f_elt |
#define DEST_3F trans_3_GLubyte_3f_elt |
#define DEST_4UB trans_3_GLubyte_4ub_elt |
#define DEST_4US trans_3_GLubyte_4us_elt |
#include "math/m_trans_tmp.h" |
#define SZ 1 |
#define INIT init_trans_1_GLubyte_elt |
#define DEST_1UI trans_1_GLubyte_1ui_elt |
#define DEST_1UB trans_1_GLubyte_1ub_elt |
#include "math/m_trans_tmp.h" |
#undef SRC |
#undef SRC_IDX |
#undef TRX_3F |
#undef TRX_4F |
#undef TRX_UB |
#undef TRX_US |
#undef TRX_UI |
/* GL_SHORT |
*/ |
#define SRC GLshort |
#define SRC_IDX TYPE_IDX(GL_SHORT) |
#define TRX_3F(f,n) SHORT_TO_FLOAT( PTR_ELT(f,n) ) |
#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) ) |
#define TRX_UB(ub, f,n) ub = SHORT_TO_UBYTE(PTR_ELT(f,n)) |
#define TRX_US(us, f,n) us = SHORT_TO_USHORT(PTR_ELT(f,n)) |
#define TRX_UI(f,n) (PTR_ELT(f,n) < 0 ? 0 : (GLuint) PTR_ELT(f,n)) |
#define SZ 4 |
#define INIT init_trans_4_GLshort_elt |
#define DEST_4F trans_4_GLshort_4f_elt |
#define DEST_4UB trans_4_GLshort_4ub_elt |
#define DEST_4US trans_4_GLshort_4us_elt |
#include "math/m_trans_tmp.h" |
#define SZ 3 |
#define INIT init_trans_3_GLshort_elt |
#define DEST_4F trans_3_GLshort_4f_elt |
#define DEST_4UB trans_3_GLshort_4ub_elt |
#define DEST_4US trans_3_GLshort_4us_elt |
#define DEST_3F trans_3_GLshort_3f_elt |
#include "math/m_trans_tmp.h" |
#define SZ 2 |
#define INIT init_trans_2_GLshort_elt |
#define DEST_4F trans_2_GLshort_4f_elt |
#include "math/m_trans_tmp.h" |
#define SZ 1 |
#define INIT init_trans_1_GLshort_elt |
#define DEST_4F trans_1_GLshort_4f_elt |
#define DEST_1UB trans_1_GLshort_1ub_elt |
#define DEST_1UI trans_1_GLshort_1ui_elt |
#include "math/m_trans_tmp.h" |
#undef SRC |
#undef SRC_IDX |
#undef TRX_3F |
#undef TRX_4F |
#undef TRX_UB |
#undef TRX_US |
#undef TRX_UI |
/* GL_UNSIGNED_SHORT |
*/ |
#define SRC GLushort |
#define SRC_IDX TYPE_IDX(GL_UNSIGNED_SHORT) |
#define TRX_3F(f,n) USHORT_TO_FLOAT( PTR_ELT(f,n) ) |
#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) ) |
#define TRX_UB(ub,f,n) ub = (GLubyte) (PTR_ELT(f,n) >> 8) |
#define TRX_US(us,f,n) us = PTR_ELT(f,n) |
#define TRX_UI(f,n) (GLuint) PTR_ELT(f,n) |
#define SZ 4 |
#define INIT init_trans_4_GLushort_elt |
#define DEST_4F trans_4_GLushort_4f_elt |
#define DEST_4UB trans_4_GLushort_4ub_elt |
#define DEST_4US trans_4_GLushort_4us_elt |
#include "math/m_trans_tmp.h" |
#define SZ 3 |
#define INIT init_trans_3_GLushort_elt |
#define DEST_4F trans_3_GLushort_4f_elt |
#define DEST_4UB trans_3_GLushort_4ub_elt |
#define DEST_4US trans_3_GLushort_4us_elt |
#define DEST_3F trans_3_GLushort_3f_elt |
#include "math/m_trans_tmp.h" |
#define SZ 2 |
#define INIT init_trans_2_GLushort_elt |
#define DEST_4F trans_2_GLushort_4f_elt |
#include "math/m_trans_tmp.h" |
#define SZ 1 |
#define INIT init_trans_1_GLushort_elt |
#define DEST_4F trans_1_GLushort_4f_elt |
#define DEST_1UB trans_1_GLushort_1ub_elt |
#define DEST_1UI trans_1_GLushort_1ui_elt |
#include "math/m_trans_tmp.h" |
#undef SRC |
#undef SRC_IDX |
#undef TRX_3F |
#undef TRX_4F |
#undef TRX_UB |
#undef TRX_US |
#undef TRX_UI |
/* GL_INT |
*/ |
#define SRC GLint |
#define SRC_IDX TYPE_IDX(GL_INT) |
#define TRX_3F(f,n) INT_TO_FLOAT( PTR_ELT(f,n) ) |
#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) ) |
#define TRX_UB(ub, f,n) ub = INT_TO_UBYTE(PTR_ELT(f,n)) |
#define TRX_US(us, f,n) us = INT_TO_USHORT(PTR_ELT(f,n)) |
#define TRX_UI(f,n) (PTR_ELT(f,n) < 0 ? 0 : (GLuint) PTR_ELT(f,n)) |
#define SZ 4 |
#define INIT init_trans_4_GLint_elt |
#define DEST_4F trans_4_GLint_4f_elt |
#define DEST_4UB trans_4_GLint_4ub_elt |
#define DEST_4US trans_4_GLint_4us_elt |
#include "math/m_trans_tmp.h" |
#define SZ 3 |
#define INIT init_trans_3_GLint_elt |
#define DEST_4F trans_3_GLint_4f_elt |
#define DEST_4UB trans_3_GLint_4ub_elt |
#define DEST_4US trans_3_GLint_4us_elt |
#define DEST_3F trans_3_GLint_3f_elt |
#include "math/m_trans_tmp.h" |
#define SZ 2 |
#define INIT init_trans_2_GLint_elt |
#define DEST_4F trans_2_GLint_4f_elt |
#include "math/m_trans_tmp.h" |
#define SZ 1 |
#define INIT init_trans_1_GLint_elt |
#define DEST_4F trans_1_GLint_4f_elt |
#define DEST_1UB trans_1_GLint_1ub_elt |
#define DEST_1UI trans_1_GLint_1ui_elt |
#include "math/m_trans_tmp.h" |
#undef SRC |
#undef SRC_IDX |
#undef TRX_3F |
#undef TRX_4F |
#undef TRX_UB |
#undef TRX_US |
#undef TRX_UI |
/* GL_UNSIGNED_INT |
*/ |
#define SRC GLuint |
#define SRC_IDX TYPE_IDX(GL_UNSIGNED_INT) |
#define TRX_3F(f,n) UINT_TO_FLOAT( PTR_ELT(f,n) ) |
#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) ) |
#define TRX_UB(ub, f,n) ub = (GLubyte) (PTR_ELT(f,n) >> 24) |
#define TRX_US(us, f,n) us = (GLushort) (PTR_ELT(f,n) >> 16) |
#define TRX_UI(f,n) PTR_ELT(f,n) |
#define SZ 4 |
#define INIT init_trans_4_GLuint_elt |
#define DEST_4F trans_4_GLuint_4f_elt |
#define DEST_4UB trans_4_GLuint_4ub_elt |
#define DEST_4US trans_4_GLuint_4us_elt |
#include "math/m_trans_tmp.h" |
#define SZ 3 |
#define INIT init_trans_3_GLuint_elt |
#define DEST_4F trans_3_GLuint_4f_elt |
#define DEST_4UB trans_3_GLuint_4ub_elt |
#define DEST_4US trans_3_GLuint_4us_elt |
#define DEST_3F trans_3_GLuint_3f_elt |
#include "math/m_trans_tmp.h" |
#define SZ 2 |
#define INIT init_trans_2_GLuint_elt |
#define DEST_4F trans_2_GLuint_4f_elt |
#include "math/m_trans_tmp.h" |
#define SZ 1 |
#define INIT init_trans_1_GLuint_elt |
#define DEST_4F trans_1_GLuint_4f_elt |
#define DEST_1UB trans_1_GLuint_1ub_elt |
#define DEST_1UI trans_1_GLuint_1ui_elt |
#include "math/m_trans_tmp.h" |
#undef SRC |
#undef SRC_IDX |
#undef TRX_3F |
#undef TRX_4F |
#undef TRX_UB |
#undef TRX_US |
#undef TRX_UI |
/* GL_DOUBLE |
*/ |
#define SRC GLdouble |
#define SRC_IDX TYPE_IDX(GL_DOUBLE) |
#define TRX_3F(f,n) (GLfloat) PTR_ELT(f,n) |
#define TRX_4F(f,n) (GLfloat) PTR_ELT(f,n) |
#define TRX_UB(ub,f,n) UNCLAMPED_FLOAT_TO_UBYTE(ub, PTR_ELT(f,n)) |
#define TRX_US(us,f,n) UNCLAMPED_FLOAT_TO_USHORT(us, PTR_ELT(f,n)) |
#define TRX_UI(f,n) (GLuint) (GLint) PTR_ELT(f,n) |
#define TRX_1F(f,n) (GLfloat) PTR_ELT(f,n) |
#define SZ 4 |
#define INIT init_trans_4_GLdouble_elt |
#define DEST_4F trans_4_GLdouble_4f_elt |
#define DEST_4UB trans_4_GLdouble_4ub_elt |
#define DEST_4US trans_4_GLdouble_4us_elt |
#include "math/m_trans_tmp.h" |
#define SZ 3 |
#define INIT init_trans_3_GLdouble_elt |
#define DEST_4F trans_3_GLdouble_4f_elt |
#define DEST_4UB trans_3_GLdouble_4ub_elt |
#define DEST_4US trans_3_GLdouble_4us_elt |
#define DEST_3F trans_3_GLdouble_3f_elt |
#include "math/m_trans_tmp.h" |
#define SZ 2 |
#define INIT init_trans_2_GLdouble_elt |
#define DEST_4F trans_2_GLdouble_4f_elt |
#include "math/m_trans_tmp.h" |
#define SZ 1 |
#define INIT init_trans_1_GLdouble_elt |
#define DEST_4F trans_1_GLdouble_4f_elt |
#define DEST_1UB trans_1_GLdouble_1ub_elt |
#define DEST_1UI trans_1_GLdouble_1ui_elt |
#define DEST_1F trans_1_GLdouble_1f_elt |
#include "math/m_trans_tmp.h" |
#undef SRC |
#undef SRC_IDX |
/* GL_FLOAT |
*/ |
#define SRC GLfloat |
#define SRC_IDX TYPE_IDX(GL_FLOAT) |
#define SZ 4 |
#define INIT init_trans_4_GLfloat_elt |
#define DEST_4UB trans_4_GLfloat_4ub_elt |
#define DEST_4US trans_4_GLfloat_4us_elt |
#define DEST_4F trans_4_GLfloat_4f_elt |
#include "math/m_trans_tmp.h" |
#define SZ 3 |
#define INIT init_trans_3_GLfloat_elt |
#define DEST_4F trans_3_GLfloat_4f_elt |
#define DEST_4UB trans_3_GLfloat_4ub_elt |
#define DEST_4US trans_3_GLfloat_4us_elt |
#define DEST_3F trans_3_GLfloat_3f_elt |
#include "math/m_trans_tmp.h" |
#define SZ 2 |
#define INIT init_trans_2_GLfloat_elt |
#define DEST_4F trans_2_GLfloat_4f_elt |
#include "math/m_trans_tmp.h" |
#define SZ 1 |
#define INIT init_trans_1_GLfloat_elt |
#define DEST_4F trans_1_GLfloat_3f_elt |
#define DEST_1UB trans_1_GLfloat_1ub_elt |
#define DEST_1UI trans_1_GLfloat_1ui_elt |
#define DEST_1F trans_1_GLfloat_1f_elt |
#include "math/m_trans_tmp.h" |
#undef SRC |
#undef SRC_IDX |
#undef TRX_3F |
#undef TRX_4F |
#undef TRX_UB |
#undef TRX_US |
#undef TRX_UI |
static void trans_4_GLubyte_4ub(GLubyte (*t)[4], |
CONST void *Ptr, |
GLuint stride, |
ARGS ) |
{ |
const GLubyte *f = (GLubyte *) Ptr + SRC_START * stride; |
const GLubyte *first = f; |
GLuint i; |
(void) start; |
if (((((long) f | (long) stride)) & 3L) == 0L) { |
/* Aligned. |
*/ |
for (i = DST_START ; i < n ; i++, NEXT_F) { |
CHECK { |
NEXT_F2; |
COPY_4UBV( t[i], f ); |
} |
} |
} else { |
for (i = DST_START ; i < n ; i++, NEXT_F) { |
CHECK { |
NEXT_F2; |
t[i][0] = f[0]; |
t[i][1] = f[1]; |
t[i][2] = f[2]; |
t[i][3] = f[3]; |
} |
} |
} |
} |
static void init_translate_elt(void) |
{ |
MEMSET( TAB(_1ui), 0, sizeof(TAB(_1ui)) ); |
MEMSET( TAB(_1ub), 0, sizeof(TAB(_1ub)) ); |
MEMSET( TAB(_3f), 0, sizeof(TAB(_3f)) ); |
MEMSET( TAB(_4ub), 0, sizeof(TAB(_4ub)) ); |
MEMSET( TAB(_4us), 0, sizeof(TAB(_4us)) ); |
MEMSET( TAB(_4f), 0, sizeof(TAB(_4f)) ); |
TAB(_4ub)[4][TYPE_IDX(GL_UNSIGNED_BYTE)] = trans_4_GLubyte_4ub; |
init_trans_4_GLbyte_elt(); |
init_trans_3_GLbyte_elt(); |
init_trans_2_GLbyte_elt(); |
init_trans_1_GLbyte_elt(); |
init_trans_1_GLubyte_elt(); |
init_trans_3_GLubyte_elt(); |
init_trans_4_GLubyte_elt(); |
init_trans_4_GLshort_elt(); |
init_trans_3_GLshort_elt(); |
init_trans_2_GLshort_elt(); |
init_trans_1_GLshort_elt(); |
init_trans_4_GLushort_elt(); |
init_trans_3_GLushort_elt(); |
init_trans_2_GLushort_elt(); |
init_trans_1_GLushort_elt(); |
init_trans_4_GLint_elt(); |
init_trans_3_GLint_elt(); |
init_trans_2_GLint_elt(); |
init_trans_1_GLint_elt(); |
init_trans_4_GLuint_elt(); |
init_trans_3_GLuint_elt(); |
init_trans_2_GLuint_elt(); |
init_trans_1_GLuint_elt(); |
init_trans_4_GLdouble_elt(); |
init_trans_3_GLdouble_elt(); |
init_trans_2_GLdouble_elt(); |
init_trans_1_GLdouble_elt(); |
init_trans_4_GLfloat_elt(); |
init_trans_3_GLfloat_elt(); |
init_trans_2_GLfloat_elt(); |
init_trans_1_GLfloat_elt(); |
} |
#undef TAB |
#undef CLASS |
#undef ARGS |
#undef CHECK |
#undef START |
void _tnl_imm_elt_init( void ) |
{ |
init_translate_elt(); |
} |
#if 00 |
static void _tnl_trans_elt_1f(GLfloat *to, |
const struct gl_client_array *from, |
GLuint *flags, |
GLuint *elts, |
GLuint match, |
GLuint start, |
GLuint n ) |
{ |
_tnl_trans_elt_1f_tab[TYPE_IDX(from->Type)]( to, |
from->Ptr, |
from->StrideB, |
flags, |
elts, |
match, |
start, |
n ); |
} |
#endif |
static void _tnl_trans_elt_1ui(GLuint *to, |
const struct gl_client_array *from, |
GLuint *flags, |
GLuint *elts, |
GLuint match, |
GLuint start, |
GLuint n ) |
{ |
_tnl_trans_elt_1ui_tab[TYPE_IDX(from->Type)]( to, |
from->Ptr, |
from->StrideB, |
flags, |
elts, |
match, |
start, |
n ); |
} |
static void _tnl_trans_elt_1ub(GLubyte *to, |
const struct gl_client_array *from, |
GLuint *flags, |
GLuint *elts, |
GLuint match, |
GLuint start, |
GLuint n ) |
{ |
_tnl_trans_elt_1ub_tab[TYPE_IDX(from->Type)]( to, |
from->Ptr, |
from->StrideB, |
flags, |
elts, |
match, |
start, |
n ); |
} |
#if 0 |
static void _tnl_trans_elt_4ub(GLubyte (*to)[4], |
const struct gl_client_array *from, |
GLuint *flags, |
GLuint *elts, |
GLuint match, |
GLuint start, |
GLuint n ) |
{ |
_tnl_trans_elt_4ub_tab[from->Size][TYPE_IDX(from->Type)]( to, |
from->Ptr, |
from->StrideB, |
flags, |
elts, |
match, |
start, |
n ); |
} |
#endif |
#if 0 |
static void _tnl_trans_elt_4us(GLushort (*to)[4], |
const struct gl_client_array *from, |
GLuint *flags, |
GLuint *elts, |
GLuint match, |
GLuint start, |
GLuint n ) |
{ |
_tnl_trans_elt_4us_tab[from->Size][TYPE_IDX(from->Type)]( to, |
from->Ptr, |
from->StrideB, |
flags, |
elts, |
match, |
start, |
n ); |
} |
#endif |
static void _tnl_trans_elt_4f(GLfloat (*to)[4], |
const struct gl_client_array *from, |
GLuint *flags, |
GLuint *elts, |
GLuint match, |
GLuint start, |
GLuint n ) |
{ |
_tnl_trans_elt_4f_tab[from->Size][TYPE_IDX(from->Type)]( to, |
from->Ptr, |
from->StrideB, |
flags, |
elts, |
match, |
start, |
n ); |
} |
#if 0 |
static void _tnl_trans_elt_3f(GLfloat (*to)[3], |
const struct gl_client_array *from, |
GLuint *flags, |
GLuint *elts, |
GLuint match, |
GLuint start, |
GLuint n ) |
{ |
_tnl_trans_elt_3f_tab[TYPE_IDX(from->Type)]( to, |
from->Ptr, |
from->StrideB, |
flags, |
elts, |
match, |
start, |
n ); |
} |
#endif |
/* Batch function to translate away all the array elements in the |
* input buffer prior to transform. Done only the first time a vertex |
* buffer is executed or compiled. |
* |
* KW: Have to do this after each glEnd if arrays aren't locked. |
*/ |
void _tnl_translate_array_elts( GLcontext *ctx, struct immediate *IM, |
GLuint start, GLuint count ) |
{ |
GLuint *flags = IM->Flag; |
GLuint *elts = IM->Elt; |
GLuint translate = ctx->Array._Enabled; |
GLuint i; |
if (MESA_VERBOSE & VERBOSE_IMMEDIATE) |
_mesa_debug(ctx, "exec_array_elements %d .. %d\n", start, count); |
if (translate & VERT_BIT_POS) { |
_tnl_trans_elt_4f( IM->Attrib[VERT_ATTRIB_POS], |
&ctx->Array.Vertex, |
flags, elts, (VERT_BIT_ELT|VERT_BIT_POS), |
start, count); |
if (ctx->Array.Vertex.Size == 4) |
translate |= VERT_BITS_OBJ_234; |
else if (ctx->Array.Vertex.Size == 3) |
translate |= VERT_BITS_OBJ_23; |
} |
if (translate & VERT_BIT_NORMAL) |
_tnl_trans_elt_4f( IM->Attrib[VERT_ATTRIB_NORMAL], |
&ctx->Array.Normal, |
flags, elts, (VERT_BIT_ELT|VERT_BIT_NORMAL), |
start, count); |
if (translate & VERT_BIT_EDGEFLAG) |
_tnl_trans_elt_1ub( IM->EdgeFlag, |
&ctx->Array.EdgeFlag, |
flags, elts, (VERT_BIT_ELT|VERT_BIT_EDGEFLAG), |
start, count); |
if (translate & VERT_BIT_COLOR0) { |
_tnl_trans_elt_4f( IM->Attrib[VERT_ATTRIB_COLOR0], |
&ctx->Array.Color, |
flags, elts, (VERT_BIT_ELT|VERT_BIT_COLOR0), |
start, count); |
} |
if (translate & VERT_BIT_COLOR1) { |
_tnl_trans_elt_4f( IM->Attrib[VERT_ATTRIB_COLOR1], |
&ctx->Array.SecondaryColor, |
flags, elts, (VERT_BIT_ELT|VERT_BIT_COLOR1), |
start, count); |
} |
if (translate & VERT_BIT_FOG) |
_tnl_trans_elt_4f( IM->Attrib[VERT_ATTRIB_FOG], |
&ctx->Array.FogCoord, |
flags, elts, (VERT_BIT_ELT|VERT_BIT_FOG), |
start, count); |
if (translate & VERT_BIT_INDEX) |
_tnl_trans_elt_1ui( IM->Index, |
&ctx->Array.Index, |
flags, elts, (VERT_BIT_ELT|VERT_BIT_INDEX), |
start, count); |
if (translate & VERT_BITS_TEX_ANY) { |
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) |
if (translate & VERT_BIT_TEX(i)) { |
_tnl_trans_elt_4f( IM->Attrib[VERT_ATTRIB_TEX0 + i], |
&ctx->Array.TexCoord[i], |
flags, elts, (VERT_BIT_ELT|VERT_BIT_TEX(i)), |
start, count); |
if (ctx->Array.TexCoord[i].Size == 4) |
IM->TexSize |= TEX_SIZE_4(i); |
else if (ctx->Array.TexCoord[i].Size == 3) |
IM->TexSize |= TEX_SIZE_3(i); |
} |
} |
for (i = start ; i < count ; i++) |
if (flags[i] & VERT_BIT_ELT) flags[i] |= translate; |
IM->FlushElt = 0; |
} |
/shark/trunk/ports/mesa/src/tnl/t_imm_exec.c |
---|
0,0 → 1,598 |
/* $Id: t_imm_exec.c,v 1.1 2003-02-28 11:48:07 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. |
*/ |
/** |
* \file tnl/t_imm_exec.c |
* \brief Setup to execute immediate-mode vertex data. |
* \author Keith Whitwell |
*/ |
#include "glheader.h" |
#include "colormac.h" |
#include "context.h" |
#include "enums.h" |
#include "dlist.h" |
#include "macros.h" |
#include "imports.h" |
#include "mmath.h" |
#include "light.h" |
#include "state.h" |
#include "mtypes.h" |
#include "math/m_matrix.h" |
#include "math/m_xform.h" |
#include "t_context.h" |
#include "t_array_import.h" |
#include "t_imm_alloc.h" |
#include "t_imm_api.h" |
#include "t_imm_debug.h" |
#include "t_imm_dlist.h" |
#include "t_imm_eval.h" |
#include "t_imm_elt.h" |
#include "t_imm_exec.h" |
#include "t_imm_fixup.h" |
#include "t_pipeline.h" |
static void reset_input( GLcontext *ctx, |
GLuint start, |
GLuint beginstate, |
GLuint savedbeginstate ) |
{ |
struct immediate *IM = TNL_CURRENT_IM(ctx); |
/* Clear the dirty part of the flag array. |
*/ |
if (start < IM->Count+2) |
MEMSET(IM->Flag + start, 0, sizeof(GLuint) * (IM->Count+2-start)); |
if (MESA_VERBOSE & VERBOSE_IMMEDIATE) |
_mesa_debug(ctx, "reset_input: IM(%d) new %x\n", IM->id, beginstate); |
IM->Start = start; |
IM->Count = start; |
IM->LastMaterial = start; |
IM->BeginState = beginstate; |
IM->SavedBeginState = savedbeginstate; |
IM->TexSize = 0; |
IM->MaterialOrMask = 0; |
if (IM->MaterialMask) |
IM->MaterialMask[IM->Start] = 0; |
IM->ArrayEltFlags = ~ctx->Array._Enabled; |
IM->ArrayEltIncr = ctx->Array.Vertex.Enabled ? 1 : 0; |
IM->ArrayEltFlush = ctx->Array.LockCount ? FLUSH_ELT_LAZY : FLUSH_ELT_EAGER; |
} |
void _tnl_reset_exec_input( GLcontext *ctx, |
GLuint start, |
GLuint beginstate, |
GLuint savedbeginstate ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct immediate *IM = TNL_CURRENT_IM(ctx); |
reset_input( ctx, start, beginstate, savedbeginstate ); |
IM->CopyStart = start - tnl->ExecCopyCount; |
IM->Primitive[IM->CopyStart] = ctx->Driver.CurrentExecPrimitive; |
if (tnl->ExecParity) |
IM->Primitive[IM->CopyStart] |= PRIM_PARITY; |
IM->LastPrimitive = IM->CopyStart; |
} |
void _tnl_reset_compile_input( GLcontext *ctx, |
GLuint start, |
GLuint beginstate, |
GLuint savedbeginstate ) |
{ |
struct immediate *IM = TNL_CURRENT_IM(ctx); |
reset_input( ctx, start, beginstate, savedbeginstate ); |
IM->CopyStart = start; |
IM->LastPrimitive = IM->Start; |
} |
/** |
* Copy the last specified normal, color, texcoord, edge flag, etc |
* from the immediate struct into the ctx->Current attribute group. |
*/ |
void _tnl_copy_to_current( GLcontext *ctx, struct immediate *IM, |
GLuint flag, GLuint count ) |
{ |
if (MESA_VERBOSE&VERBOSE_IMMEDIATE) |
_tnl_print_vert_flags("copy to current", flag); |
/* XXX should be able to replace these conditions with a loop over |
* the 16 vertex attributes. |
*/ |
if (flag & VERT_BIT_NORMAL) |
COPY_4FV( ctx->Current.Attrib[VERT_ATTRIB_NORMAL], |
IM->Attrib[VERT_ATTRIB_NORMAL][count]); |
if (flag & VERT_BIT_INDEX) |
ctx->Current.Index = IM->Index[count]; |
if (flag & VERT_BIT_EDGEFLAG) |
ctx->Current.EdgeFlag = IM->EdgeFlag[count]; |
if (flag & VERT_BIT_COLOR0) { |
COPY_4FV(ctx->Current.Attrib[VERT_ATTRIB_COLOR0], |
IM->Attrib[VERT_ATTRIB_COLOR0][count]); |
if (ctx->Light.ColorMaterialEnabled) { |
_mesa_update_color_material( ctx, |
ctx->Current.Attrib[VERT_ATTRIB_COLOR0] ); |
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx ); |
} |
} |
if (flag & VERT_BIT_COLOR1) |
COPY_4FV(ctx->Current.Attrib[VERT_ATTRIB_COLOR1], |
IM->Attrib[VERT_ATTRIB_COLOR1][count]); |
if (flag & VERT_BIT_FOG) |
ctx->Current.Attrib[VERT_ATTRIB_FOG][0] = IM->Attrib[VERT_ATTRIB_FOG][count][0]; |
if (flag & VERT_BITS_TEX_ANY) { |
GLuint i; |
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) { |
if (flag & VERT_BIT_TEX(i)) { |
COPY_4FV( ctx->Current.Attrib[VERT_ATTRIB_TEX0 + i], |
IM->Attrib[VERT_ATTRIB_TEX0 + i][count]); |
} |
} |
} |
if (flag & VERT_BIT_MATERIAL) { |
_mesa_update_material( ctx, |
IM->Material[IM->LastMaterial], |
IM->MaterialOrMask ); |
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx ); |
} |
} |
void _tnl_compute_orflag( struct immediate *IM, GLuint start ) |
{ |
GLuint count = IM->Count; |
GLuint orflag = 0; |
GLuint andflag = ~0U; |
GLuint i; |
IM->LastData = count-1; |
/* Compute the flags for the whole buffer. |
*/ |
for (i = start ; i < count ; i++) { |
andflag &= IM->Flag[i]; |
orflag |= IM->Flag[i]; |
} |
/* It is possible there will be data in the buffer arising from |
* calls like 'glNormal', 'glMaterial' that occur after the final |
* glVertex, glEval, etc. Additionally, a buffer can consist of |
* eg. a single glMaterial call, in which case IM->Start == |
* IM->Count, but the buffer is definitely not empty. |
*/ |
if (IM->Flag[i] & VERT_BITS_DATA) { |
IM->LastData++; |
orflag |= IM->Flag[i]; |
} |
IM->Flag[IM->LastData+1] |= VERT_BIT_END_VB; |
IM->CopyAndFlag = IM->AndFlag = andflag; |
IM->OrFlag = orflag; |
IM->CopyOrFlag = orflag; |
IM->Evaluated = 0; |
} |
/** |
* This is where the vertex data is transfered from the 'struct immediate |
* into the 'struct vertex_buffer'. |
* |
* Note: The 'start' member of the GLvector structs is now redundant |
* because we always re-transform copied vertices, and the vectors |
* below are set up so that the first copied vertex (if any) appears |
* at position zero. |
*/ |
static void _tnl_vb_bind_immediate( GLcontext *ctx, struct immediate *IM ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_buffer *VB = &tnl->vb; |
struct vertex_arrays *tmp = &tnl->imm_inputs; |
GLuint inputs = tnl->pipeline.inputs; /* for copy-to-current */ |
const GLuint start = IM->CopyStart; |
const GLuint count = IM->Count - start; |
/* TODO: optimize the case where nothing has changed. (Just bind |
* tmp to vb). |
*/ |
/* Setup constant data in the VB. |
*/ |
VB->Count = count; |
VB->FirstClipped = IMM_MAXDATA - IM->CopyStart; |
VB->import_data = NULL; |
VB->importable_data = 0; |
/* Need an IM->FirstPrimitive? |
*/ |
VB->Primitive = IM->Primitive + IM->CopyStart; |
VB->PrimitiveLength = IM->PrimitiveLength + IM->CopyStart; |
VB->FirstPrimitive = 0; |
VB->Flag = IM->Flag + start; |
/* TexCoordPtr's are zeroed in loop below. |
*/ |
VB->NormalPtr = NULL; |
VB->NormalLengthPtr = NULL; |
VB->EdgeFlag = NULL; |
VB->IndexPtr[0] = NULL; |
VB->IndexPtr[1] = NULL; |
VB->ColorPtr[0] = NULL; |
VB->ColorPtr[1] = NULL; |
VB->SecondaryColorPtr[0] = NULL; |
VB->SecondaryColorPtr[1] = NULL; |
VB->Elts = NULL; |
VB->MaterialMask = NULL; |
VB->Material = NULL; |
/* _tnl_print_vert_flags("copy-orflag", IM->CopyOrFlag); */ |
/* _tnl_print_vert_flags("orflag", IM->OrFlag); */ |
/* _tnl_print_vert_flags("inputs", inputs); */ |
/* Setup the initial values of array pointers in the vb. |
*/ |
if (inputs & VERT_BIT_POS) { |
tmp->Obj.data = IM->Attrib[VERT_ATTRIB_POS] + start; |
tmp->Obj.start = (GLfloat *)(IM->Attrib[VERT_ATTRIB_POS] + start); |
tmp->Obj.count = count; |
VB->ObjPtr = &tmp->Obj; |
if ((IM->CopyOrFlag & VERT_BITS_OBJ_234) == VERT_BITS_OBJ_234) |
tmp->Obj.size = 4; |
else if ((IM->CopyOrFlag & VERT_BITS_OBJ_234) == VERT_BITS_OBJ_23) |
tmp->Obj.size = 3; |
else |
tmp->Obj.size = 2; |
} |
if (inputs & VERT_BIT_NORMAL) { |
tmp->Normal.data = IM->Attrib[VERT_ATTRIB_NORMAL] + start; |
tmp->Normal.start = (GLfloat *) (IM->Attrib[VERT_ATTRIB_NORMAL] + start); |
tmp->Normal.count = count; |
tmp->Normal.size = 3; /* just to be safe */ |
VB->NormalPtr = &tmp->Normal; |
if (IM->NormalLengthPtr) |
VB->NormalLengthPtr = IM->NormalLengthPtr + start; |
} |
if (inputs & VERT_BIT_INDEX) { |
tmp->Index.count = count; |
tmp->Index.data = IM->Index + start; |
tmp->Index.start = IM->Index + start; |
VB->IndexPtr[0] = &tmp->Index; |
} |
if (inputs & VERT_BIT_FOG) { |
tmp->FogCoord.data = IM->Attrib[VERT_ATTRIB_FOG] + start; |
tmp->FogCoord.start = (GLfloat *) (IM->Attrib[VERT_ATTRIB_FOG] + start); |
tmp->FogCoord.count = count; |
VB->FogCoordPtr = &tmp->FogCoord; |
} |
if (inputs & VERT_BIT_COLOR1) { |
tmp->SecondaryColor.Ptr = IM->Attrib[VERT_ATTRIB_COLOR1] + start; |
VB->SecondaryColorPtr[0] = &tmp->SecondaryColor; |
} |
if (inputs & VERT_BIT_EDGEFLAG) { |
VB->EdgeFlag = IM->EdgeFlag + start; |
} |
if (inputs & VERT_BIT_COLOR0) { |
if (IM->CopyOrFlag & VERT_BIT_COLOR0) { |
tmp->Color.Ptr = IM->Attrib[VERT_ATTRIB_COLOR0] + start; |
tmp->Color.StrideB = 4 * sizeof(GLfloat); |
tmp->Color.Flags = 0; |
} |
else { |
tmp->Color.Ptr = ctx->Current.Attrib[VERT_ATTRIB_COLOR0]; |
tmp->Color.StrideB = 0; |
tmp->Color.Flags = CA_CLIENT_DATA; /* hack */ |
VB->import_source = IM; |
VB->importable_data |= VERT_BIT_COLOR0; |
VB->import_data = _tnl_upgrade_current_data; |
} |
VB->ColorPtr[0] = &tmp->Color; |
} |
if (inputs & VERT_BITS_TEX_ANY) { |
GLuint i; |
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) { |
VB->TexCoordPtr[i] = NULL; |
if (inputs & VERT_BIT_TEX(i)) { |
tmp->TexCoord[i].count = count; |
tmp->TexCoord[i].data = IM->Attrib[VERT_ATTRIB_TEX0 + i] + start; |
tmp->TexCoord[i].start = (GLfloat *)(IM->Attrib[VERT_ATTRIB_TEX0 + i] + start); |
tmp->TexCoord[i].size = 2; |
if (IM->TexSize & TEX_SIZE_3(i)) { |
tmp->TexCoord[i].size = 3; |
if (IM->TexSize & TEX_SIZE_4(i)) |
tmp->TexCoord[i].size = 4; |
} |
VB->TexCoordPtr[i] = &tmp->TexCoord[i]; |
} |
} |
} |
if ((inputs & IM->OrFlag & VERT_BIT_MATERIAL) && IM->Material) { |
VB->MaterialMask = IM->MaterialMask + start; |
VB->Material = IM->Material + start; |
} |
/* GL_NV_vertex_program */ |
if (ctx->VertexProgram.Enabled) { |
GLuint attr; |
for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { |
tmp->Attribs[attr].count = count; |
tmp->Attribs[attr].data = IM->Attrib[attr] + start; |
tmp->Attribs[attr].start = (GLfloat *) (IM->Attrib[attr] + start); |
tmp->Attribs[attr].size = 4; |
VB->AttribPtr[attr] = &(tmp->Attribs[attr]); |
} |
} |
} |
/** |
* Called by exec_vert_cassette, execute_compiled_cassette, but not |
* exec_elt_cassette. |
*/ |
void _tnl_run_cassette( GLcontext *ctx, struct immediate *IM ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
_tnl_vb_bind_immediate( ctx, IM ); |
if (IM->OrFlag & VERT_BITS_EVAL_ANY) |
_tnl_eval_immediate( ctx, IM ); |
/* Invalidate all stored data before and after run: |
*/ |
tnl->pipeline.run_input_changes |= tnl->pipeline.inputs; |
tnl->Driver.RunPipeline( ctx ); |
tnl->pipeline.run_input_changes |= tnl->pipeline.inputs; |
_tnl_copy_to_current( ctx, IM, IM->OrFlag, IM->LastData ); |
} |
/** |
* Called for regular vertex cassettes. |
*/ |
static void exec_vert_cassette( GLcontext *ctx, struct immediate *IM ) |
{ |
if (IM->FlushElt) { |
/* Orflag is computed twice, but only reach this code if app is |
* using a mixture of glArrayElement() and glVertex() while |
* arrays are locked (else would be in exec_elt_cassette now). |
*/ |
ASSERT(ctx->Array.LockCount); |
ASSERT(IM->FlushElt == FLUSH_ELT_LAZY); |
_tnl_translate_array_elts( ctx, IM, IM->CopyStart, IM->Count ); |
_tnl_compute_orflag( IM, IM->CopyStart ); |
} |
_tnl_fixup_input( ctx, IM ); |
/* _tnl_print_cassette( IM ); */ |
_tnl_run_cassette( ctx, IM ); |
} |
/* Called for pure, locked VERT_BIT_ELT cassettes instead of |
* _tnl_run_cassette. |
*/ |
static void exec_elt_cassette( GLcontext *ctx, struct immediate *IM ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_buffer *VB = &tnl->vb; |
_tnl_vb_bind_arrays( ctx, ctx->Array.LockFirst, ctx->Array.LockCount ); |
/* Take only elements and primitive information from the immediate: |
*/ |
VB->Elts = IM->Elt + IM->CopyStart; |
VB->Primitive = IM->Primitive + IM->CopyStart; |
VB->PrimitiveLength = IM->PrimitiveLength + IM->CopyStart; |
VB->FirstPrimitive = 0; |
/* Run the pipeline. No input changes as a result of this action. |
*/ |
tnl->Driver.RunPipeline( ctx ); |
/* Still need to update current values: |
*/ |
if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) { |
_tnl_translate_array_elts( ctx, IM, IM->LastData, IM->LastData ); |
_tnl_copy_to_current( ctx, IM, ctx->Array._Enabled, IM->LastData ); |
} |
} |
static void |
exec_empty_cassette( GLcontext *ctx, struct immediate *IM ) |
{ |
if (IM->FlushElt) |
_tnl_translate_array_elts( ctx, IM, IM->CopyStart, IM->CopyStart ); |
_tnl_copy_to_current( ctx, IM, IM->OrFlag, IM->LastData ); |
} |
/** |
* Called for all cassettes when not compiling or playing a display |
* list. |
*/ |
void _tnl_execute_cassette( GLcontext *ctx, struct immediate *IM ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
_tnl_compute_orflag( IM, IM->Start ); |
_tnl_copy_immediate_vertices( ctx, IM ); |
_tnl_get_exec_copy_verts( ctx, IM ); |
if (tnl->pipeline.build_state_changes) |
_tnl_validate_pipeline( ctx ); |
if (IM->CopyStart == IM->Count) { |
exec_empty_cassette( ctx, IM ); |
} |
else if ((IM->CopyOrFlag & VERT_BITS_DATA) == VERT_BIT_ELT && |
ctx->Array.LockCount && |
ctx->Array.Vertex.Enabled) { |
exec_elt_cassette( ctx, IM ); |
} |
else { |
exec_vert_cassette( ctx, IM ); |
} |
/* Only reuse the immediate if there are no copied vertices living |
* inside it: |
*/ |
{ |
GLuint begin_state = IM->BeginState & (VERT_BEGIN_0|VERT_BEGIN_1); |
GLuint saved_begin_state = IM->SavedBeginState; |
if (--IM->ref_count != 0) { |
IM = _tnl_alloc_immediate( ctx ); |
SET_IMMEDIATE( ctx, IM ); |
} |
IM->ref_count++; |
_tnl_reset_exec_input( ctx, IMM_MAX_COPIED_VERTS, |
begin_state, saved_begin_state ); |
} |
if (ctx->Driver.CurrentExecPrimitive == GL_POLYGON+1) |
ctx->Driver.NeedFlush &= ~FLUSH_STORED_VERTICES; |
} |
/** |
* Setup vector pointers that will be used to bind immediates to VB's. |
*/ |
void _tnl_imm_init( GLcontext *ctx ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_arrays *tmp = &tnl->imm_inputs; |
GLuint i; |
static int firsttime = 1; |
if (firsttime) { |
firsttime = 0; |
_tnl_imm_elt_init(); |
} |
ctx->swtnl_im = _tnl_alloc_immediate( ctx ); |
TNL_CURRENT_IM(ctx)->ref_count++; |
tnl->ExecCopyTexSize = 0; |
tnl->ExecCopyCount = 0; |
tnl->ExecCopySource = 0; |
TNL_CURRENT_IM(ctx)->CopyStart = IMM_MAX_COPIED_VERTS; |
_mesa_vector4f_init( &tmp->Obj, 0, 0 ); |
_mesa_vector4f_init( &tmp->Normal, 0, 0 ); |
tmp->Color.Ptr = NULL; |
tmp->Color.Type = GL_FLOAT; |
tmp->Color.Size = 4; |
tmp->Color.Stride = 0; |
tmp->Color.StrideB = 4 * sizeof(GLfloat); |
tmp->Color.Flags = 0; |
tmp->SecondaryColor.Ptr = NULL; |
tmp->SecondaryColor.Type = GL_FLOAT; |
tmp->SecondaryColor.Size = 4; |
tmp->SecondaryColor.Stride = 0; |
tmp->SecondaryColor.StrideB = 4 * sizeof(GLfloat); |
tmp->SecondaryColor.Flags = 0; |
_mesa_vector4f_init( &tmp->FogCoord, 0, 0 ); |
_mesa_vector1ui_init( &tmp->Index, 0, 0 ); |
_mesa_vector1ub_init( &tmp->EdgeFlag, 0, 0 ); |
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) |
_mesa_vector4f_init( &tmp->TexCoord[i], 0, 0); |
/* Install the first immediate. Intially outside begin/end. |
*/ |
_tnl_reset_exec_input( ctx, IMM_MAX_COPIED_VERTS, 0, 0 ); |
tnl->ReplayHardBeginEnd = 0; |
_tnl_imm_vtxfmt_init( ctx ); |
} |
/** |
* Deallocate the immediate-mode buffer for the given context, if |
* its reference count goes to zero. |
*/ |
void _tnl_imm_destroy( GLcontext *ctx ) |
{ |
if (TNL_CURRENT_IM(ctx)) { |
TNL_CURRENT_IM(ctx)->ref_count--; |
if (TNL_CURRENT_IM(ctx)->ref_count == 0) |
_tnl_free_immediate( ctx, TNL_CURRENT_IM(ctx) ); |
/* |
* Don't use SET_IMMEDIATE here, or else we'll whack the |
* _tnl_CurrentInput pointer - not good when another |
* context has already been made current. |
* So we just set the context's own tnl immediate pointer |
* to 0. |
*/ |
ctx->swtnl_im = NULL; |
} |
} |
/shark/trunk/ports/mesa/src/tnl/t_imm_debug.c |
---|
0,0 → 1,183 |
/* $Id: t_imm_debug.c,v 1.1 2003-02-28 11:48:06 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included |
* in all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
*/ |
#include "mtypes.h" |
#include "context.h" |
#include "imports.h" |
#include "t_context.h" |
#include "t_imm_debug.h" |
void _tnl_print_vert_flags( const char *name, GLuint flags ) |
{ |
_mesa_debug(NULL, |
"%s: (0x%x) %s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s\n", |
name, |
flags, |
(flags & VERT_BIT_CLIP) ? "clip/proj-clip/glend, " : "", |
(flags & VERT_BIT_EDGEFLAG) ? "edgeflag, " : "", |
(flags & VERT_BIT_ELT) ? "array-elt, " : "", |
(flags & VERT_BIT_END_VB) ? "end-vb, " : "", |
(flags & VERT_BITS_EVAL_ANY) ? "eval-coord, " : "", |
(flags & VERT_BIT_EYE) ? "eye/glbegin, " : "", |
(flags & VERT_BIT_FOG) ? "fog-coord, " : "", |
(flags & VERT_BIT_INDEX) ? "index, " : "", |
(flags & VERT_BIT_MATERIAL) ? "material, " : "", |
(flags & VERT_BIT_NORMAL) ? "normals, " : "", |
(flags & VERT_BIT_POS) ? "obj, " : "", |
(flags & VERT_BIT_OBJ_3) ? "obj-3, " : "", |
(flags & VERT_BIT_OBJ_4) ? "obj-4, " : "", |
(flags & VERT_BIT_POINT_SIZE) ? "point-size, " : "", |
(flags & VERT_BIT_COLOR0) ? "colors, " : "", |
(flags & VERT_BIT_COLOR1) ? "specular, " : "", |
(flags & VERT_BIT_TEX0) ? "texcoord0, " : "", |
(flags & VERT_BIT_TEX1) ? "texcoord1, " : "", |
(flags & VERT_BIT_TEX2) ? "texcoord2, " : "", |
(flags & VERT_BIT_TEX3) ? "texcoord3, " : "", |
(flags & VERT_BIT_TEX4) ? "texcoord4, " : "", |
(flags & VERT_BIT_TEX5) ? "texcoord5, " : "", |
(flags & VERT_BIT_TEX6) ? "texcoord6, " : "", |
(flags & VERT_BIT_TEX7) ? "texcoord7, " : "" |
); |
} |
void _tnl_print_cassette( struct immediate *IM ) |
{ |
GLuint i; |
GLuint *flags = IM->Flag; |
GLuint andflag = IM->CopyAndFlag; |
GLuint orflag = (IM->CopyOrFlag|IM->Evaluated); |
GLuint state = IM->BeginState; |
GLuint req = ~0; |
_mesa_debug(NULL, "Cassette id %d, %u rows.\n", IM->id, |
IM->Count - IM->CopyStart); |
_tnl_print_vert_flags("Contains at least one", orflag); |
if (IM->Count != IM->CopyStart) |
{ |
_tnl_print_vert_flags("Contains a full complement of", andflag); |
_mesa_debug(NULL, "Final begin/end state %s/%s, errors %s/%s\n", |
(state & VERT_BEGIN_0) ? "in" : "out", |
(state & VERT_BEGIN_1) ? "in" : "out", |
(state & VERT_ERROR_0) ? "y" : "n", |
(state & VERT_ERROR_1) ? "y" : "n"); |
} |
for (i = IM->CopyStart ; i <= IM->Count ; i++) { |
_mesa_debug(NULL, "%u: ", i); |
if (req & VERT_BITS_OBJ_234) { |
if (flags[i] & VERT_BIT_EVAL_C1) |
_mesa_debug(NULL, "EvalCoord %f ", |
IM->Attrib[VERT_ATTRIB_POS][i][0]); |
else if (flags[i] & VERT_BIT_EVAL_P1) |
_mesa_debug(NULL, "EvalPoint %.0f ", |
IM->Attrib[VERT_ATTRIB_POS][i][0]); |
else if (flags[i] & VERT_BIT_EVAL_C2) |
_mesa_debug(NULL, "EvalCoord %f %f ", |
IM->Attrib[VERT_ATTRIB_POS][i][0], |
IM->Attrib[VERT_ATTRIB_POS][i][1]); |
else if (flags[i] & VERT_BIT_EVAL_P2) |
_mesa_debug(NULL, "EvalPoint %.0f %.0f ", |
IM->Attrib[VERT_ATTRIB_POS][i][0], |
IM->Attrib[VERT_ATTRIB_POS][i][1]); |
else if (i < IM->Count && (flags[i] & VERT_BITS_OBJ_234)) { |
_mesa_debug(NULL, "Obj %f %f %f %f", |
IM->Attrib[VERT_ATTRIB_POS][i][0], |
IM->Attrib[VERT_ATTRIB_POS][i][1], |
IM->Attrib[VERT_ATTRIB_POS][i][2], |
IM->Attrib[VERT_ATTRIB_POS][i][3]); |
} |
} |
if (req & flags[i] & VERT_BIT_ELT) |
_mesa_debug(NULL, " Elt %u\t", IM->Elt[i]); |
if (req & flags[i] & VERT_BIT_NORMAL) |
_mesa_debug(NULL, " Norm %f %f %f ", |
IM->Attrib[VERT_ATTRIB_NORMAL][i][0], |
IM->Attrib[VERT_ATTRIB_NORMAL][i][1], |
IM->Attrib[VERT_ATTRIB_NORMAL][i][2]); |
if (req & flags[i] & VERT_BITS_TEX_ANY) { |
GLuint j; |
for (j = 0 ; j < MAX_TEXTURE_UNITS ; j++) { |
if (req & flags[i] & VERT_BIT_TEX(j)) { |
_mesa_debug(NULL, "TC%d %f %f %f %f", j, |
IM->Attrib[VERT_ATTRIB_TEX0 + j][i][0], |
IM->Attrib[VERT_ATTRIB_TEX0 + j][i][1], |
IM->Attrib[VERT_ATTRIB_TEX0 + j][i][2], |
IM->Attrib[VERT_ATTRIB_TEX0 + j][i][3]); |
} |
} |
} |
if (req & flags[i] & VERT_BIT_COLOR0) |
_mesa_debug(NULL, " Rgba %f %f %f %f ", |
IM->Attrib[VERT_ATTRIB_COLOR0][i][0], |
IM->Attrib[VERT_ATTRIB_COLOR0][i][1], |
IM->Attrib[VERT_ATTRIB_COLOR0][i][2], |
IM->Attrib[VERT_ATTRIB_COLOR0][i][3]); |
if (req & flags[i] & VERT_BIT_COLOR1) |
_mesa_debug(NULL, " Spec %f %f %f ", |
IM->Attrib[VERT_ATTRIB_COLOR1][i][0], |
IM->Attrib[VERT_ATTRIB_COLOR1][i][1], |
IM->Attrib[VERT_ATTRIB_COLOR1][i][2]); |
if (req & flags[i] & VERT_BIT_FOG) |
_mesa_debug(NULL, " Fog %f ", IM->Attrib[VERT_ATTRIB_FOG][i][0]); |
if (req & flags[i] & VERT_BIT_INDEX) |
_mesa_debug(NULL, " Index %u ", IM->Index[i]); |
if (req & flags[i] & VERT_BIT_EDGEFLAG) |
_mesa_debug(NULL, " Edgeflag %d ", IM->EdgeFlag[i]); |
if (req & flags[i] & VERT_BIT_MATERIAL) |
_mesa_debug(NULL, " Material "); |
/* The order of these two is not easily knowable, but this is |
* the usually correct way to look at them. |
*/ |
if (req & flags[i] & VERT_BIT_END) |
_mesa_debug(NULL, " END "); |
if (req & flags[i] & VERT_BIT_BEGIN) |
_mesa_debug(NULL, " BEGIN(%s) (%s%s%s%s)", |
_mesa_prim_name[IM->Primitive[i] & PRIM_MODE_MASK], |
(IM->Primitive[i] & PRIM_LAST) ? "LAST," : "", |
(IM->Primitive[i] & PRIM_BEGIN) ? "BEGIN," : "", |
(IM->Primitive[i] & PRIM_END) ? "END," : "", |
(IM->Primitive[i] & PRIM_PARITY) ? "PARITY," : ""); |
_mesa_debug(NULL, "\n"); |
} |
} |
/shark/trunk/ports/mesa/src/tnl/t_context.h |
---|
0,0 → 1,582 |
/* $Id: t_context.h,v 1.1 2003-02-28 11:48:06 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. |
*/ |
/** |
* \file t_context.h |
* \brief TnL module datatypes and definitions. |
* \author Keith Whitwell |
*/ |
#ifndef _T_CONTEXT_H |
#define _T_CONTEXT_H |
#include "glheader.h" |
#include "mtypes.h" |
#include "math/m_matrix.h" |
#include "math/m_vector.h" |
#include "math/m_xform.h" |
#define MAX_PIPELINE_STAGES 30 |
/* Numbers for sizing immediate structs. |
*/ |
#define IMM_MAX_COPIED_VERTS 3 |
#define IMM_MAXDATA (216 + IMM_MAX_COPIED_VERTS) |
#define IMM_SIZE (IMM_MAXDATA + MAX_CLIPPED_VERTICES) |
/* Values for IM->BeginState |
*/ |
#define VERT_BEGIN_0 0x1 /* glBegin (if initially inside beg/end) */ |
#define VERT_BEGIN_1 0x2 /* glBegin (if initially outside beg/end) */ |
#define VERT_ERROR_0 0x4 /* invalid_operation in initial state 0 */ |
#define VERT_ERROR_1 0x8 /* invalid_operation in initial state 1 */ |
/* Flags to be added to the primitive enum in VB->Primitive. |
*/ |
#define PRIM_MODE_MASK 0xff /* Extract the actual primitive */ |
#define PRIM_BEGIN 0x100 /* The prim starts here (not wrapped) */ |
#define PRIM_END 0x200 /* The prim ends in this VB (does not wrap) */ |
#define PRIM_PARITY 0x400 /* The prim wrapped on an odd number of verts */ |
#define PRIM_LAST 0x800 /* No more prims in the VB */ |
/** |
* Flags that describe the inputs and outputs of pipeline stages, and |
* the contents of a vertex-cassette. We reuse the VERT_BIT_* flags |
* defined in mtypes.h and add a bunch of new ones. |
*/ |
/* bits 0..5 defined in mtypes.h */ |
#define VERT_BIT_INDEX VERT_BIT_SIX /* a free vertex attrib bit */ |
#define VERT_BIT_EDGEFLAG VERT_BIT_SEVEN /* a free vertex attrib bit */ |
/* bits 8..15 defined in mtypes.h */ |
#define VERT_BIT_EVAL_C1 (1 << 16) /* imm only */ |
#define VERT_BIT_EVAL_C2 (1 << 17) /* imm only */ |
#define VERT_BIT_EVAL_P1 (1 << 18) /* imm only */ |
#define VERT_BIT_EVAL_P2 (1 << 19) /* imm only */ |
#define VERT_BIT_OBJ_3 (1 << 20) /* imm only */ |
#define VERT_BIT_OBJ_4 (1 << 21) /* imm only */ |
#define VERT_BIT_MATERIAL (1 << 22) /* imm only, but tested in vb code */ |
#define VERT_BIT_ELT (1 << 23) /* imm only */ |
#define VERT_BIT_BEGIN (1 << 24) /* imm only, but tested in vb code */ |
#define VERT_BIT_END (1 << 25) /* imm only, but tested in vb code */ |
#define VERT_BIT_END_VB (1 << 26) /* imm only, but tested in vb code */ |
#define VERT_BIT_POINT_SIZE (1 << 27) /* vb only, could reuse a bit */ |
#define VERT_BIT_EYE VERT_BIT_BEGIN /* vb only, reuse imm bit */ |
#define VERT_BIT_CLIP VERT_BIT_END /* vb only, reuse imm bit*/ |
/* Flags for IM->TexCoordSize. Enough flags for 16 units. |
*/ |
#define TEX_0_SIZE_3 (unsigned)0x1 |
#define TEX_0_SIZE_4 (unsigned)0x10001 |
#define TEX_SIZE_3(unit) (TEX_0_SIZE_3 << (unit)) |
#define TEX_SIZE_4(unit) (TEX_0_SIZE_4 << (unit)) |
/* Shorthands. |
*/ |
#define VERT_BITS_OBJ_23 (VERT_BIT_POS | VERT_BIT_OBJ_3) |
#define VERT_BITS_OBJ_234 (VERT_BIT_POS | VERT_BIT_OBJ_3 | VERT_BIT_OBJ_4) |
#define VERT_BITS_TEX_ANY (VERT_BIT_TEX0 | \ |
VERT_BIT_TEX1 | \ |
VERT_BIT_TEX2 | \ |
VERT_BIT_TEX3 | \ |
VERT_BIT_TEX4 | \ |
VERT_BIT_TEX5 | \ |
VERT_BIT_TEX6 | \ |
VERT_BIT_TEX7) |
#define VERT_BITS_EVAL_ANY (VERT_BIT_EVAL_C1 | VERT_BIT_EVAL_P1 | \ |
VERT_BIT_EVAL_C2 | VERT_BIT_EVAL_P2) |
#define VERT_BITS_FIXUP (VERT_BITS_TEX_ANY | \ |
VERT_BIT_COLOR0 | \ |
VERT_BIT_COLOR1 | \ |
VERT_BIT_FOG | \ |
VERT_BIT_INDEX | \ |
VERT_BIT_EDGEFLAG | \ |
VERT_BIT_NORMAL) |
#define VERT_BITS_CURRENT_DATA (VERT_BITS_FIXUP | \ |
VERT_BIT_MATERIAL) |
#define VERT_BITS_DATA (VERT_BITS_TEX_ANY | \ |
VERT_BIT_COLOR0 | \ |
VERT_BIT_COLOR1 | \ |
VERT_BIT_FOG | \ |
VERT_BIT_INDEX | \ |
VERT_BIT_EDGEFLAG | \ |
VERT_BIT_NORMAL | \ |
VERT_BIT_POS | \ |
VERT_BIT_MATERIAL | \ |
VERT_BIT_ELT | \ |
VERT_BITS_EVAL_ANY) |
/** |
* KW: Represents everything that can take place between a begin and |
* end, and can represent multiple begin/end pairs. Can be used to |
* losslessly encode this information in display lists. |
*/ |
struct immediate |
{ |
GLuint id, ref_count; |
/* This must be saved when immediates are shared in display lists. |
*/ |
GLuint CopyStart, Start, Count; |
GLuint LastData; /* count or count+1 */ |
GLuint AndFlag, OrFlag; |
GLuint TexSize; /* keep track of texcoord sizes */ |
GLuint BeginState, SavedBeginState; |
GLuint LastPrimitive; |
GLuint ArrayEltFlags; /* precalc'ed for glArrayElt */ |
GLuint ArrayEltIncr; |
GLuint ArrayEltFlush; |
#define FLUSH_ELT_EAGER 0x1 |
#define FLUSH_ELT_LAZY 0x2 |
GLuint FlushElt; |
GLuint MaxTextureUnits; /* precalc'ed for glMultiTexCoordARB */ |
/* Temporary values created when vertices are copied into the |
* first 3 slots of the struct: |
*/ |
GLuint CopyOrFlag; |
GLuint CopyAndFlag; |
GLuint CopyTexSize; |
GLuint Evaluated; |
/* allocate storage for these on demand: |
*/ |
struct gl_material (*Material)[2]; |
GLuint *MaterialMask; |
GLuint LastMaterial; |
GLuint MaterialOrMask; |
GLuint MaterialAndMask; |
GLuint Primitive[IMM_SIZE]; /* BEGIN/END */ |
GLuint PrimitiveLength[IMM_SIZE]; /* BEGIN/END */ |
GLuint Flag[IMM_SIZE]; /* VERT_BIT_* flags */ |
/* All vertex attributes (position, normal, color, secondary color, |
* texcoords, fog coord) are stored in the Attrib[] arrays instead |
* of individual arrays as we did prior to Mesa 4.1. |
* |
* XXX may need to use 32-byte aligned allocation for this!!! |
*/ |
GLfloat Attrib[VERT_ATTRIB_MAX][IMM_SIZE][4]; /* GL_NV_vertex_program */ |
GLfloat *NormalLengthPtr; /* length of normal vectors (display list only) */ |
GLuint Elt[IMM_SIZE]; |
GLubyte EdgeFlag[IMM_SIZE]; |
GLuint Index[IMM_SIZE]; |
}; |
struct vertex_arrays |
{ |
/* XXX move a bunch of these fields into the Attribs[] array??? */ |
GLvector4f Obj; |
GLvector4f Normal; |
struct gl_client_array Color; |
struct gl_client_array SecondaryColor; |
GLvector1ui Index; |
GLvector1ub EdgeFlag; |
GLvector4f TexCoord[MAX_TEXTURE_UNITS]; |
GLvector1ui Elt; |
GLvector4f FogCoord; |
GLvector4f Attribs[VERT_ATTRIB_MAX]; |
}; |
/** |
* Contains the current state of a running pipeline. |
*/ |
typedef struct vertex_buffer |
{ |
/* Constant over life of the vertex_buffer. |
*/ |
GLuint Size; |
/* Constant over the pipeline. |
*/ |
GLuint Count; /* for everything except Elts */ |
GLuint FirstClipped; /* temp verts for clipping */ |
GLuint FirstPrimitive; /* usually zero */ |
/* Pointers to current data. |
*/ |
GLuint *Elts; /* VERT_BIT_ELT */ |
GLvector4f *ObjPtr; /* VERT_BIT_POS */ |
GLvector4f *EyePtr; /* VERT_BIT_EYE */ |
GLvector4f *ClipPtr; /* VERT_BIT_CLIP */ |
GLvector4f *NdcPtr; /* VERT_BIT_CLIP (2) */ |
GLubyte ClipOrMask; /* VERT_BIT_CLIP (3) */ |
GLubyte *ClipMask; /* VERT_BIT_CLIP (4) */ |
GLvector4f *NormalPtr; /* VERT_BIT_NORMAL */ |
GLfloat *NormalLengthPtr; /* VERT_BIT_NORMAL */ |
GLboolean *EdgeFlag; /* VERT_BIT_EDGEFLAG */ |
GLvector4f *TexCoordPtr[MAX_TEXTURE_UNITS]; /* VERT_TEX_0..n */ |
GLvector1ui *IndexPtr[2]; /* VERT_BIT_INDEX */ |
struct gl_client_array *ColorPtr[2]; /* VERT_BIT_COLOR0 */ |
struct gl_client_array *SecondaryColorPtr[2];/* VERT_BIT_COLOR1 */ |
GLvector4f *PointSizePtr; /* VERT_BIT_POINT_SIZE */ |
GLvector4f *FogCoordPtr; /* VERT_BIT_FOG */ |
struct gl_material (*Material)[2]; /* VERT_BIT_MATERIAL, optional */ |
GLuint *MaterialMask; /* VERT_BIT_MATERIAL, optional */ |
GLuint *Flag; /* VERT_BIT_* flags, optional */ |
GLuint *Primitive; /* GL_(mode)|PRIM_* flags */ |
GLuint *PrimitiveLength; /* integers */ |
/* Inputs to the vertex program stage */ |
GLvector4f *AttribPtr[VERT_ATTRIB_MAX]; /* GL_NV_vertex_program */ |
GLuint importable_data; |
void *import_source; |
void (*import_data)( GLcontext *ctx, GLuint flags, GLuint vecflags ); |
/* Callback to the provider of the untransformed input for the |
* render stage (or other stages) to call if they need to write into |
* write-protected arrays, or fixup the stride on input arrays. |
* |
* This is currently only necessary for client arrays that make it |
* as far down the pipeline as the render stage. |
*/ |
GLuint LastClipped; |
/* Private data from _tnl_render_stage that has no business being |
* in this struct. |
*/ |
} TNLvertexbuffer; |
/* Describes an individual operation on the pipeline. |
*/ |
struct gl_pipeline_stage { |
const char *name; |
GLuint check_state; /* All state referenced in check() -- |
* When is the pipeline_stage struct |
* itself invalidated? Must be |
* constant. |
*/ |
/* Usually constant or set by the 'check' callback: |
*/ |
GLuint run_state; /* All state referenced in run() -- |
* When is the cached output of the |
* stage invalidated? |
*/ |
GLboolean active; /* True if runnable in current state */ |
GLuint inputs; /* VERT_* inputs to the stage */ |
GLuint outputs; /* VERT_* outputs of the stage */ |
/* Set in _tnl_run_pipeline(): |
*/ |
GLuint changed_inputs; /* Generated value -- inputs to the |
* stage that have changed since last |
* call to 'run'. |
*/ |
/* Private data for the pipeline stage: |
*/ |
void *privatePtr; |
/* Free private data. May not be null. |
*/ |
void (*destroy)( struct gl_pipeline_stage * ); |
/* Called from _tnl_validate_pipeline(). Must update all fields in |
* the pipeline_stage struct for the current state. |
*/ |
void (*check)( GLcontext *ctx, struct gl_pipeline_stage * ); |
/* Called from _tnl_run_pipeline(). The stage.changed_inputs value |
* encodes all inputs to thee struct which have changed. If |
* non-zero, recompute all affected outputs of the stage, otherwise |
* execute any 'sideeffects' of the stage. |
* |
* Return value: GL_TRUE - keep going |
* GL_FALSE - finished pipeline |
*/ |
GLboolean (*run)( GLcontext *ctx, struct gl_pipeline_stage * ); |
}; |
struct gl_pipeline { |
GLuint build_state_trigger; /* state changes which require build */ |
GLuint build_state_changes; /* state changes since last build */ |
GLuint run_state_changes; /* state changes since last run */ |
GLuint run_input_changes; /* VERT_* changes since last run */ |
GLuint inputs; /* VERT_* inputs to pipeline */ |
struct gl_pipeline_stage stages[MAX_PIPELINE_STAGES+1]; |
GLuint nr_stages; |
}; |
struct tnl_eval_store { |
GLuint EvalMap1Flags; |
GLuint EvalMap2Flags; |
GLuint EvalMap1AttribFlags; /* GL_NV_vertex_program */ |
GLuint EvalMap2AttribFlags; /* GL_NV_vertex_program */ |
GLuint EvalNewState; |
struct immediate *im; /* used for temporary data */ |
}; |
typedef void (*points_func)( GLcontext *ctx, GLuint first, GLuint last ); |
typedef void (*line_func)( GLcontext *ctx, GLuint v1, GLuint v2 ); |
typedef void (*triangle_func)( GLcontext *ctx, |
GLuint v1, GLuint v2, GLuint v3 ); |
typedef void (*quad_func)( GLcontext *ctx, GLuint v1, GLuint v2, |
GLuint v3, GLuint v4 ); |
typedef void (*render_func)( GLcontext *ctx, GLuint start, GLuint count, |
GLuint flags ); |
typedef void (*interp_func)( GLcontext *ctx, |
GLfloat t, GLuint dst, GLuint out, GLuint in, |
GLboolean force_boundary ); |
typedef void (*copy_pv_func)( GLcontext *ctx, GLuint dst, GLuint src ); |
typedef void (*setup_func)( GLcontext *ctx, |
GLuint start, GLuint end, |
GLuint new_inputs); |
struct tnl_device_driver { |
/*** |
*** TNL Pipeline |
***/ |
void (*RunPipeline)(GLcontext *ctx); |
/* Replaces PipelineStart/PipelineFinish -- intended to allow |
* drivers to wrap _tnl_run_pipeline() with code to validate state |
* and grab/release hardware locks. |
*/ |
void (*NotifyMaterialChange)(GLcontext *ctx); |
/* Alert tnl-aware drivers of changes to material. |
*/ |
GLboolean (*NotifyBegin)(GLcontext *ctx, GLenum p); |
/* Allow drivers to hook in optimized begin/end engines. |
* Return value: GL_TRUE - driver handled the begin |
* GL_FALSE - driver didn't handle the begin |
*/ |
/*** |
*** Rendering -- These functions called only from t_vb_render.c |
***/ |
struct { |
void (*Start)(GLcontext *ctx); |
void (*Finish)(GLcontext *ctx); |
/* Called before and after all rendering operations, including DrawPixels, |
* ReadPixels, Bitmap, span functions, and CopyTexImage, etc commands. |
* These are a suitable place for grabbing/releasing hardware locks. |
*/ |
void (*PrimitiveNotify)(GLcontext *ctx, GLenum mode); |
/* Called between RenderStart() and RenderFinish() to indicate the |
* type of primitive we're about to draw. Mode will be one of the |
* modes accepted by glBegin(). |
*/ |
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. |
*/ |
copy_pv_func CopyPV; |
/* The copy function is used to make a copy of a vertex. All pertinant |
* vertex attributes should be copied. |
*/ |
void (*ClippedPolygon)( GLcontext *ctx, const GLuint *elts, GLuint n ); |
/* Render a polygon with <n> vertices whose indexes are in the <elts> |
* array. |
*/ |
void (*ClippedLine)( GLcontext *ctx, GLuint v0, GLuint v1 ); |
/* Render a line between the two vertices given by indexes v0 and v1. */ |
points_func Points; /* must now respect vb->elts */ |
line_func Line; |
triangle_func Triangle; |
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. |
*/ |
render_func *PrimTabVerts; |
render_func *PrimTabElts; |
/* Render whole unclipped primitives (points, lines, linestrips, |
* lineloops, etc). The tables are indexed by the GL enum of the |
* primitive to be rendered. RenderTabVerts is used for non-indexed |
* arrays of vertices. RenderTabElts is used for indexed arrays of |
* vertices. |
*/ |
void (*ResetLineStipple)( GLcontext *ctx ); |
/* Reset the hardware's line stipple counter. |
*/ |
setup_func BuildVertices; |
/* This function is called whenever new vertices are required for |
* rendering. The vertices in question are those n such that start |
* <= n < end. The new_inputs parameter indicates those fields of |
* the vertex which need to be updated, if only a partial repair of |
* the vertex is required. |
* |
* This function is called only from _tnl_render_stage in tnl/t_render.c. |
*/ |
GLboolean (*Multipass)( GLcontext *ctx, GLuint passno ); |
/* Driver may request additional render passes by returning GL_TRUE |
* when this function is called. This function will be called |
* after the first pass, and passes will be made until the function |
* returns GL_FALSE. If no function is registered, only one pass |
* is made. |
* |
* This function will be first invoked with passno == 1. |
*/ |
} Render; |
}; |
typedef struct { |
/* Driver interface. |
*/ |
struct tnl_device_driver Driver; |
/* Track whether the module is active. |
*/ |
GLboolean bound_exec; |
/* Display list extensions |
*/ |
GLuint opcode_vertex_cassette; |
/* Pipeline |
*/ |
struct gl_pipeline pipeline; |
struct vertex_buffer vb; |
/* GLvectors for binding to vb: |
*/ |
struct vertex_arrays imm_inputs; |
struct vertex_arrays array_inputs; |
GLuint *tmp_primitive; |
GLuint *tmp_primitive_length; |
/* Set when executing an internally generated begin/end object. If |
* such an object is encountered in a display list, it will be |
* replayed only if the list is outside any existing begin/end |
* objects. |
*/ |
GLboolean ReplayHardBeginEnd; |
/* Note which vertices need copying over succesive immediates. |
* Will add save versions to precompute vertex copying where |
* possible. |
*/ |
struct immediate *ExecCopySource; |
GLuint ExecCopyCount; |
GLuint ExecCopyElts[IMM_MAX_COPIED_VERTS]; |
GLuint ExecCopyTexSize; |
GLuint ExecParity; |
GLuint DlistPrimitive; |
GLuint DlistPrimitiveLength; |
GLuint DlistLastPrimitive; |
/* Cache a single free immediate (refcount == 0) |
*/ |
struct immediate *freed_immediate; |
/* Probably need a better configuration mechanism: |
*/ |
GLboolean NeedNdcCoords; |
GLboolean LoopbackDListCassettes; |
GLboolean CalcDListNormalLengths; |
GLboolean IsolateMaterials; |
/* Derived state and storage for _tnl_eval_vb: |
*/ |
struct tnl_eval_store eval; |
/* Functions to be plugged into dispatch when tnl is active. |
*/ |
GLvertexformat vtxfmt; |
GLvertexformat save_vtxfmt; |
} TNLcontext; |
#define TNL_CONTEXT(ctx) ((TNLcontext *)(ctx->swtnl_context)) |
#define TNL_CURRENT_IM(ctx) ((struct immediate *)(ctx->swtnl_im)) |
#define TYPE_IDX(t) ((t) & 0xf) |
#define MAX_TYPES TYPE_IDX(GL_DOUBLE)+1 /* 0xa + 1 */ |
extern void _tnl_MakeCurrent( GLcontext *ctx, |
GLframebuffer *drawBuffer, |
GLframebuffer *readBuffer ); |
/* |
* Macros for fetching current input buffer. |
*/ |
#ifdef THREADS |
#define GET_IMMEDIATE struct immediate *IM = TNL_CURRENT_IM(((GLcontext *) (_glapi_Context ? _glapi_Context : _glapi_get_context()))) |
#define SET_IMMEDIATE(ctx, im) ctx->swtnl_im = (void *)im |
#else |
extern struct immediate *_tnl_CurrentInput; |
#define GET_IMMEDIATE struct immediate *IM = _tnl_CurrentInput |
#define SET_IMMEDIATE(ctx, im) \ |
do { \ |
ctx->swtnl_im = (void *)im; \ |
_tnl_CurrentInput = im; \ |
} while (0) |
#endif |
#endif |
/shark/trunk/ports/mesa/src/tnl/t_vb_texmat.c |
---|
0,0 → 1,152 |
/* $Id: t_vb_texmat.c,v 1.1 2003-02-28 11:48:08 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 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 "mmath.h" |
#include "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_UNITS]; |
}; |
#define TEXMAT_STAGE_DATA(stage) ((struct texmat_stage_data *)stage->privatePtr) |
static void check_texmat( GLcontext *ctx, struct gl_pipeline_stage *stage ) |
{ |
GLuint i; |
stage->active = 0; |
if (ctx->Texture._TexMatEnabled && !ctx->VertexProgram.Enabled) { |
GLuint flags = 0; |
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) |
if (ctx->Texture._TexMatEnabled & ENABLE_TEXMAT(i)) |
flags |= VERT_BIT_TEX(i); |
stage->active = 1; |
stage->inputs = flags; |
stage->outputs = flags; |
} |
} |
static GLboolean run_texmat_stage( GLcontext *ctx, |
struct gl_pipeline_stage *stage ) |
{ |
struct texmat_stage_data *store = TEXMAT_STAGE_DATA(stage); |
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; |
GLuint i; |
/* 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.MaxTextureUnits ; i++) |
if (ctx->Texture._TexMatEnabled & ENABLE_TEXMAT(i)) { |
if (stage->changed_inputs & VERT_BIT_TEX(i)) |
(void) TransformRaw( &store->texcoord[i], |
ctx->TextureMatrixStack[i].Top, |
VB->TexCoordPtr[i]); |
VB->TexCoordPtr[i] = &store->texcoord[i]; |
} |
return GL_TRUE; |
} |
/* Called the first time stage->run() is invoked. |
*/ |
static GLboolean alloc_texmat_data( GLcontext *ctx, |
struct gl_pipeline_stage *stage ) |
{ |
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; |
struct texmat_stage_data *store; |
GLuint i; |
stage->privatePtr = CALLOC(sizeof(*store)); |
store = TEXMAT_STAGE_DATA(stage); |
if (!store) |
return GL_FALSE; |
for (i = 0 ; i < ctx->Const.MaxTextureUnits ; i++) |
_mesa_vector4f_alloc( &store->texcoord[i], 0, VB->Size, 32 ); |
/* Now run the stage. |
*/ |
stage->run = run_texmat_stage; |
return stage->run( ctx, stage ); |
} |
static void free_texmat_data( struct gl_pipeline_stage *stage ) |
{ |
struct texmat_stage_data *store = TEXMAT_STAGE_DATA(stage); |
GLuint i; |
if (store) { |
for (i = 0 ; i < MAX_TEXTURE_UNITS ; i++) |
if (store->texcoord[i].data) |
_mesa_vector4f_free( &store->texcoord[i] ); |
FREE( store ); |
stage->privatePtr = 0; |
} |
} |
const struct gl_pipeline_stage _tnl_texture_transform_stage = |
{ |
"texture transform", /* name */ |
_NEW_TEXTURE|_NEW_TEXTURE_MATRIX, /* check_state */ |
_NEW_TEXTURE|_NEW_TEXTURE_MATRIX, /* run_state */ |
GL_FALSE, /* active? */ |
0, /* inputs */ |
0, /* outputs */ |
0, /* changed_inputs */ |
NULL, /* private data */ |
free_texmat_data, /* destructor */ |
check_texmat, /* check */ |
alloc_texmat_data, /* run -- initially set to init */ |
}; |
/shark/trunk/ports/mesa/src/tnl/t_imm_eval.c |
---|
0,0 → 1,854 |
/* $Id: t_imm_eval.c,v 1.1 2003-02-28 11:48:07 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> |
* Brian Paul - vertex program updates |
*/ |
#include "glheader.h" |
#include "colormac.h" |
#include "context.h" |
#include "macros.h" |
#include "imports.h" |
#include "mmath.h" |
#include "mtypes.h" |
#include "math/m_eval.h" |
#include "t_context.h" |
#include "t_imm_debug.h" |
#include "t_imm_eval.h" |
#include "t_imm_exec.h" |
#include "t_imm_fixup.h" |
#include "t_imm_alloc.h" |
static void eval_points1( GLfloat outcoord[][4], |
GLfloat coord[][4], |
const GLuint *flags, |
GLfloat du, GLfloat u1 ) |
{ |
GLuint i; |
for (i = 0 ; !(flags[i] & VERT_BIT_END_VB) ; i++) |
if (flags[i] & VERT_BITS_EVAL_ANY) { |
outcoord[i][0] = coord[i][0]; |
outcoord[i][1] = coord[i][1]; |
if (flags[i] & VERT_BIT_EVAL_P1) |
outcoord[i][0] = coord[i][0] * du + u1; |
} |
} |
static void eval_points2( GLfloat outcoord[][4], |
GLfloat coord[][4], |
const GLuint *flags, |
GLfloat du, GLfloat u1, |
GLfloat dv, GLfloat v1 ) |
{ |
GLuint i; |
for (i = 0 ; !(flags[i] & VERT_BIT_END_VB) ; i++) { |
if (flags[i] & VERT_BITS_EVAL_ANY) { |
outcoord[i][0] = coord[i][0]; |
outcoord[i][1] = coord[i][1]; |
if (flags[i] & VERT_BIT_EVAL_P2) { |
outcoord[i][0] = coord[i][0] * du + u1; |
outcoord[i][1] = coord[i][1] * dv + v1; |
} |
} |
} |
} |
static const GLubyte dirty_flags[5] = { |
0, /* not possible */ |
VEC_DIRTY_0, |
VEC_DIRTY_1, |
VEC_DIRTY_2, |
VEC_DIRTY_3 |
}; |
static void eval1_4f( GLvector4f *dest, |
GLfloat coord[][4], |
const GLuint *flags, |
GLuint dimension, |
const struct gl_1d_map *map ) |
{ |
const GLfloat u1 = map->u1; |
const GLfloat du = map->du; |
GLfloat (*to)[4] = dest->data; |
GLuint i; |
for (i = 0 ; !(flags[i] & VERT_BIT_END_VB) ; i++) |
if (flags[i] & (VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1)) { |
GLfloat u = (coord[i][0] - u1) * du; |
ASSIGN_4V(to[i], 0,0,0,1); |
_math_horner_bezier_curve(map->Points, to[i], u, |
dimension, map->Order); |
} |
dest->size = MAX2(dest->size, dimension); |
dest->flags |= dirty_flags[dimension]; |
} |
/* as above, but dest is a gl_client_array */ |
static void eval1_4f_ca( struct gl_client_array *dest, |
GLfloat coord[][4], |
const GLuint *flags, |
GLuint dimension, |
const struct gl_1d_map *map ) |
{ |
const GLfloat u1 = map->u1; |
const GLfloat du = map->du; |
GLfloat (*to)[4] = (GLfloat (*)[4])dest->Ptr; |
GLuint i; |
ASSERT(dest->Type == GL_FLOAT); |
ASSERT(dest->StrideB == 4 * sizeof(GLfloat)); |
for (i = 0 ; !(flags[i] & VERT_BIT_END_VB) ; i++) |
if (flags[i] & (VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1)) { |
GLfloat u = (coord[i][0] - u1) * du; |
ASSIGN_4V(to[i], 0,0,0,1); |
_math_horner_bezier_curve(map->Points, to[i], u, |
dimension, map->Order); |
} |
dest->Size = MAX2(dest->Size, (GLint) dimension); |
} |
static void eval1_1ui( GLvector1ui *dest, |
GLfloat coord[][4], |
const GLuint *flags, |
const struct gl_1d_map *map ) |
{ |
const GLfloat u1 = map->u1; |
const GLfloat du = map->du; |
GLuint *to = dest->data; |
GLuint i; |
for (i = 0 ; !(flags[i] & VERT_BIT_END_VB) ; i++) |
if (flags[i] & (VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1)) { |
GLfloat u = (coord[i][0] - u1) * du; |
GLfloat tmp; |
_math_horner_bezier_curve(map->Points, &tmp, u, 1, map->Order); |
to[i] = (GLuint) (GLint) tmp; |
} |
} |
static void eval1_norm( GLvector4f *dest, |
GLfloat coord[][4], |
const GLuint *flags, |
const struct gl_1d_map *map ) |
{ |
const GLfloat u1 = map->u1; |
const GLfloat du = map->du; |
GLfloat (*to)[4] = dest->data; |
GLuint i; |
for (i = 0 ; !(flags[i] & VERT_BIT_END_VB) ; i++) |
if (flags[i] & (VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1)) { |
GLfloat u = (coord[i][0] - u1) * du; |
_math_horner_bezier_curve(map->Points, to[i], u, 3, map->Order); |
} |
} |
static void eval2_obj_norm( GLvector4f *obj_ptr, |
GLvector4f *norm_ptr, |
GLfloat coord[][4], |
GLuint *flags, |
GLuint dimension, |
const struct gl_2d_map *map ) |
{ |
const GLfloat u1 = map->u1; |
const GLfloat du = map->du; |
const GLfloat v1 = map->v1; |
const GLfloat dv = map->dv; |
GLfloat (*obj)[4] = obj_ptr->data; |
GLfloat (*normal)[4] = norm_ptr->data; |
GLuint i; |
for (i = 0 ; !(flags[i] & VERT_BIT_END_VB) ; i++) |
if (flags[i] & (VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2)) { |
GLfloat u = (coord[i][0] - u1) * du; |
GLfloat v = (coord[i][1] - v1) * dv; |
GLfloat du[4], dv[4]; |
ASSIGN_4V(obj[i], 0,0,0,1); |
_math_de_casteljau_surf(map->Points, obj[i], du, dv, u, v, dimension, |
map->Uorder, map->Vorder); |
if (dimension == 4) { |
du[0] = du[0]*obj[i][3] - du[3]*obj[i][0]; |
du[1] = du[1]*obj[i][3] - du[3]*obj[i][1]; |
du[2] = du[2]*obj[i][3] - du[3]*obj[i][2]; |
dv[0] = dv[0]*obj[i][3] - dv[3]*obj[i][0]; |
dv[1] = dv[1]*obj[i][3] - dv[3]*obj[i][1]; |
dv[2] = dv[2]*obj[i][3] - dv[3]*obj[i][2]; |
} |
CROSS3(normal[i], du, dv); |
NORMALIZE_3FV(normal[i]); |
} |
obj_ptr->size = MAX2(obj_ptr->size, dimension); |
obj_ptr->flags |= dirty_flags[dimension]; |
} |
static void eval2_4f( GLvector4f *dest, |
GLfloat coord[][4], |
const GLuint *flags, |
GLuint dimension, |
const struct gl_2d_map *map ) |
{ |
const GLfloat u1 = map->u1; |
const GLfloat du = map->du; |
const GLfloat v1 = map->v1; |
const GLfloat dv = map->dv; |
GLfloat (*to)[4] = dest->data; |
GLuint i; |
for (i = 0 ; !(flags[i] & VERT_BIT_END_VB) ; i++) |
if (flags[i] & (VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2)) { |
GLfloat u = (coord[i][0] - u1) * du; |
GLfloat v = (coord[i][1] - v1) * dv; |
_math_horner_bezier_surf(map->Points, to[i], u, v, dimension, |
map->Uorder, map->Vorder); |
} |
dest->size = MAX2(dest->size, dimension); |
dest->flags |= dirty_flags[dimension]; |
} |
/* as above, but dest is a gl_client_array */ |
static void eval2_4f_ca( struct gl_client_array *dest, |
GLfloat coord[][4], |
const GLuint *flags, |
GLuint dimension, |
const struct gl_2d_map *map ) |
{ |
const GLfloat u1 = map->u1; |
const GLfloat du = map->du; |
const GLfloat v1 = map->v1; |
const GLfloat dv = map->dv; |
GLfloat (*to)[4] = (GLfloat (*)[4])dest->Ptr; |
GLuint i; |
ASSERT(dest->Type == GL_FLOAT); |
ASSERT(dest->StrideB == 4 * sizeof(GLfloat)); |
for (i = 0 ; !(flags[i] & VERT_BIT_END_VB) ; i++) |
if (flags[i] & (VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2)) { |
GLfloat u = (coord[i][0] - u1) * du; |
GLfloat v = (coord[i][1] - v1) * dv; |
_math_horner_bezier_surf(map->Points, to[i], u, v, dimension, |
map->Uorder, map->Vorder); |
} |
dest->Size = MAX2(dest->Size, (GLint) dimension); |
} |
static void eval2_norm( GLvector4f *dest, |
GLfloat coord[][4], |
GLuint *flags, |
const struct gl_2d_map *map ) |
{ |
const GLfloat u1 = map->u1; |
const GLfloat du = map->du; |
const GLfloat v1 = map->v1; |
const GLfloat dv = map->dv; |
GLfloat (*to)[4] = dest->data; |
GLuint i; |
for (i = 0 ; !(flags[i] & VERT_BIT_END_VB) ; i++) { |
if (flags[i] & (VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2)) { |
GLfloat u = (coord[i][0] - u1) * du; |
GLfloat v = (coord[i][1] - v1) * dv; |
_math_horner_bezier_surf(map->Points, to[i], u, v, 3, |
map->Uorder, map->Vorder); |
} |
} |
} |
static void eval2_1ui( GLvector1ui *dest, |
GLfloat coord[][4], |
const GLuint *flags, |
const struct gl_2d_map *map ) |
{ |
const GLfloat u1 = map->u1; |
const GLfloat du = map->du; |
const GLfloat v1 = map->v1; |
const GLfloat dv = map->dv; |
GLuint *to = dest->data; |
GLuint i; |
for (i = 0 ; !(flags[i] & VERT_BIT_END_VB) ; i++) |
if (flags[i] & (VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2)) { |
GLfloat u = (coord[i][0] - u1) * du; |
GLfloat v = (coord[i][1] - v1) * dv; |
GLfloat tmp; |
_math_horner_bezier_surf(map->Points, &tmp, u, v, 1, |
map->Uorder, map->Vorder); |
to[i] = (GLuint) (GLint) tmp; |
} |
} |
static void copy_4f( GLfloat to[][4], GLfloat from[][4], GLuint count ) |
{ |
MEMCPY( to, from, count * sizeof(to[0])); |
} |
static void copy_4f_stride( GLfloat to[][4], const GLfloat *from, |
GLuint stride, GLuint count ) |
{ |
if (stride == 4 * sizeof(GLfloat)) |
MEMCPY( to, from, count * sizeof(to[0])); |
else { |
GLuint i; |
for (i = 0 ; i < count ; i++, STRIDE_F(from, stride)) |
COPY_4FV( to[i], from ); |
} |
} |
static void copy_3f( GLfloat to[][4], GLfloat from[][4], GLuint count ) |
{ |
GLuint i; |
for (i = 0 ; i < count ; i++) { |
COPY_3FV(to[i], from[i]); |
} |
} |
static void copy_1ui( GLuint to[], const GLuint from[], GLuint count ) |
{ |
MEMCPY( to, from, (count) * sizeof(to[0])); |
} |
/* Translate eval enabled flags to VERT_* flags. |
*/ |
static void update_eval( GLcontext *ctx ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
GLuint eval1 = 0, eval2 = 0; |
GLuint i; |
if (ctx->Eval.Map1Index) |
eval1 |= VERT_BIT_INDEX; |
if (ctx->Eval.Map2Index) |
eval2 |= VERT_BIT_INDEX; |
if (ctx->Eval.Map1Color4) |
eval1 |= VERT_BIT_COLOR0; |
if (ctx->Eval.Map2Color4) |
eval2 |= VERT_BIT_COLOR0; |
if (ctx->Eval.Map1Normal) |
eval1 |= VERT_BIT_NORMAL; |
if (ctx->Eval.Map2Normal) |
eval2 |= VERT_BIT_NORMAL; |
if (ctx->Eval.Map1TextureCoord4 || |
ctx->Eval.Map1TextureCoord3 || |
ctx->Eval.Map1TextureCoord2 || |
ctx->Eval.Map1TextureCoord1) |
eval1 |= VERT_BIT_TEX0; |
if (ctx->Eval.Map2TextureCoord4 || |
ctx->Eval.Map2TextureCoord3 || |
ctx->Eval.Map2TextureCoord2 || |
ctx->Eval.Map2TextureCoord1) |
eval2 |= VERT_BIT_TEX0; |
if (ctx->Eval.Map1Vertex4) |
eval1 |= VERT_BITS_OBJ_234; |
if (ctx->Eval.Map1Vertex3) |
eval1 |= VERT_BITS_OBJ_23; |
if (ctx->Eval.Map2Vertex4) { |
if (ctx->Eval.AutoNormal) |
eval2 |= VERT_BITS_OBJ_234 | VERT_BIT_NORMAL; |
else |
eval2 |= VERT_BITS_OBJ_234; |
} |
else if (ctx->Eval.Map2Vertex3) { |
if (ctx->Eval.AutoNormal) |
eval2 |= VERT_BITS_OBJ_23 | VERT_BIT_NORMAL; |
else |
eval2 |= VERT_BITS_OBJ_23; |
} |
tnl->eval.EvalMap1Flags = eval1; |
tnl->eval.EvalMap2Flags = eval2; |
/* GL_NV_vertex_program evaluators */ |
eval1 = eval2 = 0; |
for (i = 0; i < VERT_ATTRIB_MAX; i++) { |
if (ctx->Eval.Map1Attrib[i]) |
eval1 |= (1 << i); |
if (ctx->Eval.Map2Attrib[i]) |
eval2 |= (1 << i); |
} |
tnl->eval.EvalMap1AttribFlags = eval1; |
tnl->eval.EvalMap2AttribFlags = eval2; |
tnl->eval.EvalNewState = 0; |
} |
/* This looks a lot like a pipeline stage, but for various reasons is |
* better handled outside the pipeline, and considered the final stage |
* of fixing up an immediate struct for execution. |
* |
* Really want to cache the results of this function in display lists, |
* at least for EvalMesh commands. |
*/ |
void _tnl_eval_immediate( GLcontext *ctx, struct immediate *IM ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_arrays *tmp = &tnl->imm_inputs; |
struct immediate *store = tnl->eval.im; |
GLuint *flags = IM->Flag + IM->CopyStart; |
GLuint copycount; |
GLuint orflag = IM->OrFlag; |
GLuint any_eval1 = orflag & (VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1); |
GLuint any_eval2 = orflag & (VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2); |
GLuint req = 0; |
GLuint purge_flags = 0; |
GLfloat (*coord)[4] = IM->Attrib[VERT_ATTRIB_POS] + IM->CopyStart; |
if (IM->AndFlag & VERT_BITS_EVAL_ANY) |
copycount = IM->Start - IM->CopyStart; /* just copy copied vertices */ |
else |
copycount = IM->Count - IM->CopyStart; /* copy all vertices */ |
if (!store) |
store = tnl->eval.im = _tnl_alloc_immediate( ctx ); |
if (tnl->eval.EvalNewState & _NEW_EVAL) |
update_eval( ctx ); |
if (any_eval1) { |
req |= tnl->pipeline.inputs |
& (tnl->eval.EvalMap1Flags | tnl->eval.EvalMap1AttribFlags); |
if (!ctx->Eval.Map1Vertex4 && !ctx->Eval.Map1Vertex3 && |
!ctx->Eval.Map1Attrib[0]) |
purge_flags = (VERT_BIT_EVAL_P1|VERT_BIT_EVAL_C1); |
if (orflag & VERT_BIT_EVAL_P1) { |
eval_points1( store->Attrib[VERT_ATTRIB_POS] + IM->CopyStart, |
coord, flags, |
ctx->Eval.MapGrid1du, |
ctx->Eval.MapGrid1u1); |
coord = store->Attrib[VERT_ATTRIB_POS] + IM->CopyStart; |
} |
} |
if (any_eval2) { |
req |= tnl->pipeline.inputs |
& (tnl->eval.EvalMap2Flags | tnl->eval.EvalMap2AttribFlags); |
if (!ctx->Eval.Map2Vertex4 && !ctx->Eval.Map2Vertex3 && |
!ctx->Eval.Map2Attrib[0]) |
purge_flags |= (VERT_BIT_EVAL_P2|VERT_BIT_EVAL_C2); |
if (orflag & VERT_BIT_EVAL_P2) { |
eval_points2( store->Attrib[VERT_ATTRIB_POS] + IM->CopyStart, |
coord, flags, |
ctx->Eval.MapGrid2du, |
ctx->Eval.MapGrid2u1, |
ctx->Eval.MapGrid2dv, |
ctx->Eval.MapGrid2v1 ); |
coord = store->Attrib[VERT_ATTRIB_POS] + IM->CopyStart; |
} |
} |
/* Perform the evaluations on active data elements. |
*/ |
if (req & VERT_BIT_INDEX) { |
GLuint generated = 0; |
if (copycount) |
copy_1ui( store->Index + IM->CopyStart, tmp->Index.data, copycount ); |
tmp->Index.data = store->Index + IM->CopyStart; |
tmp->Index.start = store->Index + IM->CopyStart; |
if (ctx->Eval.Map1Index && any_eval1) { |
eval1_1ui( &tmp->Index, coord, flags, &ctx->EvalMap.Map1Index ); |
generated |= VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1; |
} |
if (ctx->Eval.Map2Index && any_eval2) { |
eval2_1ui( &tmp->Index, coord, flags, &ctx->EvalMap.Map2Index ); |
generated |= VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2; |
} |
} |
if (req & VERT_BIT_COLOR0) { |
GLuint generated = 0; |
if (copycount) |
copy_4f_stride( store->Attrib[VERT_ATTRIB_COLOR0] + IM->CopyStart, |
(GLfloat *)tmp->Color.Ptr, |
tmp->Color.StrideB, |
copycount ); |
tmp->Color.Ptr = store->Attrib[VERT_ATTRIB_COLOR0] + IM->CopyStart; |
tmp->Color.StrideB = 4 * sizeof(GLfloat); |
tmp->Color.Flags = 0; |
tnl->vb.importable_data &= ~VERT_BIT_COLOR0; |
if (ctx->VertexProgram.Enabled) { |
tmp->Attribs[VERT_ATTRIB_COLOR0].data = |
store->Attrib[VERT_ATTRIB_COLOR0] + IM->CopyStart; |
tmp->Attribs[VERT_ATTRIB_COLOR0].start = |
(GLfloat *) tmp->Attribs[VERT_ATTRIB_COLOR0].data; |
tmp->Attribs[VERT_ATTRIB_COLOR0].size = 0; |
} |
/* Vertex program maps have priority over conventional attribs */ |
if (any_eval1) { |
if (ctx->VertexProgram.Enabled |
&& ctx->Eval.Map1Attrib[VERT_ATTRIB_COLOR0]) { |
eval1_4f_ca( &tmp->Color, coord, flags, 4, |
&ctx->EvalMap.Map1Attrib[VERT_ATTRIB_COLOR0] ); |
generated |= VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1; |
} |
else if (ctx->Eval.Map1Color4) { |
eval1_4f_ca( &tmp->Color, coord, flags, 4, |
&ctx->EvalMap.Map1Color4 ); |
generated |= VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1; |
} |
} |
if (any_eval2) { |
if (ctx->VertexProgram.Enabled |
&& ctx->Eval.Map2Attrib[VERT_ATTRIB_COLOR0]) { |
eval2_4f_ca( &tmp->Color, coord, flags, 4, |
&ctx->EvalMap.Map2Attrib[VERT_ATTRIB_COLOR0] ); |
generated |= VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2; |
} |
else if (ctx->Eval.Map2Color4) { |
eval2_4f_ca( &tmp->Color, coord, flags, 4, |
&ctx->EvalMap.Map2Color4 ); |
generated |= VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2; |
} |
} |
} |
if (req & VERT_BIT_TEX0) { |
GLuint generated = 0; |
if (copycount) |
copy_4f( store->Attrib[VERT_ATTRIB_TEX0] + IM->CopyStart, |
tmp->TexCoord[0].data, copycount ); |
else |
tmp->TexCoord[0].size = 0; |
tmp->TexCoord[0].data = store->Attrib[VERT_ATTRIB_TEX0] + IM->CopyStart; |
tmp->TexCoord[0].start = (GLfloat *)tmp->TexCoord[0].data; |
if (ctx->VertexProgram.Enabled) { |
tmp->Attribs[VERT_ATTRIB_TEX0].data = |
store->Attrib[VERT_ATTRIB_TEX0] + IM->CopyStart; |
tmp->Attribs[VERT_ATTRIB_TEX0].start = |
(GLfloat *) tmp->Attribs[VERT_ATTRIB_TEX0].data; |
tmp->Attribs[VERT_ATTRIB_TEX0].size = 0; |
} |
/* Vertex program maps have priority over conventional attribs */ |
if (any_eval1) { |
if (ctx->VertexProgram.Enabled |
&& ctx->Eval.Map1Attrib[VERT_ATTRIB_TEX0]) { |
eval1_4f( &tmp->TexCoord[0], coord, flags, 4, |
&ctx->EvalMap.Map1Attrib[VERT_ATTRIB_TEX0] ); |
generated |= VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1; |
} |
else if (ctx->Eval.Map1TextureCoord4) { |
eval1_4f( &tmp->TexCoord[0], coord, flags, 4, |
&ctx->EvalMap.Map1Texture4 ); |
generated |= VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1; |
} |
else if (ctx->Eval.Map1TextureCoord3) { |
eval1_4f( &tmp->TexCoord[0], coord, flags, 3, |
&ctx->EvalMap.Map1Texture3 ); |
generated |= VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1; |
} |
else if (ctx->Eval.Map1TextureCoord2) { |
eval1_4f( &tmp->TexCoord[0], coord, flags, 2, |
&ctx->EvalMap.Map1Texture2 ); |
generated |= VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1; |
} |
else if (ctx->Eval.Map1TextureCoord1) { |
eval1_4f( &tmp->TexCoord[0], coord, flags, 1, |
&ctx->EvalMap.Map1Texture1 ); |
generated |= VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1; |
} |
} |
if (any_eval2) { |
if (ctx->VertexProgram.Enabled |
&& ctx->Eval.Map2Attrib[VERT_ATTRIB_TEX0]) { |
eval2_4f( &tmp->TexCoord[0], coord, flags, 4, |
&ctx->EvalMap.Map2Attrib[VERT_ATTRIB_TEX0] ); |
generated |= VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1; |
} |
else if (ctx->Eval.Map2TextureCoord4) { |
eval2_4f( &tmp->TexCoord[0], coord, flags, 4, |
&ctx->EvalMap.Map2Texture4 ); |
generated |= VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2; |
} |
else if (ctx->Eval.Map2TextureCoord3) { |
eval2_4f( &tmp->TexCoord[0], coord, flags, 3, |
&ctx->EvalMap.Map2Texture3 ); |
generated |= VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2; |
} |
else if (ctx->Eval.Map2TextureCoord2) { |
eval2_4f( &tmp->TexCoord[0], coord, flags, 2, |
&ctx->EvalMap.Map2Texture2 ); |
generated |= VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2; |
} |
else if (ctx->Eval.Map2TextureCoord1) { |
eval2_4f( &tmp->TexCoord[0], coord, flags, 1, |
&ctx->EvalMap.Map2Texture1 ); |
generated |= VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2; |
} |
} |
} |
if (req & VERT_BIT_NORMAL) { |
GLuint generated = 0; |
if (copycount) { |
copy_3f( store->Attrib[VERT_ATTRIB_NORMAL] + IM->CopyStart, |
tmp->Normal.data, copycount ); |
} |
tmp->Normal.data = store->Attrib[VERT_ATTRIB_NORMAL] + IM->CopyStart; |
tmp->Normal.start = (GLfloat *)tmp->Normal.data; |
if (ctx->VertexProgram.Enabled) { |
tmp->Attribs[VERT_ATTRIB_NORMAL].data = |
store->Attrib[VERT_ATTRIB_NORMAL] + IM->CopyStart; |
tmp->Attribs[VERT_ATTRIB_NORMAL].start = |
(GLfloat *) tmp->Attribs[VERT_ATTRIB_NORMAL].data; |
tmp->Attribs[VERT_ATTRIB_NORMAL].size = 0; |
} |
if (any_eval1) { |
if (ctx->VertexProgram.Enabled && |
ctx->Eval.Map1Attrib[VERT_ATTRIB_NORMAL]) { |
eval1_norm( &tmp->Normal, coord, flags, |
&ctx->EvalMap.Map1Attrib[VERT_ATTRIB_NORMAL] ); |
generated |= VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1; |
} |
else if (ctx->Eval.Map1Normal) { |
eval1_norm( &tmp->Normal, coord, flags, &ctx->EvalMap.Map1Normal ); |
generated |= VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1; |
} |
} |
if (any_eval2) { |
if (ctx->VertexProgram.Enabled && |
ctx->Eval.Map2Attrib[VERT_ATTRIB_NORMAL]) { |
eval2_norm( &tmp->Normal, coord, flags, |
&ctx->EvalMap.Map2Attrib[VERT_ATTRIB_NORMAL] ); |
generated |= VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2; |
} |
else if (ctx->Eval.Map2Normal) { |
eval2_norm( &tmp->Normal, coord, flags, &ctx->EvalMap.Map2Normal ); |
generated |= VERT_BIT_EVAL_C2|VERT_BIT_EVAL_P2; |
} |
} |
} |
/* In the AutoNormal case, the copy and assignment of tmp->NormalPtr |
* are done above. |
*/ |
if (req & VERT_BIT_POS) { |
if (copycount) { |
/* This copy may already have occurred when eliminating |
* glEvalPoint calls: |
*/ |
if (coord != store->Attrib[VERT_ATTRIB_POS] + IM->CopyStart) { |
copy_4f( store->Attrib[VERT_ATTRIB_POS] + IM->CopyStart, |
tmp->Obj.data, copycount ); |
} |
} |
else { |
tmp->Obj.size = 0; |
} |
tmp->Obj.data = store->Attrib[VERT_ATTRIB_POS] + IM->CopyStart; |
tmp->Obj.start = (GLfloat *) tmp->Obj.data; |
#if 1 |
/*tmp->Attribs[0].count = count;*/ |
tmp->Attribs[0].data = store->Attrib[0] + IM->CopyStart; |
tmp->Attribs[0].start = (GLfloat *) tmp->Attribs[0].data; |
tmp->Attribs[0].size = 0; |
#endif |
/* Note: Normal data is already prepared above. |
*/ |
if (any_eval1) { |
if (ctx->VertexProgram.Enabled && |
ctx->Eval.Map1Attrib[VERT_ATTRIB_POS]) { |
eval1_4f( &tmp->Obj, coord, flags, 4, |
&ctx->EvalMap.Map1Attrib[VERT_ATTRIB_POS] ); |
} |
else if (ctx->Eval.Map1Vertex4) { |
eval1_4f( &tmp->Obj, coord, flags, 4, |
&ctx->EvalMap.Map1Vertex4 ); |
} |
else if (ctx->Eval.Map1Vertex3) { |
eval1_4f( &tmp->Obj, coord, flags, 3, |
&ctx->EvalMap.Map1Vertex3 ); |
} |
} |
if (any_eval2) { |
if (ctx->VertexProgram.Enabled && |
ctx->Eval.Map2Attrib[VERT_ATTRIB_POS]) { |
if (ctx->Eval.AutoNormal && (req & VERT_BIT_NORMAL)) |
eval2_obj_norm( &tmp->Obj, &tmp->Normal, coord, flags, 4, |
&ctx->EvalMap.Map2Attrib[VERT_ATTRIB_POS] ); |
else |
eval2_4f( &tmp->Obj, coord, flags, 4, |
&ctx->EvalMap.Map2Attrib[VERT_ATTRIB_POS] ); |
} |
else if (ctx->Eval.Map2Vertex4) { |
if (ctx->Eval.AutoNormal && (req & VERT_BIT_NORMAL)) |
eval2_obj_norm( &tmp->Obj, &tmp->Normal, coord, flags, 4, |
&ctx->EvalMap.Map2Vertex4 ); |
else |
eval2_4f( &tmp->Obj, coord, flags, 4, |
&ctx->EvalMap.Map2Vertex4 ); |
} |
else if (ctx->Eval.Map2Vertex3) { |
if (ctx->Eval.AutoNormal && (req & VERT_BIT_NORMAL)) |
eval2_obj_norm( &tmp->Obj, &tmp->Normal, coord, flags, 3, |
&ctx->EvalMap.Map2Vertex3 ); |
else |
eval2_4f( &tmp->Obj, coord, flags, 3, |
&ctx->EvalMap.Map2Vertex3 ); |
} |
} |
} |
if (ctx->VertexProgram.Enabled) { |
/* We already evaluated position, normal, color and texture 0 above. |
* now evaluate any other generic attributes. |
*/ |
const GLuint skipBits = (VERT_BIT_POS | |
VERT_BIT_NORMAL | |
VERT_BIT_COLOR0 | |
VERT_BIT_TEX0); |
GLuint generated = 0; |
GLuint attr; |
for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { |
if ((1 << attr) & req & ~skipBits) { |
if (any_eval1 && ctx->Eval.Map1Attrib[attr]) { |
/* evaluate 1-D vertex attrib map [i] */ |
eval1_4f( &tmp->Attribs[attr], coord, flags, 4, |
&ctx->EvalMap.Map1Attrib[attr] ); |
generated |= VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1; |
} |
if (any_eval2 && ctx->Eval.Map2Attrib[attr]) { |
/* evaluate 2-D vertex attrib map [i] */ |
eval2_4f( &tmp->Attribs[attr], coord, flags, 4, |
&ctx->EvalMap.Map2Attrib[attr] ); |
generated |= VERT_BIT_EVAL_C1|VERT_BIT_EVAL_P1; |
} |
} |
} |
} |
/* Calculate new IM->Elts, IM->Primitive, IM->PrimitiveLength for |
* the case where vertex maps are not enabled for some received |
* eval coordinates. In this case those slots in the immediate |
* must be ignored. |
*/ |
if (purge_flags) { |
const GLuint vertex = VERT_BIT_POS|(VERT_BITS_EVAL_ANY & ~purge_flags); |
GLuint last_new_prim = 0; |
GLuint new_prim_length = 0; |
GLuint next_old_prim = 0; |
struct vertex_buffer *VB = &tnl->vb; |
const GLuint count = VB->Count; |
GLuint i, j; |
for (i = 0, j = 0 ; i < count ; i++) { |
if (flags[i] & vertex) { |
store->Elt[j++] = i; |
new_prim_length++; |
} |
if (i == next_old_prim) { |
next_old_prim += VB->PrimitiveLength[i]; |
VB->PrimitiveLength[last_new_prim] = new_prim_length; |
VB->Primitive[j] = VB->Primitive[i]; |
last_new_prim = j; |
} |
} |
VB->Elts = store->Elt; |
_tnl_get_purged_copy_verts( ctx, store ); |
} |
/* Produce new flags array: |
*/ |
{ |
const GLuint count = tnl->vb.Count + 1; |
GLuint i; |
copy_1ui( store->Flag, flags, count ); |
tnl->vb.Flag = store->Flag; |
for (i = 0 ; i < count ; i++) |
store->Flag[i] |= req; |
IM->Evaluated = req; /* hack for copying. */ |
} |
} |
/shark/trunk/ports/mesa/src/tnl/t_imm_exec.h |
---|
0,0 → 1,70 |
/* $Id: t_imm_exec.h,v 1.1 2003-02-28 11:48:07 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 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. |
*/ |
#ifndef _T_VBXFORM_H |
#define _T_VBXFORM_H |
#include "mtypes.h" |
#include "t_context.h" |
/* Hook for ctx->Driver.FlushVertices: |
*/ |
extern void _tnl_flush_vertices( GLcontext *ctx, GLuint flush_flags ); |
/* Called from imm_api.c and _tnl_flush_vertices: |
*/ |
extern void _tnl_flush_immediate( GLcontext *ctx, struct immediate *IM ); |
/* Called from imm_dlist.c and _tnl_flush_immediate: |
*/ |
extern void _tnl_run_cassette( GLcontext *ctx, struct immediate *IM ); |
extern void _tnl_copy_to_current( GLcontext *ctx, struct immediate *IM, |
GLuint flag, GLuint row ); |
/* Initialize some stuff: |
*/ |
extern void _tnl_imm_init( GLcontext *ctx ); |
extern void _tnl_imm_destroy( GLcontext *ctx ); |
extern void _tnl_reset_exec_input( GLcontext *ctx, |
GLuint start, |
GLuint beginstate, |
GLuint savedbeginstate ); |
extern void _tnl_reset_compile_input( GLcontext *ctx, |
GLuint start, |
GLuint beginstate, |
GLuint savedbeginstate ); |
extern void _tnl_compute_orflag( struct immediate *IM, GLuint start ); |
extern void _tnl_execute_cassette( GLcontext *ctx, struct immediate *IM ); |
#endif |
/shark/trunk/ports/mesa/src/tnl/t_imm_elt.h |
---|
0,0 → 1,46 |
/* $Id: t_imm_elt.h,v 1.1 2003-02-28 11:48:07 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included |
* in all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
* |
* Authors: |
* Keith Whitwell <keith@tungstengraphics.com> |
*/ |
#ifndef _T_IMM_ELT_H_ |
#define _T_IMM_ELT_H_ |
#include "mtypes.h" |
#include "t_context.h" |
extern void _tnl_imm_elt_init( void ); |
extern void _tnl_translate_array_elts( GLcontext *ctx, |
struct immediate *IM, |
GLuint start, |
GLuint end ); |
#endif |
/shark/trunk/ports/mesa/src/tnl/t_imm_debug.h |
---|
0,0 → 1,39 |
/* $Id: t_imm_debug.h,v 1.1 2003-02-28 11:48:06 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included |
* in all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
* |
* Authors: |
* Keith Whitwell <keith@tungstengraphics.com> |
*/ |
#ifndef _T_DEBUG_H |
#define _T_DEBUG_H |
#include "mtypes.h" |
#include "t_context.h" |
void _tnl_print_cassette( struct immediate *IM ); |
void _tnl_print_vert_flags( const char *name, GLuint flags ); |
#endif |
/shark/trunk/ports/mesa/src/tnl/t_vb_light.c |
---|
0,0 → 1,350 |
/* $Id: t_vb_light.c,v 1.1 2003-02-28 11:48:07 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included |
* in all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
*/ |
#include "glheader.h" |
#include "colormac.h" |
#include "light.h" |
#include "macros.h" |
#include "imports.h" |
#include "mmath.h" |
#include "simple_list.h" |
#include "mtypes.h" |
#include "math/m_translate.h" |
#include "t_context.h" |
#include "t_pipeline.h" |
#define LIGHT_FLAGS 0x1 /* must be first */ |
#define LIGHT_TWOSIDE 0x2 |
#define LIGHT_COLORMATERIAL 0x4 |
#define MAX_LIGHT_FUNC 0x8 |
typedef void (*light_func)( GLcontext *ctx, |
struct vertex_buffer *VB, |
struct gl_pipeline_stage *stage, |
GLvector4f *input ); |
struct light_stage_data { |
struct gl_client_array FloatColor; |
struct gl_client_array LitColor[2]; |
struct gl_client_array LitSecondary[2]; |
GLvector1ui LitIndex[2]; |
light_func *light_func_tab; |
}; |
#define LIGHT_STAGE_DATA(stage) ((struct light_stage_data *)(stage->privatePtr)) |
static void import_color_material( GLcontext *ctx, |
struct gl_pipeline_stage *stage ) |
{ |
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; |
struct gl_client_array *to = &LIGHT_STAGE_DATA(stage)->FloatColor; |
struct gl_client_array *from = VB->ColorPtr[0]; |
GLuint count = VB->Count; |
if (!to->Ptr) { |
to->Ptr = ALIGN_MALLOC( VB->Size * 4 * sizeof(GLfloat), 32 ); |
to->Type = GL_FLOAT; |
} |
/* No need to transform the same value 3000 times. |
*/ |
if (!from->StrideB) { |
to->StrideB = 0; |
count = 1; |
} |
else |
to->StrideB = 4 * sizeof(GLfloat); |
_math_trans_4f( (GLfloat (*)[4]) to->Ptr, |
from->Ptr, |
from->StrideB, |
from->Type, |
from->Size, |
0, |
count); |
VB->ColorPtr[0] = to; |
} |
/* 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]; |
static light_func _tnl_light_ci_tab[MAX_LIGHT_FUNC]; |
#define TAG(x) x |
#define IDX (0) |
#include "t_vb_lighttmp.h" |
#define TAG(x) x##_tw |
#define IDX (LIGHT_TWOSIDE) |
#include "t_vb_lighttmp.h" |
#define TAG(x) x##_fl |
#define IDX (LIGHT_FLAGS) |
#include "t_vb_lighttmp.h" |
#define TAG(x) x##_tw_fl |
#define IDX (LIGHT_FLAGS|LIGHT_TWOSIDE) |
#include "t_vb_lighttmp.h" |
#define TAG(x) x##_cm |
#define IDX (LIGHT_COLORMATERIAL) |
#include "t_vb_lighttmp.h" |
#define TAG(x) x##_tw_cm |
#define IDX (LIGHT_TWOSIDE|LIGHT_COLORMATERIAL) |
#include "t_vb_lighttmp.h" |
#define TAG(x) x##_fl_cm |
#define IDX (LIGHT_FLAGS|LIGHT_COLORMATERIAL) |
#include "t_vb_lighttmp.h" |
#define TAG(x) x##_tw_fl_cm |
#define IDX (LIGHT_FLAGS|LIGHT_TWOSIDE|LIGHT_COLORMATERIAL) |
#include "t_vb_lighttmp.h" |
static void init_lighting( void ) |
{ |
static int done; |
if (!done) { |
init_light_tab(); |
init_light_tab_tw(); |
init_light_tab_fl(); |
init_light_tab_tw_fl(); |
init_light_tab_cm(); |
init_light_tab_tw_cm(); |
init_light_tab_fl_cm(); |
init_light_tab_tw_fl_cm(); |
done = 1; |
} |
} |
static GLboolean run_lighting( GLcontext *ctx, struct gl_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->ObjPtr; |
GLuint ind; |
/* _tnl_print_vert_flags( __FUNCTION__, stage->changed_inputs ); */ |
/* Make sure we can talk about elements 0..2 in the vector we are |
* lighting. |
*/ |
if (stage->changed_inputs & (VERT_BIT_EYE|VERT_BIT_POS)) { |
if (input->size <= 2) { |
if (input->flags & VEC_NOT_WRITEABLE) { |
ASSERT(VB->importable_data & VERT_BIT_POS); |
VB->import_data( ctx, VERT_BIT_POS, VEC_NOT_WRITEABLE ); |
input = ctx->_NeedEyeCoords ? VB->EyePtr : VB->ObjPtr; |
ASSERT((input->flags & VEC_NOT_WRITEABLE) == 0); |
} |
_mesa_vector4f_clean_elem(input, VB->Count, 2); |
} |
} |
if (VB->Flag) |
ind = LIGHT_FLAGS; |
else |
ind = 0; |
/* The individual functions know about replaying side-effects |
* vs. full re-execution. |
*/ |
store->light_func_tab[ind]( ctx, VB, stage, input ); |
return GL_TRUE; |
} |
/* Called in place of do_lighting when the light table may have changed. |
*/ |
static GLboolean run_validate_lighting( GLcontext *ctx, |
struct gl_pipeline_stage *stage ) |
{ |
GLuint ind = 0; |
light_func *tab; |
if (ctx->Visual.rgbMode) { |
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; |
} |
} |
else |
tab = _tnl_light_ci_tab; |
if (ctx->Light.ColorMaterialEnabled) |
ind |= LIGHT_COLORMATERIAL; |
if (ctx->Light.Model.TwoSide) |
ind |= LIGHT_TWOSIDE; |
LIGHT_STAGE_DATA(stage)->light_func_tab = &tab[ind]; |
/* This and the above should only be done on _NEW_LIGHT: |
*/ |
TNL_CONTEXT(ctx)->Driver.NotifyMaterialChange( ctx ); |
/* Now run the stage... |
*/ |
stage->run = run_lighting; |
return stage->run( ctx, stage ); |
} |
static void alloc_4chan( struct gl_client_array *a, GLuint sz ) |
{ |
a->Ptr = ALIGN_MALLOC( sz * sizeof(GLchan) * 4, 32 ); |
a->Size = 4; |
a->Type = CHAN_TYPE; |
a->Stride = 0; |
a->StrideB = sizeof(GLchan) * 4; |
a->Enabled = 0; |
a->Flags = 0; |
} |
/* Called the first time stage->run is called. In effect, don't |
* allocate data until the first time the stage is run. |
*/ |
static GLboolean run_init_lighting( GLcontext *ctx, |
struct gl_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(); |
store->FloatColor.Ptr = 0; |
alloc_4chan( &store->LitColor[0], size ); |
alloc_4chan( &store->LitColor[1], size ); |
alloc_4chan( &store->LitSecondary[0], size ); |
alloc_4chan( &store->LitSecondary[1], size ); |
_mesa_vector1ui_alloc( &store->LitIndex[0], 0, size, 32 ); |
_mesa_vector1ui_alloc( &store->LitIndex[1], 0, size, 32 ); |
/* Now validate the stage derived data... |
*/ |
stage->run = run_validate_lighting; |
return stage->run( ctx, stage ); |
} |
/* |
* Check if lighting is enabled. If so, configure the pipeline stage's |
* type, inputs, and outputs. |
*/ |
static void check_lighting( GLcontext *ctx, struct gl_pipeline_stage *stage ) |
{ |
stage->active = ctx->Light.Enabled && !ctx->VertexProgram.Enabled; |
if (stage->active) { |
if (stage->privatePtr) |
stage->run = run_validate_lighting; |
stage->inputs = VERT_BIT_NORMAL|VERT_BIT_MATERIAL; |
if (ctx->Light._NeedVertices) |
stage->inputs |= VERT_BIT_EYE; /* effectively, even when lighting in obj */ |
if (ctx->Light.ColorMaterialEnabled) |
stage->inputs |= VERT_BIT_COLOR0; |
stage->outputs = VERT_BIT_COLOR0; |
if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) |
stage->outputs |= VERT_BIT_COLOR1; |
} |
} |
static void dtr( struct gl_pipeline_stage *stage ) |
{ |
struct light_stage_data *store = LIGHT_STAGE_DATA(stage); |
if (store) { |
ALIGN_FREE( store->LitColor[0].Ptr ); |
ALIGN_FREE( store->LitColor[1].Ptr ); |
ALIGN_FREE( store->LitSecondary[0].Ptr ); |
ALIGN_FREE( store->LitSecondary[1].Ptr ); |
if (store->FloatColor.Ptr) |
ALIGN_FREE( store->FloatColor.Ptr ); |
_mesa_vector1ui_free( &store->LitIndex[0] ); |
_mesa_vector1ui_free( &store->LitIndex[1] ); |
FREE( store ); |
stage->privatePtr = 0; |
} |
} |
const struct gl_pipeline_stage _tnl_lighting_stage = |
{ |
"lighting", /* name */ |
_NEW_LIGHT, /* recheck */ |
_NEW_LIGHT|_NEW_MODELVIEW, /* recalc -- modelview dependency |
* otherwise not captured by inputs |
* (which may be VERT_BIT_POS) */ |
GL_FALSE, /* active? */ |
0, /* inputs */ |
0, /* outputs */ |
0, /* changed_inputs */ |
NULL, /* private_data */ |
dtr, /* destroy */ |
check_lighting, /* check */ |
run_init_lighting /* run -- initially set to ctr */ |
}; |
/shark/trunk/ports/mesa/src/tnl/t_imm_eval.h |
---|
0,0 → 1,39 |
/* $Id: t_imm_eval.h,v 1.1 2003-02-28 11:48:07 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 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. |
*/ |
#ifndef _T_IMM_EVAL_H |
#define _T_IMM_EVAL_H |
#include "mtypes.h" |
#include "t_context.h" |
extern void _tnl_eval_init( void ); |
extern void _tnl_eval_immediate( GLcontext *ctx, struct immediate *IM ); |
#endif |
/shark/trunk/ports/mesa/src/tnl/t_vb_program.c |
---|
0,0 → 1,477 |
/* $Id: t_vb_program.c,v 1.1 2003-02-28 11:48:07 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 5.0 |
* |
* 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. |
*/ |
/* |
* -------- Regarding NV_vertex_program -------- |
* Redistribution and use in source and binary forms, with or without |
* modification, are permitted provided that the following conditions are met: |
* |
* o Redistribution of the source code must contain a copyright notice |
* and this list of conditions; |
* |
* o Redistribution in binary and source code form must contain the |
* following Notice in the software and any documentation and/or other |
* materials provided with the distribution; and |
* |
* o The name of Nvidia may not be used to promote or endorse software |
* derived from the software. |
* |
* NOTICE: Nvidia hereby grants to each recipient a non-exclusive worldwide |
* royalty free patent license under patent claims that are licensable by |
* Nvidia and which are necessarily required and for which no commercially |
* viable non infringing alternative exists to make, use, sell, offer to sell, |
* import and otherwise transfer the vertex extension for the Mesa 3D Graphics |
* Library as distributed in source code and object code form. No hardware or |
* hardware implementation (including a semiconductor implementation and chips) |
* are licensed hereunder. If a recipient makes a patent claim or institutes |
* patent litigation against Nvidia or Nvidia's customers for use or sale of |
* Nvidia products, then this license grant as to such recipient shall |
* immediately terminate and recipient immediately agrees to cease use and |
* distribution of the Mesa Program and derivatives thereof. |
* |
* THE MESA 3D GRAPHICS LIBRARY IS PROVIDED ON AN "AS IS BASIS, WITHOUT |
* WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, |
* WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-NFRINGEMENT |
* MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. |
* |
* NVIDIA SHALL NOT HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION |
* LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
* ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE MESA 3D GRAPHICS |
* LIBRARY OR EVIDENCE OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDR, EVEN |
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
* |
* If you do not comply with this agreement, then Nvidia may cancel the license |
* and rights granted herein. |
* --------------------------------------------- |
*/ |
/** |
* \file tnl/t_vb_program.c |
* \brief Pipeline stage for executing vertex programs |
* \author Brian Paul, Keith Whitwell |
*/ |
#include "glheader.h" |
#include "api_noop.h" |
#include "colormac.h" |
#include "context.h" |
#include "dlist.h" |
#include "hash.h" |
#include "light.h" |
#include "macros.h" |
#include "imports.h" |
#include "mmath.h" |
#include "simple_list.h" |
#include "mtypes.h" |
#include "vpexec.h" |
#include "math/m_translate.h" |
#include "t_context.h" |
#include "t_pipeline.h" |
#include "t_imm_api.h" |
#include "t_imm_exec.h" |
/** |
* \warning These values _MUST_ match the values in the OutputRegisters[] |
* array in vpparse.c!!! |
*/ |
#define VERT_RESULT_HPOS 0 |
#define VERT_RESULT_COL0 1 |
#define VERT_RESULT_COL1 2 |
#define VERT_RESULT_BFC0 3 |
#define VERT_RESULT_BFC1 4 |
#define VERT_RESULT_FOGC 5 |
#define VERT_RESULT_PSIZ 6 |
#define VERT_RESULT_TEX0 7 |
#define VERT_RESULT_TEX1 8 |
#define VERT_RESULT_TEX2 9 |
#define VERT_RESULT_TEX3 10 |
#define VERT_RESULT_TEX4 11 |
#define VERT_RESULT_TEX5 12 |
#define VERT_RESULT_TEX6 13 |
#define VERT_RESULT_TEX7 14 |
/*! |
* Private storage for the vertex program pipeline stage. |
*/ |
struct vp_stage_data { |
/** The results of running the vertex program go into these arrays. */ |
GLvector4f attribs[15]; |
/* These point to the attribs[VERT_RESULT_COL0, COL1, BFC0, BFC1] arrays */ |
struct gl_client_array color0[2]; /**< diffuse front and back */ |
struct gl_client_array color1[2]; /**< specular front and back */ |
GLvector4f ndcCoords; /**< normalized device coords */ |
GLubyte *clipmask; /**< clip flags */ |
GLubyte ormask, andmask; /**< for clipping */ |
}; |
#define VP_STAGE_DATA(stage) ((struct vp_stage_data *)(stage->privatePtr)) |
/** |
* This function executes vertex programs |
*/ |
static GLboolean run_vp( GLcontext *ctx, struct gl_pipeline_stage *stage ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vp_stage_data *store = VP_STAGE_DATA(stage); |
struct vertex_buffer *VB = &tnl->vb; |
struct vp_machine *machine = &(ctx->VertexProgram.Machine); |
struct vp_program *program = ctx->VertexProgram.Current; |
GLuint i; |
_mesa_init_tracked_matrices(ctx); /* load registers with matrices */ |
_mesa_init_vp_registers(ctx); /* init temp and result regs */ |
for (i = 0; i < VB->Count; i++) { |
GLuint attr; |
#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 |
/* load the input attribute registers */ |
if (VB->Flag) { |
/* the traditional glBegin/glVertex/glEnd case */ |
for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { |
if (attr == 0 || (VB->Flag[i] & (1 << attr))) { |
COPY_4V(machine->Registers[VP_INPUT_REG_START + attr], |
VB->AttribPtr[attr]->data[i]); |
} |
} |
} |
else { |
/* the vertex array case */ |
for (attr = 0; attr < VERT_ATTRIB_MAX; attr++) { |
if (program->InputsRead & (1 << attr)) { |
const GLubyte *ptr = (const GLubyte*) VB->AttribPtr[attr]->data; |
const GLuint stride = VB->AttribPtr[attr]->stride; |
const GLfloat *data = (GLfloat *) (ptr + stride * i); |
COPY_4V(machine->Registers[VP_INPUT_REG_START + attr], data); |
/*ASSERT(VB->AttribPtr[attr]->size == 4);*/ |
ASSERT(stride == 4 * sizeof(GLfloat) || stride == 0); |
} |
} |
} |
/* execute the program */ |
ASSERT(program); |
_mesa_exec_program(ctx, program); |
#if 0 |
printf("Output %d: %f, %f, %f, %f\n", i, |
machine->Registers[VP_OUTPUT_REG_START + 0][0], |
machine->Registers[VP_OUTPUT_REG_START + 0][1], |
machine->Registers[VP_OUTPUT_REG_START + 0][2], |
machine->Registers[VP_OUTPUT_REG_START + 0][3]); |
printf(" color: %f, %f, %f, %f\n", |
machine->Registers[VP_OUTPUT_REG_START +_1][0], |
machine->Registers[VP_OUTPUT_REG_START + 1][1], |
machine->Registers[VP_OUTPUT_REG_START + 1][2], |
machine->Registers[VP_OUTPUT_REG_START + 1][3]); |
printf("PointSize[%d]: %g\n", i, |
machine->Registers[VP_OUTPUT_REG_START + VERT_RESULT_PSIZ][0]); |
#endif |
/* Fixup fog an point size results if needed */ |
if (ctx->Fog.Enabled && |
(program->OutputsWritten & (1 << VERT_RESULT_FOGC)) == 0) { |
machine->Registers[VP_OUTPUT_REG_START + VERT_RESULT_FOGC][0] = 1.0; |
} |
if (ctx->VertexProgram.PointSizeEnabled && |
(program->OutputsWritten & (1 << VERT_RESULT_PSIZ)) == 0) { |
machine->Registers[VP_OUTPUT_REG_START + VERT_RESULT_PSIZ][0] |
= ctx->Point.Size; |
} |
/* copy the output registers into the VB->attribs arrays */ |
/* XXX (optimize) could use a conditional and smaller loop limit here */ |
for (attr = 0; attr < 15; attr++) { |
COPY_4V( store->attribs[attr].data[i], |
machine->Registers[VP_OUTPUT_REG_START + attr] ); |
} |
} |
/* Setup the VB pointers so that the next pipeline stages get |
* their data from the right place (the program output arrays). |
*/ |
VB->ClipPtr = &store->attribs[VERT_RESULT_HPOS]; |
VB->ClipPtr->size = 4; |
VB->ClipPtr->count = VB->Count; |
VB->ColorPtr[0] = &store->color0[0]; |
VB->ColorPtr[1] = &store->color0[1]; |
VB->SecondaryColorPtr[0] = &store->color1[0]; |
VB->SecondaryColorPtr[1] = &store->color1[1]; |
VB->FogCoordPtr = &store->attribs[VERT_RESULT_FOGC]; |
VB->PointSizePtr = &store->attribs[VERT_RESULT_PSIZ]; |
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) |
VB->TexCoordPtr[i] = &store->attribs[VERT_RESULT_TEX0 + i]; |
/* Cliptest and perspective divide. Clip functions must clear |
* the clipmask. |
*/ |
store->ormask = 0; |
store->andmask = CLIP_ALL_BITS; |
if (tnl->NeedNdcCoords) { |
VB->NdcPtr = |
_mesa_clip_tab[VB->ClipPtr->size]( VB->ClipPtr, |
&store->ndcCoords, |
store->clipmask, |
&store->ormask, |
&store->andmask ); |
} |
else { |
VB->NdcPtr = 0; |
_mesa_clip_np_tab[VB->ClipPtr->size]( VB->ClipPtr, |
0, |
store->clipmask, |
&store->ormask, |
&store->andmask ); |
} |
if (store->andmask) /* All vertices are outside the frustum */ |
return GL_FALSE; |
/* This is where we'd do clip testing against the user-defined |
* clipping planes, but they're not supported by vertex programs. |
*/ |
VB->ClipOrMask = store->ormask; |
VB->ClipMask = store->clipmask; |
/* XXXX what's this? |
if (VB->ClipPtr == VB->ObjPtr && (VB->importable_data & VERT_BIT_POS)) |
VB->importable_data |= VERT_BIT_CLIP; |
*/ |
return GL_TRUE; |
} |
/** |
* This function validates stuff. |
*/ |
static GLboolean run_validate_program( GLcontext *ctx, |
struct gl_pipeline_stage *stage ) |
{ |
#if 000 |
/* XXX do we need any validation for vertex programs? */ |
GLuint ind = 0; |
light_func *tab; |
if (ctx->Visual.rgbMode) { |
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; |
} |
} |
else |
tab = _tnl_light_ci_tab; |
if (ctx->Light.ColorMaterialEnabled) |
ind |= LIGHT_COLORMATERIAL; |
if (ctx->Light.Model.TwoSide) |
ind |= LIGHT_TWOSIDE; |
VP_STAGE_DATA(stage)->light_func_tab = &tab[ind]; |
/* This and the above should only be done on _NEW_LIGHT: |
*/ |
_mesa_validate_all_lighting_tables( ctx ); |
#endif |
/* Now run the stage... |
*/ |
stage->run = run_vp; |
return stage->run( ctx, stage ); |
} |
/** |
* Initialize a gl_client_array to point into a GLvector4f color vector. |
*/ |
static void init_color_array( struct gl_client_array *a, GLvector4f *vec ) |
{ |
a->Ptr = vec->data; |
a->Size = 4; |
a->Type = GL_FLOAT; |
a->Stride = 0; |
a->StrideB = sizeof(GLfloat) * 4; |
a->Enabled = 0; |
a->Flags = 0; |
} |
/** |
* Called the first time stage->run is called. In effect, don't |
* allocate data until the first time the stage is run. |
*/ |
static GLboolean run_init_vp( GLcontext *ctx, |
struct gl_pipeline_stage *stage ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_buffer *VB = &(tnl->vb); |
struct vp_stage_data *store; |
const GLuint size = VB->Size; |
GLuint i; |
stage->privatePtr = MALLOC(sizeof(*store)); |
store = VP_STAGE_DATA(stage); |
if (!store) |
return GL_FALSE; |
/* Allocate arrays of vertex output values */ |
for (i = 0; i < 15; i++) |
_mesa_vector4f_alloc( &store->attribs[i], 0, size, 32 ); |
/* Make the color0[] and color1[] arrays point into the attribs[] arrays */ |
init_color_array( &store->color0[0], &store->attribs[VERT_RESULT_COL0] ); |
init_color_array( &store->color0[1], &store->attribs[VERT_RESULT_COL1] ); |
init_color_array( &store->color1[0], &store->attribs[VERT_RESULT_BFC0] ); |
init_color_array( &store->color1[1], &store->attribs[VERT_RESULT_BFC1] ); |
/* a few other misc allocations */ |
_mesa_vector4f_alloc( &store->ndcCoords, 0, size, 32 ); |
store->clipmask = (GLubyte *) ALIGN_MALLOC(sizeof(GLubyte)*size, 32 ); |
/* Now validate the stage derived data... |
*/ |
stage->run = run_validate_program; |
return stage->run( ctx, stage ); |
} |
/** |
* Check if vertex program mode is enabled. |
* If so, configure the pipeline stage's type, inputs, and outputs. |
*/ |
static void check_vp( GLcontext *ctx, struct gl_pipeline_stage *stage ) |
{ |
stage->active = ctx->VertexProgram.Enabled; |
if (stage->active) { |
/* I believe this is right - Keith? |
* Set stage->inputs equal to the bitmask of vertex attributes |
* which the program needs for inputs. |
*/ |
stage->inputs = ctx->VertexProgram.Current->InputsRead; |
#if 000 |
if (stage->privatePtr) |
stage->run = run_validate_program; |
stage->inputs = VERT_BIT_NORMAL|VERT_BIT_MATERIAL; |
if (ctx->Light._NeedVertices) |
stage->inputs |= VERT_BIT_EYE; /* effectively, even when lighting in obj */ |
if (ctx->Light.ColorMaterialEnabled) |
stage->inputs |= VERT_BIT_COLOR0; |
stage->outputs = VERT_BIT_COLOR0; |
if (ctx->Light.Model.ColorControl == GL_SEPARATE_SPECULAR_COLOR) |
stage->outputs |= VERT_BIT_COLOR1; |
#endif |
} |
} |
/** |
* Destructor for this pipeline stage. |
*/ |
static void dtr( struct gl_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 < 15; i++) |
_mesa_vector4f_free( &store->attribs[i] ); |
/* free misc arrays */ |
_mesa_vector4f_free( &store->ndcCoords ); |
ALIGN_FREE( store->clipmask ); |
FREE( store ); |
stage->privatePtr = 0; |
} |
} |
/** |
* Public description of this pipeline stage. |
*/ |
const struct gl_pipeline_stage _tnl_vertex_program_stage = |
{ |
"vertex-program", |
_NEW_ALL, /*XXX FIX */ /* recheck */ |
_NEW_ALL, /*XXX FIX */ /* recalc -- modelview dependency |
* otherwise not captured by inputs |
* (which may be VERT_BIT_POS) */ |
GL_FALSE, /* active */ |
/*0*/ VERT_BIT_POS, /* inputs XXX OK? */ |
VERT_BIT_CLIP | VERT_BIT_COLOR0, /* outputs XXX OK? */ |
0, /* changed_inputs */ |
NULL, /* private_data */ |
dtr, /* destroy */ |
check_vp, /* check */ |
run_init_vp /* run -- initially set to ctr */ |
}; |
/shark/trunk/ports/mesa/src/tnl/t_vb_normals.c |
---|
0,0 → 1,199 |
/* $Id: t_vb_normals.c,v 1.1 2003-02-28 11:48:07 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 "mmath.h" |
#include "mtypes.h" |
#include "math/m_xform.h" |
#include "t_context.h" |
#include "t_pipeline.h" |
struct normal_stage_data { |
normal_func NormalTransform; |
GLvector4f normal; |
}; |
#define NORMAL_STAGE_DATA(stage) ((struct normal_stage_data *)stage->privatePtr) |
static GLboolean run_normal_stage( GLcontext *ctx, |
struct gl_pipeline_stage *stage ) |
{ |
struct normal_stage_data *store = NORMAL_STAGE_DATA(stage); |
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; |
ASSERT(store->NormalTransform); |
if (stage->changed_inputs) { |
/* We can only use the display list's saved normal lengths if we've |
* got a transformation matrix with uniform scaling. |
*/ |
const GLfloat *lengths; |
if (ctx->ModelviewMatrixStack.Top->flags & MAT_FLAG_GENERAL_SCALE) |
lengths = NULL; |
else |
lengths = VB->NormalLengthPtr; |
store->NormalTransform( ctx->ModelviewMatrixStack.Top, |
ctx->_ModelViewInvScale, |
VB->NormalPtr, /* input normals */ |
lengths, |
&store->normal ); /* resulting normals */ |
} |
VB->NormalPtr = &store->normal; |
VB->NormalLengthPtr = 0; /* no longer valid */ |
return GL_TRUE; |
} |
static GLboolean run_validate_normal_stage( GLcontext *ctx, |
struct gl_pipeline_stage *stage ) |
{ |
struct normal_stage_data *store = NORMAL_STAGE_DATA(stage); |
ASSERT(ctx->_NeedNormals); |
if (ctx->_NeedEyeCoords) { |
GLuint transform = NORM_TRANSFORM_NO_ROT; |
if (ctx->ModelviewMatrixStack.Top->flags & (MAT_FLAG_GENERAL | |
MAT_FLAG_ROTATION | |
MAT_FLAG_GENERAL_3D | |
MAT_FLAG_PERSPECTIVE)) |
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 { |
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 = 0; |
} |
} |
if (store->NormalTransform) { |
stage->run = run_normal_stage; |
return stage->run( ctx, stage ); |
} else { |
stage->active = GL_FALSE; /* !!! */ |
return GL_TRUE; |
} |
} |
static void check_normal_transform( GLcontext *ctx, |
struct gl_pipeline_stage *stage ) |
{ |
stage->active = ctx->_NeedNormals && !ctx->VertexProgram.Enabled; |
/* Don't clobber the initialize function: |
*/ |
if (stage->privatePtr) |
stage->run = run_validate_normal_stage; |
} |
static GLboolean alloc_normal_data( GLcontext *ctx, |
struct gl_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 ); |
/* Now run the stage. |
*/ |
stage->run = run_validate_normal_stage; |
return stage->run( ctx, stage ); |
} |
static void free_normal_data( struct gl_pipeline_stage *stage ) |
{ |
struct normal_stage_data *store = NORMAL_STAGE_DATA(stage); |
if (store) { |
_mesa_vector4f_free( &store->normal ); |
FREE( store ); |
stage->privatePtr = NULL; |
} |
} |
#define _TNL_NEW_NORMAL_TRANSFORM (_NEW_MODELVIEW| \ |
_NEW_TRANSFORM| \ |
_MESA_NEW_NEED_NORMALS| \ |
_MESA_NEW_NEED_EYE_COORDS) |
const struct gl_pipeline_stage _tnl_normal_transform_stage = |
{ |
"normal transform", /* name */ |
_TNL_NEW_NORMAL_TRANSFORM, /* re-check */ |
_TNL_NEW_NORMAL_TRANSFORM, /* re-run */ |
GL_FALSE, /* active? */ |
VERT_BIT_NORMAL, /* inputs */ |
VERT_BIT_NORMAL, /* outputs */ |
0, /* changed_inputs */ |
NULL, /* private data */ |
free_normal_data, /* destructor */ |
check_normal_transform, /* check */ |
alloc_normal_data /* run -- initially set to alloc */ |
}; |
/shark/trunk/ports/mesa/src/tnl/t_vb_points.c |
---|
0,0 → 1,124 |
/* $Id: t_vb_points.c,v 1.1 2003-02-28 11:48:07 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: |
* Brian Paul |
*/ |
#include "mtypes.h" |
#include "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 attenuated point sizes |
*/ |
static GLboolean run_point_stage( GLcontext *ctx, |
struct gl_pipeline_stage *stage ) |
{ |
struct point_stage_data *store = POINT_STAGE_DATA(stage); |
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; |
const GLfloat (*eye)[4] = (const GLfloat (*)[4]) VB->EyePtr->data; |
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; |
if (stage->changed_inputs) { |
/* XXX do threshold and min/max clamping here? */ |
for (i = 0; i < VB->Count; i++) { |
const GLfloat dist = -eye[i][2]; |
/* GLfloat dist = GL_SQRT(pos[0]*pos[0]+pos[1]*pos[1]+pos[2]*pos[2]);*/ |
size[i][0] = pointSize / (p0 + dist * (p1 + dist * p2)); |
} |
} |
VB->PointSizePtr = &store->PointSize; |
return GL_TRUE; |
} |
/* If point size attenuation is on we'll compute the point size for |
* each vertex in a special pipeline stage. |
*/ |
static void check_point_size( GLcontext *ctx, struct gl_pipeline_stage *d ) |
{ |
d->active = ctx->Point._Attenuated && !ctx->VertexProgram.Enabled; |
} |
static GLboolean alloc_point_data( GLcontext *ctx, |
struct gl_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 ); |
/* Now run the stage. |
*/ |
stage->run = run_point_stage; |
return stage->run( ctx, stage ); |
} |
static void free_point_data( struct gl_pipeline_stage *stage ) |
{ |
struct point_stage_data *store = POINT_STAGE_DATA(stage); |
if (store) { |
_mesa_vector4f_free( &store->PointSize ); |
FREE( store ); |
stage->privatePtr = 0; |
} |
} |
const struct gl_pipeline_stage _tnl_point_attenuation_stage = |
{ |
"point size attenuation", /* name */ |
_NEW_POINT, /* build_state_change */ |
_NEW_POINT, /* run_state_change */ |
GL_FALSE, /* active */ |
VERT_BIT_EYE, /* inputs */ |
VERT_BIT_POINT_SIZE, /* outputs */ |
0, /* changed_inputs (temporary value) */ |
NULL, /* stage private data */ |
free_point_data, /* destructor */ |
check_point_size, /* check */ |
alloc_point_data /* run -- initially set to alloc data */ |
}; |
/shark/trunk/ports/mesa/src/tnl/t_vb_vertex.c |
---|
0,0 → 1,323 |
/* $Id: t_vb_vertex.c,v 1.1 2003-02-28 11:48:08 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 5.0 |
* |
* Copyright (C) 1999-2001 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 "mmath.h" |
#include "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; |
/* Need these because it's difficult to replay the sideeffects |
* analytically. |
*/ |
GLvector4f *save_eyeptr; |
GLvector4f *save_clipptr; |
GLvector4f *save_ndcptr; |
}; |
#define VERTEX_STAGE_DATA(stage) ((struct vertex_stage_data *)stage->privatePtr) |
/* This function implements cliptesting for user-defined clip planes. |
* The clipping of primitives to these planes is implemented in |
* t_render_clip.h. |
*/ |
#define USER_CLIPTEST(NAME, SZ) \ |
static void NAME( GLcontext *ctx, \ |
GLvector4f *clip, \ |
GLubyte *clipmask, \ |
GLubyte *clipormask, \ |
GLubyte *clipandmask ) \ |
{ \ |
GLuint p; \ |
\ |
for (p = 0; p < ctx->Const.MaxClipPlanes; p++) \ |
if (ctx->Transform.ClipPlanesEnabled & (1 << p)) { \ |
GLuint nr, i; \ |
const GLfloat a = ctx->Transform._ClipUserPlane[p][0]; \ |
const GLfloat b = ctx->Transform._ClipUserPlane[p][1]; \ |
const GLfloat c = ctx->Transform._ClipUserPlane[p][2]; \ |
const GLfloat d = ctx->Transform._ClipUserPlane[p][3]; \ |
GLfloat *coord = (GLfloat *)clip->data; \ |
GLuint stride = clip->stride; \ |
GLuint count = clip->count; \ |
\ |
for (nr = 0, i = 0 ; i < count ; i++) { \ |
GLfloat dp = coord[0] * a + coord[1] * b; \ |
if (SZ > 2) dp += coord[2] * c; \ |
if (SZ > 3) dp += coord[3] * d; else dp += d; \ |
\ |
if (dp < 0) { \ |
nr++; \ |
clipmask[i] |= CLIP_USER_BIT; \ |
} \ |
\ |
STRIDE_F(coord, stride); \ |
} \ |
\ |
if (nr > 0) { \ |
*clipormask |= CLIP_USER_BIT; \ |
if (nr == count) { \ |
*clipandmask |= CLIP_USER_BIT; \ |
return; \ |
} \ |
} \ |
} \ |
} |
USER_CLIPTEST(userclip2, 2) |
USER_CLIPTEST(userclip3, 3) |
USER_CLIPTEST(userclip4, 4) |
static void (*(usercliptab[5]))( GLcontext *, |
GLvector4f *, GLubyte *, |
GLubyte *, GLubyte * ) = |
{ |
0, |
0, |
userclip2, |
userclip3, |
userclip4 |
}; |
static GLboolean run_vertex_stage( GLcontext *ctx, |
struct gl_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; |
ASSERT(!ctx->VertexProgram.Enabled); |
if (stage->changed_inputs) { |
if (ctx->_NeedEyeCoords) { |
/* Separate modelview transformation: |
* Use combined ModelProject to avoid some depth artifacts |
*/ |
if (ctx->ModelviewMatrixStack.Top->type == MATRIX_IDENTITY) |
VB->EyePtr = VB->ObjPtr; |
else |
VB->EyePtr = TransformRaw( &store->eye, |
ctx->ModelviewMatrixStack.Top, |
VB->ObjPtr); |
if (ctx->ProjectionMatrixStack.Top->type == MATRIX_IDENTITY) |
VB->ClipPtr = VB->EyePtr; |
else |
VB->ClipPtr = TransformRaw( &store->clip, |
&ctx->_ModelProjectMatrix, |
VB->ObjPtr ); |
} |
else { |
/* Combined modelviewproject transform: |
*/ |
if (ctx->_ModelProjectMatrix.type == MATRIX_IDENTITY) |
VB->ClipPtr = VB->ObjPtr; |
else |
VB->ClipPtr = TransformRaw( &store->clip, |
&ctx->_ModelProjectMatrix, |
VB->ObjPtr ); |
} |
/* Drivers expect this to be clean to element 4... |
*/ |
if (VB->ClipPtr->size < 4) { |
if (VB->ClipPtr->flags & VEC_NOT_WRITEABLE) { |
ASSERT(VB->ClipPtr == VB->ObjPtr); |
VB->import_data( ctx, VERT_BIT_POS, VEC_NOT_WRITEABLE ); |
VB->ClipPtr = VB->ObjPtr; |
} |
if (VB->ClipPtr->size == 2) |
_mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 2 ); |
_mesa_vector4f_clean_elem( VB->ClipPtr, VB->Count, 3 ); |
} |
/* Cliptest and perspective divide. Clip functions must clear |
* the clipmask. |
*/ |
store->ormask = 0; |
store->andmask = CLIP_ALL_BITS; |
if (tnl->NeedNdcCoords) { |
VB->NdcPtr = |
_mesa_clip_tab[VB->ClipPtr->size]( VB->ClipPtr, |
&store->proj, |
store->clipmask, |
&store->ormask, |
&store->andmask ); |
} |
else { |
VB->NdcPtr = 0; |
_mesa_clip_np_tab[VB->ClipPtr->size]( VB->ClipPtr, |
0, |
store->clipmask, |
&store->ormask, |
&store->andmask ); |
} |
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->ClipOrMask = store->ormask; |
VB->ClipMask = store->clipmask; |
if (VB->ClipPtr == VB->ObjPtr && (VB->importable_data & VERT_BIT_POS)) |
VB->importable_data |= VERT_BIT_CLIP; |
store->save_eyeptr = VB->EyePtr; |
store->save_clipptr = VB->ClipPtr; |
store->save_ndcptr = VB->NdcPtr; |
} |
else { |
/* Replay the sideeffects. |
*/ |
VB->EyePtr = store->save_eyeptr; |
VB->ClipPtr = store->save_clipptr; |
VB->NdcPtr = store->save_ndcptr; |
VB->ClipMask = store->clipmask; |
VB->ClipOrMask = store->ormask; |
if (VB->ClipPtr == VB->ObjPtr && (VB->importable_data & VERT_BIT_POS)) |
VB->importable_data |= VERT_BIT_CLIP; |
if (store->andmask) |
return GL_FALSE; |
} |
return GL_TRUE; |
} |
static void check_vertex( GLcontext *ctx, struct gl_pipeline_stage *stage ) |
{ |
stage->active = !ctx->VertexProgram.Enabled; |
} |
static GLboolean init_vertex_stage( GLcontext *ctx, |
struct gl_pipeline_stage *stage ) |
{ |
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb; |
struct vertex_stage_data *store; |
GLuint size = VB->Size; |
stage->privatePtr = CALLOC(sizeof(*store)); |
store = VERTEX_STAGE_DATA(stage); |
if (!store) |
return GL_FALSE; |
_mesa_vector4f_alloc( &store->eye, 0, size, 32 ); |
_mesa_vector4f_alloc( &store->clip, 0, size, 32 ); |
_mesa_vector4f_alloc( &store->proj, 0, size, 32 ); |
store->clipmask = (GLubyte *) ALIGN_MALLOC(sizeof(GLubyte)*size, 32 ); |
if (!store->clipmask || |
!store->eye.data || |
!store->clip.data || |
!store->proj.data) |
return GL_FALSE; |
/* Now run the stage. |
*/ |
stage->run = run_vertex_stage; |
return stage->run( ctx, stage ); |
} |
static void dtr( struct gl_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 ); |
ALIGN_FREE( store->clipmask ); |
FREE(store); |
stage->privatePtr = NULL; |
stage->run = init_vertex_stage; |
} |
} |
const struct gl_pipeline_stage _tnl_vertex_transform_stage = |
{ |
"modelview/project/cliptest/divide", |
_NEW_PROGRAM, /* check_state: only care about vertex prog */ |
_MESA_NEW_NEED_EYE_COORDS | /* run_state: when to invalidate / re-run */ |
_NEW_MODELVIEW| |
_NEW_PROJECTION| |
_NEW_PROGRAM| |
_NEW_TRANSFORM, |
GL_TRUE, /* active */ |
VERT_BIT_POS, /* inputs */ |
VERT_BIT_EYE|VERT_BIT_CLIP, /* outputs */ |
0, /* changed_inputs */ |
NULL, /* private data */ |
dtr, /* destructor */ |
check_vertex, /* check */ |
init_vertex_stage /* run -- initially set to init */ |
}; |
/shark/trunk/ports/mesa/src/tnl/t_pipeline.c |
---|
0,0 → 1,211 |
/* $Id: t_pipeline.c,v 1.1 2003-02-28 11:48:07 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 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 "context.h" |
#include "imports.h" |
#include "mmath.h" |
#include "state.h" |
#include "mtypes.h" |
#include "math/m_translate.h" |
#include "math/m_xform.h" |
#include "t_context.h" |
#include "t_pipeline.h" |
void _tnl_install_pipeline( GLcontext *ctx, |
const struct gl_pipeline_stage **stages ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct gl_pipeline *pipe = &tnl->pipeline; |
GLuint i; |
ASSERT(pipe->nr_stages == 0); |
pipe->run_state_changes = ~0; |
pipe->run_input_changes = ~0; |
pipe->build_state_changes = ~0; |
pipe->build_state_trigger = 0; |
pipe->inputs = 0; |
/* Create a writeable copy of each stage. |
*/ |
for (i = 0 ; i < MAX_PIPELINE_STAGES && stages[i] ; i++) { |
MEMCPY( &pipe->stages[i], stages[i], sizeof( **stages )); |
pipe->build_state_trigger |= pipe->stages[i].check_state; |
} |
MEMSET( &pipe->stages[i], 0, sizeof( **stages )); |
pipe->nr_stages = i; |
} |
void _tnl_destroy_pipeline( GLcontext *ctx ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
GLuint i; |
for (i = 0 ; i < tnl->pipeline.nr_stages ; i++) |
tnl->pipeline.stages[i].destroy( &tnl->pipeline.stages[i] ); |
tnl->pipeline.nr_stages = 0; |
} |
/* TODO: merge validate with run. |
*/ |
void _tnl_validate_pipeline( GLcontext *ctx ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct gl_pipeline *pipe = &tnl->pipeline; |
struct gl_pipeline_stage *s = pipe->stages; |
GLuint newstate = pipe->build_state_changes; |
GLuint generated = 0; |
GLuint changed_inputs = 0; |
pipe->inputs = 0; |
pipe->build_state_changes = 0; |
for ( ; s->check ; s++) { |
s->changed_inputs |= s->inputs & changed_inputs; |
if (s->check_state & newstate) { |
if (s->active) { |
GLuint old_outputs = s->outputs; |
s->check(ctx, s); |
if (!s->active) |
changed_inputs |= old_outputs; |
} |
else |
s->check(ctx, s); |
} |
if (s->active) { |
pipe->inputs |= s->inputs & ~generated; |
generated |= s->outputs; |
} |
} |
} |
void _tnl_run_pipeline( GLcontext *ctx ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_buffer *VB = &tnl->vb; |
struct gl_pipeline *pipe = &tnl->pipeline; |
struct gl_pipeline_stage *s = pipe->stages; |
GLuint changed_state = pipe->run_state_changes; |
GLuint changed_inputs = pipe->run_input_changes; |
GLboolean running = GL_TRUE; |
unsigned short __tmp; |
pipe->run_state_changes = 0; |
pipe->run_input_changes = 0; |
/* Done elsewhere. |
*/ |
ASSERT(pipe->build_state_changes == 0); |
START_FAST_MATH(__tmp); |
/* If something changes in the pipeline, tag all subsequent stages |
* using this value for recalculation. Inactive stages have their |
* state and inputs examined to try to keep cached data alive over |
* state-changes. |
*/ |
for ( ; s->run ; s++) { |
s->changed_inputs |= s->inputs & changed_inputs; |
if (s->run_state & changed_state) |
s->changed_inputs = s->inputs; |
if (s->active && running) { |
if (s->changed_inputs) |
changed_inputs |= s->outputs; |
running = s->run( ctx, s ); |
s->changed_inputs = 0; |
VB->importable_data &= ~s->outputs; |
} |
} |
END_FAST_MATH(__tmp); |
} |
/* The default pipeline. This is useful for software rasterizers, and |
* simple hardware rasterizers. For customization, I don't recommend |
* tampering with the internals of these stages in the way that |
* drivers did in Mesa 3.4. These stages are basically black boxes, |
* and should be left intact. |
* |
* To customize the pipeline, consider: |
* |
* - removing redundant stages (making sure that the software rasterizer |
* can cope with this on fallback paths). An example is fog |
* coordinate generation, which is not required in the FX driver. |
* |
* - replacing general-purpose machine-independent stages with |
* general-purpose machine-specific stages. There is no example of |
* this to date, though it must be borne in mind that all subsequent |
* stages that reference the output of the new stage must cope with |
* any machine-specific data introduced. This may not be easy |
* unless there are no such stages (ie the new stage is the last in |
* the pipe). |
* |
* - inserting optimized (but specialized) stages ahead of the |
* general-purpose fallback implementation. For example, the old |
* fastpath mechanism, which only works when the VERT_BIT_ELT 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 gl_pipeline_stage *_tnl_default_pipeline[] = { |
&_tnl_vertex_transform_stage, |
&_tnl_normal_transform_stage, |
&_tnl_lighting_stage, |
&_tnl_fog_coordinate_stage, |
&_tnl_texgen_stage, |
&_tnl_texture_transform_stage, |
&_tnl_point_attenuation_stage, |
#if FEATURE_NV_vertex_program |
&_tnl_vertex_program_stage, |
#endif |
&_tnl_render_stage, |
0 |
}; |
/shark/trunk/ports/mesa/src/tnl/t_array_api.c |
---|
0,0 → 1,402 |
/* $Id: t_array_api.c,v 1.1 2003-02-28 11:48:06 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. |
*/ |
/** |
* \file vpexec.c |
* \brief Vertex array API functions (glDrawArrays, etc) |
* \author Keith Whitwell |
*/ |
#include "glheader.h" |
#include "api_validate.h" |
#include "context.h" |
#include "imports.h" |
#include "macros.h" |
#include "mmath.h" |
#include "mtypes.h" |
#include "state.h" |
#include "array_cache/acache.h" |
#include "t_array_api.h" |
#include "t_array_import.h" |
#include "t_imm_api.h" |
#include "t_imm_exec.h" |
#include "t_context.h" |
#include "t_pipeline.h" |
static void fallback_drawarrays( GLcontext *ctx, GLenum mode, GLint start, |
GLsizei count ) |
{ |
if (_tnl_hard_begin( ctx, mode )) { |
GLint i; |
for (i = start; i < count; i++) |
glArrayElement( i ); |
glEnd(); |
} |
} |
static void fallback_drawelements( GLcontext *ctx, GLenum mode, GLsizei count, |
const GLuint *indices) |
{ |
if (_tnl_hard_begin(ctx, mode)) { |
GLint i; |
for (i = 0 ; i < count ; i++) |
glArrayElement( indices[i] ); |
glEnd(); |
} |
} |
static void _tnl_draw_range_elements( GLcontext *ctx, GLenum mode, |
GLuint start, GLuint end, |
GLsizei count, const GLuint *indices ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
FLUSH_CURRENT( ctx, 0 ); |
/* _mesa_debug(ctx, "%s\n", __FUNCTION__); */ |
if (tnl->pipeline.build_state_changes) |
_tnl_validate_pipeline( ctx ); |
_tnl_vb_bind_arrays( ctx, start, end ); |
tnl->vb.FirstPrimitive = 0; |
tnl->vb.Primitive[0] = mode | PRIM_BEGIN | PRIM_END | PRIM_LAST; |
tnl->vb.PrimitiveLength[0] = count; |
tnl->vb.Elts = (GLuint *)indices; |
if (ctx->Array.LockCount) |
tnl->Driver.RunPipeline( ctx ); |
else { |
/* Note that arrays may have changed before/after execution. |
*/ |
tnl->pipeline.run_input_changes |= ctx->Array._Enabled; |
tnl->Driver.RunPipeline( ctx ); |
tnl->pipeline.run_input_changes |= ctx->Array._Enabled; |
} |
} |
/** |
* Called via the GL API dispatcher. |
*/ |
void |
_tnl_DrawArrays(GLenum mode, GLint start, GLsizei count) |
{ |
GET_CURRENT_CONTEXT(ctx); |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_buffer *VB = &tnl->vb; |
GLuint thresh = (ctx->Driver.NeedFlush & FLUSH_STORED_VERTICES) ? 30 : 10; |
if (MESA_VERBOSE & VERBOSE_API) |
_mesa_debug(NULL, "_tnl_DrawArrays %d %d\n", start, count); |
/* Check arguments, etc. |
*/ |
if (!_mesa_validate_DrawArrays( ctx, mode, start, count )) |
return; |
if (tnl->pipeline.build_state_changes) |
_tnl_validate_pipeline( ctx ); |
if (ctx->CompileFlag) { |
fallback_drawarrays( ctx, mode, start, start + count ); |
} |
else if (!ctx->Array.LockCount && (GLuint) count < thresh) { |
/* Small primitives: attempt to share a vb (at the expense of |
* using the immediate interface). |
*/ |
fallback_drawarrays( ctx, mode, start, start + count ); |
} |
else if (ctx->Array.LockCount && |
count < (GLint) ctx->Const.MaxArrayLockSize) { |
/* Locked primitives which can fit in a single vertex buffer: |
*/ |
FLUSH_CURRENT( ctx, 0 ); |
if (start < (GLint) ctx->Array.LockFirst) |
start = ctx->Array.LockFirst; |
if (start + count > (GLint) ctx->Array.LockCount) |
count = ctx->Array.LockCount - start; |
/* Locked drawarrays. Reuse any previously transformed data. |
*/ |
_tnl_vb_bind_arrays( ctx, ctx->Array.LockFirst, ctx->Array.LockCount ); |
VB->FirstPrimitive = start; |
VB->Primitive[start] = mode | PRIM_BEGIN | PRIM_END | PRIM_LAST; |
VB->PrimitiveLength[start] = count; |
tnl->Driver.RunPipeline( ctx ); |
} |
else { |
int bufsz = 256; /* Use a small buffer for cache goodness */ |
int j, nr; |
int minimum, modulo, skip; |
/* Large primitives requiring decomposition to multiple vertex |
* buffers: |
*/ |
switch (mode) { |
case GL_POINTS: |
minimum = 0; |
modulo = 1; |
skip = 0; |
case GL_LINES: |
minimum = 1; |
modulo = 2; |
skip = 1; |
case GL_LINE_STRIP: |
minimum = 1; |
modulo = 1; |
skip = 0; |
break; |
case GL_TRIANGLES: |
minimum = 2; |
modulo = 3; |
skip = 2; |
break; |
case GL_TRIANGLE_STRIP: |
minimum = 2; |
modulo = 1; |
skip = 0; |
break; |
case GL_QUADS: |
minimum = 3; |
modulo = 4; |
skip = 3; |
break; |
case GL_QUAD_STRIP: |
minimum = 3; |
modulo = 2; |
skip = 0; |
break; |
case GL_LINE_LOOP: |
case GL_TRIANGLE_FAN: |
case GL_POLYGON: |
default: |
/* Primitives requiring a copied vertex (fan-like primitives) |
* must use the slow path if they cannot fit in a single |
* vertex buffer. |
*/ |
if (count < (GLint) ctx->Const.MaxArrayLockSize) { |
bufsz = ctx->Const.MaxArrayLockSize; |
minimum = 0; |
modulo = 1; |
skip = 0; |
} |
else { |
fallback_drawarrays( ctx, mode, start, start + count ); |
return; |
} |
} |
FLUSH_CURRENT( ctx, 0 ); |
bufsz -= bufsz % modulo; |
bufsz -= minimum; |
count += start; |
for (j = start + minimum ; j < count ; j += nr + skip ) { |
nr = MIN2( bufsz, count - j ); |
_tnl_vb_bind_arrays( ctx, j - minimum, j + nr ); |
VB->FirstPrimitive = 0; |
VB->Primitive[0] = mode | PRIM_BEGIN | PRIM_END | PRIM_LAST; |
VB->PrimitiveLength[0] = nr + minimum; |
tnl->pipeline.run_input_changes |= ctx->Array._Enabled; |
tnl->Driver.RunPipeline( ctx ); |
tnl->pipeline.run_input_changes |= ctx->Array._Enabled; |
} |
} |
} |
/** |
* Called via the GL API dispatcher. |
*/ |
void |
_tnl_DrawRangeElements(GLenum mode, |
GLuint start, GLuint end, |
GLsizei count, GLenum type, const GLvoid *indices) |
{ |
GET_CURRENT_CONTEXT(ctx); |
GLuint *ui_indices; |
if (MESA_VERBOSE & VERBOSE_API) |
_mesa_debug(NULL, "_tnl_DrawRangeElements %d %d %d\n", start, end, count); |
/* Check arguments, etc. |
*/ |
if (!_mesa_validate_DrawRangeElements( ctx, mode, start, end, count, |
type, indices )) |
return; |
ui_indices = (GLuint *)_ac_import_elements( ctx, GL_UNSIGNED_INT, |
count, type, indices ); |
if (ctx->CompileFlag) { |
/* Can't do anything when compiling: |
*/ |
fallback_drawelements( ctx, mode, count, ui_indices ); |
} |
else if (ctx->Array.LockCount) { |
/* Are the arrays already locked? If so we currently have to look |
* at the whole locked range. |
*/ |
if (start >= ctx->Array.LockFirst && end <= ctx->Array.LockCount) |
_tnl_draw_range_elements( ctx, mode, |
ctx->Array.LockFirst, |
ctx->Array.LockCount, |
count, ui_indices ); |
else { |
/* The spec says referencing elements outside the locked |
* range is undefined. I'm going to make it a noop this time |
* round, maybe come up with something beter before 3.6. |
* |
* May be able to get away with just setting LockCount==0, |
* though this raises the problems of dependent state. May |
* have to call glUnlockArrays() directly? |
* |
* Or scan the list and replace bad indices? |
*/ |
_mesa_problem( ctx, |
"DrawRangeElements references " |
"elements outside locked range."); |
} |
} |
else if (end + 1 - start < ctx->Const.MaxArrayLockSize) { |
/* The arrays aren't locked but we can still fit them inside a |
* single vertexbuffer. |
*/ |
_tnl_draw_range_elements( ctx, mode, start, end + 1, count, ui_indices ); |
} else { |
/* Range is too big to optimize: |
*/ |
fallback_drawelements( ctx, mode, count, ui_indices ); |
} |
} |
/** |
* Called via the GL API dispatcher. |
*/ |
void |
_tnl_DrawElements(GLenum mode, GLsizei count, GLenum type, |
const GLvoid *indices) |
{ |
GET_CURRENT_CONTEXT(ctx); |
GLuint *ui_indices; |
if (MESA_VERBOSE & VERBOSE_API) |
_mesa_debug(NULL, "_tnl_DrawElements %d\n", count); |
/* Check arguments, etc. |
*/ |
if (!_mesa_validate_DrawElements( ctx, mode, count, type, indices )) |
return; |
ui_indices = (GLuint *)_ac_import_elements( ctx, GL_UNSIGNED_INT, |
count, type, indices ); |
if (ctx->CompileFlag) { |
/* Can't do anything when compiling: |
*/ |
fallback_drawelements( ctx, mode, count, ui_indices ); |
} |
else if (ctx->Array.LockCount) { |
_tnl_draw_range_elements( ctx, mode, |
ctx->Array.LockFirst, |
ctx->Array.LockCount, |
count, ui_indices ); |
} |
else { |
/* Scan the index list and see if we can use the locked path anyway. |
*/ |
GLuint max_elt = 0; |
GLint i; |
for (i = 0 ; i < count ; i++) |
if (ui_indices[i] > max_elt) |
max_elt = ui_indices[i]; |
if (max_elt < ctx->Const.MaxArrayLockSize && /* can we use it? */ |
max_elt < (GLuint) count) /* do we want to use it? */ |
_tnl_draw_range_elements( ctx, mode, 0, max_elt+1, count, ui_indices ); |
else |
fallback_drawelements( ctx, mode, count, ui_indices ); |
} |
} |
/** |
* Initialize context's vertex array fields. Called during T 'n L context |
* creation. |
*/ |
void _tnl_array_init( GLcontext *ctx ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
struct vertex_arrays *tmp = &tnl->array_inputs; |
GLvertexformat *vfmt = &(TNL_CONTEXT(ctx)->vtxfmt); |
GLuint i; |
vfmt->DrawArrays = _tnl_DrawArrays; |
vfmt->DrawElements = _tnl_DrawElements; |
vfmt->DrawRangeElements = _tnl_DrawRangeElements; |
/* Setup vector pointers that will be used to bind arrays to VB's. |
*/ |
_mesa_vector4f_init( &tmp->Obj, 0, 0 ); |
_mesa_vector4f_init( &tmp->Normal, 0, 0 ); |
_mesa_vector4f_init( &tmp->FogCoord, 0, 0 ); |
_mesa_vector1ui_init( &tmp->Index, 0, 0 ); |
_mesa_vector1ub_init( &tmp->EdgeFlag, 0, 0 ); |
for (i = 0; i < ctx->Const.MaxTextureUnits; i++) |
_mesa_vector4f_init( &tmp->TexCoord[i], 0, 0); |
tnl->tmp_primitive = (GLuint *)MALLOC(sizeof(GLuint)*tnl->vb.Size); |
tnl->tmp_primitive_length = (GLuint *)MALLOC(sizeof(GLuint)*tnl->vb.Size); |
} |
/** |
* Destroy the context's vertex array stuff. |
* Called during T 'n L context destruction. |
*/ |
void _tnl_array_destroy( GLcontext *ctx ) |
{ |
TNLcontext *tnl = TNL_CONTEXT(ctx); |
if (tnl->tmp_primitive_length) FREE(tnl->tmp_primitive_length); |
if (tnl->tmp_primitive) FREE(tnl->tmp_primitive); |
} |
/shark/trunk/ports/mesa/src/tnl/t_pipeline.h |
---|
0,0 → 1,76 |
/* $Id: t_pipeline.h,v 1.1 2003-02-28 11:48:07 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 Brian Paul All Rights Reserved. |
* |
* Permission is hereby granted, free of charge, to any person obtaining a |
* copy of this software and associated documentation files (the "Software"), |
* to deal in the Software without restriction, including without limitation |
* the rights to use, copy, modify, merge, publish, distribute, sublicense, |
* and/or sell copies of the Software, and to permit persons to whom the |
* Software is furnished to do so, subject to the following conditions: |
* |
* The above copyright notice and this permission notice shall be included |
* in all copies or substantial portions of the Software. |
* |
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
* BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN |
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN |
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
* |
* Authors: |
* Keith Whitwell <keith@tungstengraphics.com> |
*/ |
#ifndef _T_PIPELINE_H_ |
#define _T_PIPELINE_H_ |
#include "mtypes.h" |
#include "t_context.h" |
extern void _tnl_run_pipeline( GLcontext *ctx ); |
extern void _tnl_validate_pipeline( GLcontext *ctx ); |
extern void _tnl_destroy_pipeline( GLcontext *ctx ); |
extern void _tnl_install_pipeline( GLcontext *ctx, |
const struct gl_pipeline_stage **stages ); |
/* These are implemented in the t_vb_*.c files: |
*/ |
extern const struct gl_pipeline_stage _tnl_vertex_transform_stage; |
extern const struct gl_pipeline_stage _tnl_normal_transform_stage; |
extern const struct gl_pipeline_stage _tnl_lighting_stage; |
extern const struct gl_pipeline_stage _tnl_fog_coordinate_stage; |
extern const struct gl_pipeline_stage _tnl_texgen_stage; |
extern const struct gl_pipeline_stage _tnl_texture_transform_stage; |
extern const struct gl_pipeline_stage _tnl_point_attenuation_stage; |
extern const struct gl_pipeline_stage _tnl_vertex_program_stage; |
extern const struct gl_pipeline_stage _tnl_render_stage; |
/* Shorthand to plug in the default pipeline: |
*/ |
extern const struct gl_pipeline_stage *_tnl_default_pipeline[]; |
/* Convenience routines provided by t_vb_render.c: |
*/ |
extern render_func _tnl_render_tab_elts[]; |
extern render_func _tnl_render_tab_verts[]; |
extern void _tnl_RenderClippedPolygon( GLcontext *ctx, |
const GLuint *elts, GLuint n ); |
extern void _tnl_RenderClippedLine( GLcontext *ctx, GLuint ii, GLuint jj ); |
#endif |
/shark/trunk/ports/mesa/src/makefile |
---|
0,0 → 1,59 |
# The Frame Buffer Device |
ifndef BASE |
BASE=../../.. |
endif |
include $(BASE)/config/config.mk |
LIBRARY = osmesa |
# C_OPT += -DUSE_MMX_ASM |
# ASM_OPT += -DUSE_MMX_ASM |
OBJS_PATH = $(BASE)/drivers/mesa/src/ |
OSMESA = accum.o api_arrayelt.o api_eval.o api_loopback.o api_noop.o api_validate.o\ |
attrib.o blend.o buffers.o clip.o colortab.o context.o convolve.o\ |
debug.o depth.o dispatch.o dlist.o drawpix.o enable.o enums.o eval.o\ |
extensions.o feedback.o fog.o get.o glapi.o glthread.o hash.o hint.o\ |
histogram.o image.o imports.o light.o lines.o matrix.o mmath.o pixel.o\ |
points.o polygon.o rastpos.o state.o stencil.o texcompress.o texformat.o\ |
teximage.o texobj.o texstate.o texstore.o texutil.o varray.o vpexec.o\ |
vpparse.o vpstate.o vtxfmt.o ./osmesa/osmesa.o ./array_cache/ac_context.o\ |
./array_cache/ac_import.o ./swrast/s_aaline.o ./swrast/s_aatriangle.o\ |
./swrast/s_accum.o ./swrast/s_alphabuf.o ./swrast/s_alpha.o ./swrast/s_bitmap.o\ |
./swrast/s_blend.o ./swrast/s_buffers.o ./swrast/s_context.o ./swrast/s_copypix.o\ |
./swrast/s_depth.o ./swrast/s_drawpix.o ./swrast/s_feedback.o ./swrast/s_fog.o\ |
./swrast/s_histogram.o ./swrast/s_imaging.o ./swrast/s_lines.o ./swrast/s_logic.o\ |
./swrast/s_masking.o ./swrast/s_pixeltex.o ./swrast/s_points.o ./swrast/s_readpix.o\ |
./swrast/s_span.o ./swrast/s_stencil.o ./swrast/s_texstore.o ./swrast/s_texture.o\ |
./swrast/s_triangle.o ./swrast/s_zoom.o ./swrast_setup/ss_context.o\ |
./swrast_setup/ss_triangle.o ./swrast_setup/ss_vb.o ./tnl/t_array_api.o\ |
./tnl/t_array_import.o ./tnl/t_context.o ./tnl/t_eval_api.o ./tnl/t_imm_alloc.o\ |
./tnl/t_imm_api.o ./tnl/t_imm_debug.o ./tnl/t_imm_dlist.o ./tnl/t_imm_elt.o\ |
./tnl/t_imm_eval.o ./tnl/t_imm_exec.o ./tnl/t_imm_fixup.o ./tnl/t_pipeline.o\ |
./tnl/t_vb_fog.o ./tnl/t_vb_light.o\ |
./tnl/t_vb_normals.o ./tnl/t_vb_points.o ./tnl/t_vb_program.o ./tnl/t_vb_render.o\ |
./tnl/t_vb_texgen.o ./tnl/t_vb_texmat.o ./tnl/t_vb_vertex.o\ |
./math/m_debug_clip.o ./math/m_debug_norm.o\ |
./math/m_debug_xform.o ./math/m_eval.o ./math/m_matrix.o ./math/m_translate.o\ |
./math/m_vector.o ./math/m_xform.o\ |
./X86/common_x86_asm.o ./X86/common_x86.o ./X86/gen_matypes.o ./X86/glapi_x86.o\ |
./X86/mmx_blend.o ./X86/x86.o ./X86/x86_cliptest.o ./X86/x86_xform2.o\ |
./X86/x86_xform3.o ./X86/x86_xform4.o |
OBJS = $(OSMESA) |
C_OPT += -I../../../drivers/linuxc24/include -I../include -I. -I.. -D__KERNEL__ -D__i368__ \ |
-ffast-math -fexpensive-optimizations -fstrict-aliasing -fPIC\ |
-malign-loops=2 -malign-jumps=2 -malign-functions=2 -D_REENTRANT\ |
-DUSE_X86_ASM -DUSE_MMX_ASM |
ASM_OPT += -I../../../drivers/linuxc24/include -I../include -I. -I.. -D__KERNEL__ -D__i368__ \ |
-ffast-math -fexpensive-optimizations -fstrict-aliasing -fPIC -O\ |
-malign-loops=2 -malign-jumps=2 -malign-functions=2 -D_REENTRANT\ |
-DUSE_X86_ASM -DUSE_MMX_ASM |
include $(BASE)/config/lib.mk |
/shark/trunk/ports/mesa/src/math/mathmod.h |
---|
0,0 → 1,32 |
/* $Id: mathmod.h,v 1.1 2003-02-28 11:48:06 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 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. |
*/ |
#ifndef _MESA_MATH_H_ |
#define _MESA_MATH_H_ |
extern void _math_init( void ); |
#endif |
/shark/trunk/ports/mesa/src/math/m_eval.c |
---|
0,0 → 1,462 |
/* $Id: m_eval.c,v 1.1 2003-02-28 11:48:05 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 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. |
*/ |
/* |
* eval.c was written by |
* Bernd Barsuhn (bdbarsuh@cip.informatik.uni-erlangen.de) and |
* Volker Weiss (vrweiss@cip.informatik.uni-erlangen.de). |
* |
* My original implementation of evaluators was simplistic and didn't |
* compute surface normal vectors properly. Bernd and Volker applied |
* used more sophisticated methods to get better results. |
* |
* Thanks guys! |
*/ |
#include "glheader.h" |
#include "config.h" |
#include "m_eval.h" |
static GLfloat inv_tab[MAX_EVAL_ORDER]; |
/* |
* Horner scheme for Bezier curves |
* |
* Bezier curves can be computed via a Horner scheme. |
* Horner is numerically less stable than the de Casteljau |
* algorithm, but it is faster. For curves of degree n |
* the complexity of Horner is O(n) and de Casteljau is O(n^2). |
* Since stability is not important for displaying curve |
* points I decided to use the Horner scheme. |
* |
* A cubic Bezier curve with control points b0, b1, b2, b3 can be |
* written as |
* |
* (([3] [3] ) [3] ) [3] |
* c(t) = (([0]*s*b0 + [1]*t*b1)*s + [2]*t^2*b2)*s + [3]*t^2*b3 |
* |
* [n] |
* where s=1-t and the binomial coefficients [i]. These can |
* be computed iteratively using the identity: |
* |
* [n] [n ] [n] |
* [i] = (n-i+1)/i * [i-1] and [0] = 1 |
*/ |
void |
_math_horner_bezier_curve(const GLfloat * cp, GLfloat * out, GLfloat t, |
GLuint dim, GLuint order) |
{ |
GLfloat s, powert, bincoeff; |
GLuint i, k; |
if (order >= 2) { |
bincoeff = (GLfloat) (order - 1); |
s = 1.0F - t; |
for (k = 0; k < dim; k++) |
out[k] = s * cp[k] + bincoeff * t * cp[dim + k]; |
for (i = 2, cp += 2 * dim, powert = t * t; i < order; |
i++, powert *= t, cp += dim) { |
bincoeff *= (GLfloat) (order - i); |
bincoeff *= inv_tab[i]; |
for (k = 0; k < dim; k++) |
out[k] = s * out[k] + bincoeff * powert * cp[k]; |
} |
} |
else { /* order=1 -> constant curve */ |
for (k = 0; k < dim; k++) |
out[k] = cp[k]; |
} |
} |
/* |
* Tensor product Bezier surfaces |
* |
* Again the Horner scheme is used to compute a point on a |
* TP Bezier surface. First a control polygon for a curve |
* on the surface in one parameter direction is computed, |
* then the point on the curve for the other parameter |
* direction is evaluated. |
* |
* To store the curve control polygon additional storage |
* for max(uorder,vorder) points is needed in the |
* control net cn. |
*/ |
void |
_math_horner_bezier_surf(GLfloat * cn, GLfloat * out, GLfloat u, GLfloat v, |
GLuint dim, GLuint uorder, GLuint vorder) |
{ |
GLfloat *cp = cn + uorder * vorder * dim; |
GLuint i, uinc = vorder * dim; |
if (vorder > uorder) { |
if (uorder >= 2) { |
GLfloat s, poweru, bincoeff; |
GLuint j, k; |
/* Compute the control polygon for the surface-curve in u-direction */ |
for (j = 0; j < vorder; j++) { |
GLfloat *ucp = &cn[j * dim]; |
/* Each control point is the point for parameter u on a */ |
/* curve defined by the control polygons in u-direction */ |
bincoeff = (GLfloat) (uorder - 1); |
s = 1.0F - u; |
for (k = 0; k < dim; k++) |
cp[j * dim + k] = s * ucp[k] + bincoeff * u * ucp[uinc + k]; |
for (i = 2, ucp += 2 * uinc, poweru = u * u; i < uorder; |
i++, poweru *= u, ucp += uinc) { |
bincoeff *= (GLfloat) (uorder - i); |
bincoeff *= inv_tab[i]; |
for (k = 0; k < dim; k++) |
cp[j * dim + k] = |
s * cp[j * dim + k] + bincoeff * poweru * ucp[k]; |
} |
} |
/* Evaluate curve point in v */ |
_math_horner_bezier_curve(cp, out, v, dim, vorder); |
} |
else /* uorder=1 -> cn defines a curve in v */ |
_math_horner_bezier_curve(cn, out, v, dim, vorder); |
} |
else { /* vorder <= uorder */ |
if (vorder > 1) { |
GLuint i; |
/* Compute the control polygon for the surface-curve in u-direction */ |
for (i = 0; i < uorder; i++, cn += uinc) { |
/* For constant i all cn[i][j] (j=0..vorder) are located */ |
/* on consecutive memory locations, so we can use */ |
/* horner_bezier_curve to compute the control points */ |
_math_horner_bezier_curve(cn, &cp[i * dim], v, dim, vorder); |
} |
/* Evaluate curve point in u */ |
_math_horner_bezier_curve(cp, out, u, dim, uorder); |
} |
else /* vorder=1 -> cn defines a curve in u */ |
_math_horner_bezier_curve(cn, out, u, dim, uorder); |
} |
} |
/* |
* The direct de Casteljau algorithm is used when a point on the |
* surface and the tangent directions spanning the tangent plane |
* should be computed (this is needed to compute normals to the |
* surface). In this case the de Casteljau algorithm approach is |
* nicer because a point and the partial derivatives can be computed |
* at the same time. To get the correct tangent length du and dv |
* must be multiplied with the (u2-u1)/uorder-1 and (v2-v1)/vorder-1. |
* Since only the directions are needed, this scaling step is omitted. |
* |
* De Casteljau needs additional storage for uorder*vorder |
* values in the control net cn. |
*/ |
void |
_math_de_casteljau_surf(GLfloat * cn, GLfloat * out, GLfloat * du, |
GLfloat * dv, GLfloat u, GLfloat v, GLuint dim, |
GLuint uorder, GLuint vorder) |
{ |
GLfloat *dcn = cn + uorder * vorder * dim; |
GLfloat us = 1.0F - u, vs = 1.0F - v; |
GLuint h, i, j, k; |
GLuint minorder = uorder < vorder ? uorder : vorder; |
GLuint uinc = vorder * dim; |
GLuint dcuinc = vorder; |
/* Each component is evaluated separately to save buffer space */ |
/* This does not drasticaly decrease the performance of the */ |
/* algorithm. If additional storage for (uorder-1)*(vorder-1) */ |
/* points would be available, the components could be accessed */ |
/* in the innermost loop which could lead to less cache misses. */ |
#define CN(I,J,K) cn[(I)*uinc+(J)*dim+(K)] |
#define DCN(I, J) dcn[(I)*dcuinc+(J)] |
if (minorder < 3) { |
if (uorder == vorder) { |
for (k = 0; k < dim; k++) { |
/* Derivative direction in u */ |
du[k] = vs * (CN(1, 0, k) - CN(0, 0, k)) + |
v * (CN(1, 1, k) - CN(0, 1, k)); |
/* Derivative direction in v */ |
dv[k] = us * (CN(0, 1, k) - CN(0, 0, k)) + |
u * (CN(1, 1, k) - CN(1, 0, k)); |
/* bilinear de Casteljau step */ |
out[k] = us * (vs * CN(0, 0, k) + v * CN(0, 1, k)) + |
u * (vs * CN(1, 0, k) + v * CN(1, 1, k)); |
} |
} |
else if (minorder == uorder) { |
for (k = 0; k < dim; k++) { |
/* bilinear de Casteljau step */ |
DCN(1, 0) = CN(1, 0, k) - CN(0, 0, k); |
DCN(0, 0) = us * CN(0, 0, k) + u * CN(1, 0, k); |
for (j = 0; j < vorder - 1; j++) { |
/* for the derivative in u */ |
DCN(1, j + 1) = CN(1, j + 1, k) - CN(0, j + 1, k); |
DCN(1, j) = vs * DCN(1, j) + v * DCN(1, j + 1); |
/* for the `point' */ |
DCN(0, j + 1) = us * CN(0, j + 1, k) + u * CN(1, j + 1, k); |
DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1); |
} |
/* remaining linear de Casteljau steps until the second last step */ |
for (h = minorder; h < vorder - 1; h++) |
for (j = 0; j < vorder - h; j++) { |
/* for the derivative in u */ |
DCN(1, j) = vs * DCN(1, j) + v * DCN(1, j + 1); |
/* for the `point' */ |
DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1); |
} |
/* derivative direction in v */ |
dv[k] = DCN(0, 1) - DCN(0, 0); |
/* derivative direction in u */ |
du[k] = vs * DCN(1, 0) + v * DCN(1, 1); |
/* last linear de Casteljau step */ |
out[k] = vs * DCN(0, 0) + v * DCN(0, 1); |
} |
} |
else { /* minorder == vorder */ |
for (k = 0; k < dim; k++) { |
/* bilinear de Casteljau step */ |
DCN(0, 1) = CN(0, 1, k) - CN(0, 0, k); |
DCN(0, 0) = vs * CN(0, 0, k) + v * CN(0, 1, k); |
for (i = 0; i < uorder - 1; i++) { |
/* for the derivative in v */ |
DCN(i + 1, 1) = CN(i + 1, 1, k) - CN(i + 1, 0, k); |
DCN(i, 1) = us * DCN(i, 1) + u * DCN(i + 1, 1); |
/* for the `point' */ |
DCN(i + 1, 0) = vs * CN(i + 1, 0, k) + v * CN(i + 1, 1, k); |
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0); |
} |
/* remaining linear de Casteljau steps until the second last step */ |
for (h = minorder; h < uorder - 1; h++) |
for (i = 0; i < uorder - h; i++) { |
/* for the derivative in v */ |
DCN(i, 1) = us * DCN(i, 1) + u * DCN(i + 1, 1); |
/* for the `point' */ |
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0); |
} |
/* derivative direction in u */ |
du[k] = DCN(1, 0) - DCN(0, 0); |
/* derivative direction in v */ |
dv[k] = us * DCN(0, 1) + u * DCN(1, 1); |
/* last linear de Casteljau step */ |
out[k] = us * DCN(0, 0) + u * DCN(1, 0); |
} |
} |
} |
else if (uorder == vorder) { |
for (k = 0; k < dim; k++) { |
/* first bilinear de Casteljau step */ |
for (i = 0; i < uorder - 1; i++) { |
DCN(i, 0) = us * CN(i, 0, k) + u * CN(i + 1, 0, k); |
for (j = 0; j < vorder - 1; j++) { |
DCN(i, j + 1) = us * CN(i, j + 1, k) + u * CN(i + 1, j + 1, k); |
DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1); |
} |
} |
/* remaining bilinear de Casteljau steps until the second last step */ |
for (h = 2; h < minorder - 1; h++) |
for (i = 0; i < uorder - h; i++) { |
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0); |
for (j = 0; j < vorder - h; j++) { |
DCN(i, j + 1) = us * DCN(i, j + 1) + u * DCN(i + 1, j + 1); |
DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1); |
} |
} |
/* derivative direction in u */ |
du[k] = vs * (DCN(1, 0) - DCN(0, 0)) + v * (DCN(1, 1) - DCN(0, 1)); |
/* derivative direction in v */ |
dv[k] = us * (DCN(0, 1) - DCN(0, 0)) + u * (DCN(1, 1) - DCN(1, 0)); |
/* last bilinear de Casteljau step */ |
out[k] = us * (vs * DCN(0, 0) + v * DCN(0, 1)) + |
u * (vs * DCN(1, 0) + v * DCN(1, 1)); |
} |
} |
else if (minorder == uorder) { |
for (k = 0; k < dim; k++) { |
/* first bilinear de Casteljau step */ |
for (i = 0; i < uorder - 1; i++) { |
DCN(i, 0) = us * CN(i, 0, k) + u * CN(i + 1, 0, k); |
for (j = 0; j < vorder - 1; j++) { |
DCN(i, j + 1) = us * CN(i, j + 1, k) + u * CN(i + 1, j + 1, k); |
DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1); |
} |
} |
/* remaining bilinear de Casteljau steps until the second last step */ |
for (h = 2; h < minorder - 1; h++) |
for (i = 0; i < uorder - h; i++) { |
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0); |
for (j = 0; j < vorder - h; j++) { |
DCN(i, j + 1) = us * DCN(i, j + 1) + u * DCN(i + 1, j + 1); |
DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1); |
} |
} |
/* last bilinear de Casteljau step */ |
DCN(2, 0) = DCN(1, 0) - DCN(0, 0); |
DCN(0, 0) = us * DCN(0, 0) + u * DCN(1, 0); |
for (j = 0; j < vorder - 1; j++) { |
/* for the derivative in u */ |
DCN(2, j + 1) = DCN(1, j + 1) - DCN(0, j + 1); |
DCN(2, j) = vs * DCN(2, j) + v * DCN(2, j + 1); |
/* for the `point' */ |
DCN(0, j + 1) = us * DCN(0, j + 1) + u * DCN(1, j + 1); |
DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1); |
} |
/* remaining linear de Casteljau steps until the second last step */ |
for (h = minorder; h < vorder - 1; h++) |
for (j = 0; j < vorder - h; j++) { |
/* for the derivative in u */ |
DCN(2, j) = vs * DCN(2, j) + v * DCN(2, j + 1); |
/* for the `point' */ |
DCN(0, j) = vs * DCN(0, j) + v * DCN(0, j + 1); |
} |
/* derivative direction in v */ |
dv[k] = DCN(0, 1) - DCN(0, 0); |
/* derivative direction in u */ |
du[k] = vs * DCN(2, 0) + v * DCN(2, 1); |
/* last linear de Casteljau step */ |
out[k] = vs * DCN(0, 0) + v * DCN(0, 1); |
} |
} |
else { /* minorder == vorder */ |
for (k = 0; k < dim; k++) { |
/* first bilinear de Casteljau step */ |
for (i = 0; i < uorder - 1; i++) { |
DCN(i, 0) = us * CN(i, 0, k) + u * CN(i + 1, 0, k); |
for (j = 0; j < vorder - 1; j++) { |
DCN(i, j + 1) = us * CN(i, j + 1, k) + u * CN(i + 1, j + 1, k); |
DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1); |
} |
} |
/* remaining bilinear de Casteljau steps until the second last step */ |
for (h = 2; h < minorder - 1; h++) |
for (i = 0; i < uorder - h; i++) { |
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0); |
for (j = 0; j < vorder - h; j++) { |
DCN(i, j + 1) = us * DCN(i, j + 1) + u * DCN(i + 1, j + 1); |
DCN(i, j) = vs * DCN(i, j) + v * DCN(i, j + 1); |
} |
} |
/* last bilinear de Casteljau step */ |
DCN(0, 2) = DCN(0, 1) - DCN(0, 0); |
DCN(0, 0) = vs * DCN(0, 0) + v * DCN(0, 1); |
for (i = 0; i < uorder - 1; i++) { |
/* for the derivative in v */ |
DCN(i + 1, 2) = DCN(i + 1, 1) - DCN(i + 1, 0); |
DCN(i, 2) = us * DCN(i, 2) + u * DCN(i + 1, 2); |
/* for the `point' */ |
DCN(i + 1, 0) = vs * DCN(i + 1, 0) + v * DCN(i + 1, 1); |
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0); |
} |
/* remaining linear de Casteljau steps until the second last step */ |
for (h = minorder; h < uorder - 1; h++) |
for (i = 0; i < uorder - h; i++) { |
/* for the derivative in v */ |
DCN(i, 2) = us * DCN(i, 2) + u * DCN(i + 1, 2); |
/* for the `point' */ |
DCN(i, 0) = us * DCN(i, 0) + u * DCN(i + 1, 0); |
} |
/* derivative direction in u */ |
du[k] = DCN(1, 0) - DCN(0, 0); |
/* derivative direction in v */ |
dv[k] = us * DCN(0, 2) + u * DCN(1, 2); |
/* last linear de Casteljau step */ |
out[k] = us * DCN(0, 0) + u * DCN(1, 0); |
} |
} |
#undef DCN |
#undef CN |
} |
/* |
* Do one-time initialization for evaluators. |
*/ |
void |
_math_init_eval(void) |
{ |
GLuint i; |
/* KW: precompute 1/x for useful x. |
*/ |
for (i = 1; i < MAX_EVAL_ORDER; i++) |
inv_tab[i] = 1.0F / i; |
} |
/shark/trunk/ports/mesa/src/math/m_debug_util.h |
---|
0,0 → 1,280 |
/* $Id: m_debug_util.h,v 1.1 2003-02-28 11:48:05 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 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: |
* Gareth Hughes |
*/ |
#ifndef __M_DEBUG_UTIL_H__ |
#define __M_DEBUG_UTIL_H__ |
#ifdef DEBUG /* This code only used for debugging */ |
/* Comment this out to deactivate the cycle counter. |
* NOTE: it works only on CPUs which know the 'rdtsc' command (586 or higher) |
* (hope, you don't try to debug Mesa on a 386 ;) |
*/ |
#if defined(__GNUC__) && \ |
((defined(__i386__) && defined(USE_X86_ASM)) || \ |
(defined(__sparc__) && defined(USE_SPARC_ASM))) |
#define RUN_DEBUG_BENCHMARK |
#endif |
#define TEST_COUNT 128 /* size of the tested vector array */ |
#define REQUIRED_PRECISION 10 /* allow 4 bits to miss */ |
#define MAX_PRECISION 24 /* max. precision possible */ |
#ifdef RUN_DEBUG_BENCHMARK |
/* Overhead of profiling counter in cycles. Automatically adjusted to |
* your machine at run time - counter initialization should give very |
* consistent results. |
*/ |
extern long counter_overhead; |
/* This is the value of the environment variable MESA_PROFILE, and is |
* used to determine if we should benchmark the functions as well as |
* verify their correctness. |
*/ |
extern char *mesa_profile; |
/* Modify the the number of tests if you like. |
* We take the minimum of all results, because every error should be |
* positive (time used by other processes, task switches etc). |
* It is assumed that all calculations are done in the cache. |
*/ |
#if defined(__i386__) |
#if 1 /* PPro, PII, PIII version */ |
/* Profiling on the P6 architecture requires a little more work, due to |
* the internal out-of-order execution. We must perform a serializing |
* 'cpuid' instruction before and after the 'rdtsc' instructions to make |
* sure no other uops are executed when we sample the timestamp counter. |
*/ |
#define INIT_COUNTER() \ |
do { \ |
int cycle_i; \ |
counter_overhead = LONG_MAX; \ |
for ( cycle_i = 0 ; cycle_i < 8 ; cycle_i++ ) { \ |
long cycle_tmp1 = 0, cycle_tmp2 = 0; \ |
__asm__ __volatile__ ( "push %%ebx \n" \ |
"xor %%eax, %%eax \n" \ |
"cpuid \n" \ |
"rdtsc \n" \ |
"mov %%eax, %0 \n" \ |
"xor %%eax, %%eax \n" \ |
"cpuid \n" \ |
"pop %%ebx \n" \ |
"push %%ebx \n" \ |
"xor %%eax, %%eax \n" \ |
"cpuid \n" \ |
"rdtsc \n" \ |
"mov %%eax, %1 \n" \ |
"xor %%eax, %%eax \n" \ |
"cpuid \n" \ |
"pop %%ebx \n" \ |
: "=m" (cycle_tmp1), "=m" (cycle_tmp2) \ |
: : "eax", "ecx", "edx" ); \ |
if ( counter_overhead > (cycle_tmp2 - cycle_tmp1) ) { \ |
counter_overhead = cycle_tmp2 - cycle_tmp1; \ |
} \ |
} \ |
} while (0) |
#define BEGIN_RACE(x) \ |
x = LONG_MAX; \ |
for ( cycle_i = 0 ; cycle_i < 10 ; cycle_i++ ) { \ |
long cycle_tmp1 = 0, cycle_tmp2 = 0; \ |
__asm__ __volatile__ ( "push %%ebx \n" \ |
"xor %%eax, %%eax \n" \ |
"cpuid \n" \ |
"rdtsc \n" \ |
"mov %%eax, %0 \n" \ |
"xor %%eax, %%eax \n" \ |
"cpuid \n" \ |
"pop %%ebx \n" \ |
: "=m" (cycle_tmp1) \ |
: : "eax", "ecx", "edx" ); |
#define END_RACE(x) \ |
__asm__ __volatile__ ( "push %%ebx \n" \ |
"xor %%eax, %%eax \n" \ |
"cpuid \n" \ |
"rdtsc \n" \ |
"mov %%eax, %0 \n" \ |
"xor %%eax, %%eax \n" \ |
"cpuid \n" \ |
"pop %%ebx \n" \ |
: "=m" (cycle_tmp2) \ |
: : "eax", "ecx", "edx" ); \ |
if ( x > (cycle_tmp2 - cycle_tmp1) ) { \ |
x = cycle_tmp2 - cycle_tmp1; \ |
} \ |
} \ |
x -= counter_overhead; |
#else /* PPlain, PMMX version */ |
/* To ensure accurate results, we stall the pipelines with the |
* non-pairable 'cdq' instruction. This ensures all the code being |
* profiled is complete when the 'rdtsc' instruction executes. |
*/ |
#define INIT_COUNTER(x) \ |
do { \ |
int cycle_i; \ |
x = LONG_MAX; \ |
for ( cycle_i = 0 ; cycle_i < 32 ; cycle_i++ ) { \ |
long cycle_tmp1, cycle_tmp2, dummy; \ |
__asm__ ( "mov %%eax, %0" : "=a" (cycle_tmp1) ); \ |
__asm__ ( "mov %%eax, %0" : "=a" (cycle_tmp2) ); \ |
__asm__ ( "cdq" ); \ |
__asm__ ( "cdq" ); \ |
__asm__ ( "rdtsc" : "=a" (cycle_tmp1), "=d" (dummy) ); \ |
__asm__ ( "cdq" ); \ |
__asm__ ( "cdq" ); \ |
__asm__ ( "rdtsc" : "=a" (cycle_tmp2), "=d" (dummy) ); \ |
if ( x > (cycle_tmp2 - cycle_tmp1) ) \ |
x = cycle_tmp2 - cycle_tmp1; \ |
} \ |
} while (0) |
#define BEGIN_RACE(x) \ |
x = LONG_MAX; \ |
for ( cycle_i = 0 ; cycle_i < 16 ; cycle_i++ ) { \ |
long cycle_tmp1, cycle_tmp2, dummy; \ |
__asm__ ( "mov %%eax, %0" : "=a" (cycle_tmp1) ); \ |
__asm__ ( "mov %%eax, %0" : "=a" (cycle_tmp2) ); \ |
__asm__ ( "cdq" ); \ |
__asm__ ( "cdq" ); \ |
__asm__ ( "rdtsc" : "=a" (cycle_tmp1), "=d" (dummy) ); |
#define END_RACE(x) \ |
__asm__ ( "cdq" ); \ |
__asm__ ( "cdq" ); \ |
__asm__ ( "rdtsc" : "=a" (cycle_tmp2), "=d" (dummy) ); \ |
if ( x > (cycle_tmp2 - cycle_tmp1) ) \ |
x = cycle_tmp2 - cycle_tmp1; \ |
} \ |
x -= counter_overhead; |
#endif |
#elif defined(__sparc__) |
#define INIT_COUNTER() \ |
do { counter_overhead = 5; } while(0) |
#define BEGIN_RACE(x) \ |
x = LONG_MAX; \ |
for (cycle_i = 0; cycle_i <10; cycle_i++) { \ |
register long cycle_tmp1 asm("l0"); \ |
register long cycle_tmp2 asm("l1"); \ |
/* rd %tick, %l0 */ \ |
__asm__ __volatile__ (".word 0xa1410000" : "=r" (cycle_tmp1)); /* save timestamp */ |
#define END_RACE(x) \ |
/* rd %tick, %l1 */ \ |
__asm__ __volatile__ (".word 0xa3410000" : "=r" (cycle_tmp2)); \ |
if (x > (cycle_tmp2-cycle_tmp1)) x = cycle_tmp2 - cycle_tmp1; \ |
} \ |
x -= counter_overhead; |
#else |
#error Your processor is not supported for RUN_XFORM_BENCHMARK |
#endif |
#else |
#define BEGIN_RACE(x) |
#define END_RACE(x) |
#endif |
/* ============================================================= |
* Helper functions |
*/ |
static GLfloat rnd( void ) |
{ |
GLfloat f = (GLfloat)rand() / (GLfloat)RAND_MAX; |
GLfloat gran = (GLfloat)(1 << 13); |
f = (GLfloat)(GLint)(f * gran) / gran; |
return f * 2.0 - 1.0; |
} |
static int significand_match( GLfloat a, GLfloat b ) |
{ |
GLfloat d = a - b; |
int a_ex, b_ex, d_ex; |
if ( d == 0.0F ) { |
return MAX_PRECISION; /* Exact match */ |
} |
if ( a == 0.0F || b == 0.0F ) { |
/* It would probably be better to check if the |
* non-zero number is denormalized and return |
* the index of the highest set bit here. |
*/ |
return 0; |
} |
frexp( a, &a_ex ); |
frexp( b, &b_ex ); |
frexp( d, &d_ex ); |
if ( a_ex < b_ex ) { |
return a_ex - d_ex; |
} else { |
return b_ex - d_ex; |
} |
} |
enum { NIL = 0, ONE = 1, NEG = -1, VAR = 2 }; |
/* Ensure our arrays are correctly aligned. |
*/ |
#if defined(__GNUC__) |
# define ALIGN16 __attribute__ ((aligned (16))) |
#elif defined(__MSC__) |
# define ALIGN16 __declspec(align(16)) /* GH: Does this work? */ |
#else |
# warning "ALIGN16 will not 16-byte align!\n" |
# define ALIGN16 |
#endif |
#endif /* DEBUG */ |
#endif /* __M_DEBUG_UTIL_H__ */ |
/shark/trunk/ports/mesa/src/math/m_debug.h |
---|
0,0 → 1,43 |
/* $Id: m_debug.h,v 1.1 2003-02-28 11:48:04 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 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: |
* Gareth Hughes |
*/ |
#ifndef __M_DEBUG_H__ |
#define __M_DEBUG_H__ |
extern void _math_test_all_transform_functions( char *description ); |
extern void _math_test_all_normal_transform_functions( char *description ); |
extern void _math_test_all_cliptest_functions( char *description ); |
/* Deprecated? |
*/ |
extern void _math_test_all_vertex_functions( char *description ); |
extern char *mesa_profile; |
#endif |
/shark/trunk/ports/mesa/src/math/m_xform.c |
---|
0,0 → 1,222 |
/* $Id: m_xform.c,v 1.1 2003-02-28 11:48:05 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 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. |
*/ |
/* |
* Matrix/vertex/vector transformation stuff |
* |
* |
* NOTES: |
* 1. 4x4 transformation matrices are stored in memory in column major order. |
* 2. Points/vertices are to be thought of as column vectors. |
* 3. Transformation of a point p by a matrix M is: p' = M * p |
*/ |
#include "glheader.h" |
#include "macros.h" |
#include "mmath.h" |
#include "m_eval.h" |
#include "m_matrix.h" |
#include "m_translate.h" |
#include "m_xform.h" |
#include "mathmod.h" |
#ifdef DEBUG |
#include "m_debug.h" |
#endif |
#ifdef USE_X86_ASM |
#include "X86/common_x86_asm.h" |
#endif |
#ifdef USE_SPARC_ASM |
#include "SPARC/sparc.h" |
#endif |
clip_func _mesa_clip_tab[5]; |
clip_func _mesa_clip_np_tab[5]; |
dotprod_func _mesa_dotprod_tab[5]; |
vec_copy_func _mesa_copy_tab[0x10]; |
normal_func _mesa_normal_tab[0xf]; |
transform_func *_mesa_transform_tab[5]; |
/* Raw data format used for: |
* - Object-to-eye transform prior to culling, although this too |
* could be culled under some circumstances. |
* - Eye-to-clip transform (via the function above). |
* - Cliptesting |
* - And everything else too, if culling happens to be disabled. |
* |
* GH: It's used for everything now, as clipping/culling is done |
* elsewhere (most often by the driver itself). |
*/ |
#define TAG(x) x |
#define TAG2(x,y) x##y |
#define STRIDE_LOOP for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) ) |
#define LOOP for ( i = 0 ; i < n ; i++ ) |
#define ARGS |
#include "m_xform_tmp.h" |
#include "m_clip_tmp.h" |
#include "m_norm_tmp.h" |
#include "m_dotprod_tmp.h" |
#include "m_copy_tmp.h" |
#undef TAG |
#undef TAG2 |
#undef LOOP |
#undef ARGS |
GLvector4f *_mesa_project_points( GLvector4f *proj_vec, |
const GLvector4f *clip_vec ) |
{ |
const GLuint stride = clip_vec->stride; |
const GLfloat *from = (GLfloat *)clip_vec->start; |
const GLuint count = clip_vec->count; |
GLfloat (*vProj)[4] = (GLfloat (*)[4])proj_vec->start; |
GLuint i; |
for (i = 0 ; i < count ; i++, STRIDE_F(from, stride)) |
{ |
GLfloat oow = 1.0F / from[3]; |
vProj[i][3] = oow; |
vProj[i][0] = from[0] * oow; |
vProj[i][1] = from[1] * oow; |
vProj[i][2] = from[2] * oow; |
} |
proj_vec->flags |= VEC_SIZE_4; |
proj_vec->size = 3; |
proj_vec->count = clip_vec->count; |
return proj_vec; |
} |
/* |
* Transform a 4-element row vector (1x4 matrix) by a 4x4 matrix. This |
* function is used for transforming clipping plane equations and spotlight |
* directions. |
* Mathematically, u = v * m. |
* Input: v - input vector |
* m - transformation matrix |
* Output: u - transformed vector |
*/ |
void _mesa_transform_vector( GLfloat u[4], const GLfloat v[4], const GLfloat m[16] ) |
{ |
GLfloat v0=v[0], v1=v[1], v2=v[2], v3=v[3]; |
#define M(row,col) m[row + col*4] |
u[0] = v0 * M(0,0) + v1 * M(1,0) + v2 * M(2,0) + v3 * M(3,0); |
u[1] = v0 * M(0,1) + v1 * M(1,1) + v2 * M(2,1) + v3 * M(3,1); |
u[2] = v0 * M(0,2) + v1 * M(1,2) + v2 * M(2,2) + v3 * M(3,2); |
u[3] = v0 * M(0,3) + v1 * M(1,3) + v2 * M(2,3) + v3 * M(3,3); |
#undef M |
} |
/* Useful for one-off point transformations, as in clipping. |
* Note that because the matrix isn't analysed we do too many |
* multiplies, and that the result is always 4-clean. |
*/ |
void _mesa_transform_point_sz( GLfloat Q[4], const GLfloat M[16], |
const GLfloat P[4], GLuint sz ) |
{ |
if (Q == P) |
return; |
if (sz == 4) |
{ |
Q[0] = M[0] * P[0] + M[4] * P[1] + M[8] * P[2] + M[12] * P[3]; |
Q[1] = M[1] * P[0] + M[5] * P[1] + M[9] * P[2] + M[13] * P[3]; |
Q[2] = M[2] * P[0] + M[6] * P[1] + M[10] * P[2] + M[14] * P[3]; |
Q[3] = M[3] * P[0] + M[7] * P[1] + M[11] * P[2] + M[15] * P[3]; |
} |
else if (sz == 3) |
{ |
Q[0] = M[0] * P[0] + M[4] * P[1] + M[8] * P[2] + M[12]; |
Q[1] = M[1] * P[0] + M[5] * P[1] + M[9] * P[2] + M[13]; |
Q[2] = M[2] * P[0] + M[6] * P[1] + M[10] * P[2] + M[14]; |
Q[3] = M[3] * P[0] + M[7] * P[1] + M[11] * P[2] + M[15]; |
} |
else if (sz == 2) |
{ |
Q[0] = M[0] * P[0] + M[4] * P[1] + M[12]; |
Q[1] = M[1] * P[0] + M[5] * P[1] + M[13]; |
Q[2] = M[2] * P[0] + M[6] * P[1] + M[14]; |
Q[3] = M[3] * P[0] + M[7] * P[1] + M[15]; |
} |
else if (sz == 1) |
{ |
Q[0] = M[0] * P[0] + M[12]; |
Q[1] = M[1] * P[0] + M[13]; |
Q[2] = M[2] * P[0] + M[14]; |
Q[3] = M[3] * P[0] + M[15]; |
} |
} |
/* |
* This is called only once. It initializes several tables with pointers |
* to optimized transformation functions. This is where we can test for |
* AMD 3Dnow! capability, Intel Katmai, etc. and hook in the right code. |
*/ |
void |
_math_init_transformation( void ) |
{ |
init_c_transformations(); |
init_c_norm_transform(); |
init_c_cliptest(); |
init_copy0(); |
init_dotprod(); |
#ifdef DEBUG |
_math_test_all_transform_functions( "default" ); |
_math_test_all_normal_transform_functions( "default" ); |
_math_test_all_cliptest_functions( "default" ); |
#endif |
#ifdef USE_X86_ASM |
_mesa_init_all_x86_transform_asm(); |
#endif |
#ifdef USE_SPARC_ASM |
_mesa_init_all_sparc_transform_asm(); |
#endif |
} |
void |
_math_init( void ) |
{ |
_math_init_transformation(); |
_math_init_translate(); |
_math_init_eval(); |
} |
/shark/trunk/ports/mesa/src/math/m_eval.h |
---|
0,0 → 1,104 |
/* $Id: m_eval.h,v 1.1 2003-02-28 11:48:05 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 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. |
*/ |
#ifndef _M_EVAL_H |
#define _M_EVAL_H |
#include "glheader.h" |
void _math_init_eval( void ); |
/* |
* Horner scheme for Bezier curves |
* |
* Bezier curves can be computed via a Horner scheme. |
* Horner is numerically less stable than the de Casteljau |
* algorithm, but it is faster. For curves of degree n |
* the complexity of Horner is O(n) and de Casteljau is O(n^2). |
* Since stability is not important for displaying curve |
* points I decided to use the Horner scheme. |
* |
* A cubic Bezier curve with control points b0, b1, b2, b3 can be |
* written as |
* |
* (([3] [3] ) [3] ) [3] |
* c(t) = (([0]*s*b0 + [1]*t*b1)*s + [2]*t^2*b2)*s + [3]*t^2*b3 |
* |
* [n] |
* where s=1-t and the binomial coefficients [i]. These can |
* be computed iteratively using the identity: |
* |
* [n] [n ] [n] |
* [i] = (n-i+1)/i * [i-1] and [0] = 1 |
*/ |
void |
_math_horner_bezier_curve(const GLfloat *cp, GLfloat *out, GLfloat t, |
GLuint dim, GLuint order); |
/* |
* Tensor product Bezier surfaces |
* |
* Again the Horner scheme is used to compute a point on a |
* TP Bezier surface. First a control polygon for a curve |
* on the surface in one parameter direction is computed, |
* then the point on the curve for the other parameter |
* direction is evaluated. |
* |
* To store the curve control polygon additional storage |
* for max(uorder,vorder) points is needed in the |
* control net cn. |
*/ |
void |
_math_horner_bezier_surf(GLfloat *cn, GLfloat *out, GLfloat u, GLfloat v, |
GLuint dim, GLuint uorder, GLuint vorder); |
/* |
* The direct de Casteljau algorithm is used when a point on the |
* surface and the tangent directions spanning the tangent plane |
* should be computed (this is needed to compute normals to the |
* surface). In this case the de Casteljau algorithm approach is |
* nicer because a point and the partial derivatives can be computed |
* at the same time. To get the correct tangent length du and dv |
* must be multiplied with the (u2-u1)/uorder-1 and (v2-v1)/vorder-1. |
* Since only the directions are needed, this scaling step is omitted. |
* |
* De Casteljau needs additional storage for uorder*vorder |
* values in the control net cn. |
*/ |
void |
_math_de_casteljau_surf(GLfloat *cn, GLfloat *out, GLfloat *du, GLfloat *dv, |
GLfloat u, GLfloat v, GLuint dim, |
GLuint uorder, GLuint vorder); |
#endif |
/shark/trunk/ports/mesa/src/math/m_translate.c |
---|
0,0 → 1,662 |
/* $Id: m_translate.c,v 1.1 2003-02-28 11:48:05 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. |
*/ |
/* |
* New (3.1) transformation code written by Keith Whitwell. |
*/ |
#include "glheader.h" |
#include "mtypes.h" /* GLchan hack */ |
#include "colormac.h" |
#include "mmath.h" |
#include "m_translate.h" |
typedef void (*trans_1f_func)(GLfloat *to, |
CONST void *ptr, |
GLuint stride, |
GLuint start, |
GLuint n ); |
typedef void (*trans_1ui_func)(GLuint *to, |
CONST void *ptr, |
GLuint stride, |
GLuint start, |
GLuint n ); |
typedef void (*trans_1ub_func)(GLubyte *to, |
CONST void *ptr, |
GLuint stride, |
GLuint start, |
GLuint n ); |
typedef void (*trans_4ub_func)(GLubyte (*to)[4], |
CONST void *ptr, |
GLuint stride, |
GLuint start, |
GLuint n ); |
typedef void (*trans_4us_func)(GLushort (*to)[4], |
CONST void *ptr, |
GLuint stride, |
GLuint start, |
GLuint n ); |
typedef void (*trans_4f_func)(GLfloat (*to)[4], |
CONST void *ptr, |
GLuint stride, |
GLuint start, |
GLuint n ); |
typedef void (*trans_3f_func)(GLfloat (*to)[3], |
CONST void *ptr, |
GLuint stride, |
GLuint start, |
GLuint n ); |
#define TYPE_IDX(t) ((t) & 0xf) |
#define MAX_TYPES TYPE_IDX(GL_DOUBLE)+1 /* 0xa + 1 */ |
/* This macro is used on other systems, so undefine it for this module */ |
#undef CHECK |
static trans_1f_func _math_trans_1f_tab[MAX_TYPES]; |
static trans_1ui_func _math_trans_1ui_tab[MAX_TYPES]; |
static trans_1ub_func _math_trans_1ub_tab[MAX_TYPES]; |
static trans_3f_func _math_trans_3f_tab[MAX_TYPES]; |
static trans_4ub_func _math_trans_4ub_tab[5][MAX_TYPES]; |
static trans_4us_func _math_trans_4us_tab[5][MAX_TYPES]; |
static trans_4f_func _math_trans_4f_tab[5][MAX_TYPES]; |
#define PTR_ELT(ptr, elt) (((SRC *)ptr)[elt]) |
#define TAB(x) _math_trans##x##_tab |
#define ARGS GLuint start, GLuint n |
#define SRC_START start |
#define DST_START 0 |
#define STRIDE stride |
#define NEXT_F f += stride |
#define NEXT_F2 |
#define CHECK |
/* GL_BYTE |
*/ |
#define SRC GLbyte |
#define SRC_IDX TYPE_IDX(GL_BYTE) |
#define TRX_3F(f,n) BYTE_TO_FLOAT( PTR_ELT(f,n) ) |
#define TRX_4F(f,n) BYTE_TO_FLOAT( PTR_ELT(f,n) ) |
#define TRX_UB(ub, f,n) ub = BYTE_TO_UBYTE( PTR_ELT(f,n) ) |
#define TRX_US(ch, f,n) ch = BYTE_TO_USHORT( PTR_ELT(f,n) ) |
#define TRX_UI(f,n) (PTR_ELT(f,n) < 0 ? 0 : (GLuint) PTR_ELT(f,n)) |
#define SZ 4 |
#define INIT init_trans_4_GLbyte_raw |
#define DEST_4F trans_4_GLbyte_4f_raw |
#define DEST_4UB trans_4_GLbyte_4ub_raw |
#define DEST_4US trans_4_GLbyte_4us_raw |
#include "m_trans_tmp.h" |
#define SZ 3 |
#define INIT init_trans_3_GLbyte_raw |
#define DEST_4F trans_3_GLbyte_4f_raw |
#define DEST_4UB trans_3_GLbyte_4ub_raw |
#define DEST_4US trans_3_GLbyte_4us_raw |
#define DEST_3F trans_3_GLbyte_3f_raw |
#include "m_trans_tmp.h" |
#define SZ 2 |
#define INIT init_trans_2_GLbyte_raw |
#define DEST_4F trans_2_GLbyte_4f_raw |
#include "m_trans_tmp.h" |
#define SZ 1 |
#define INIT init_trans_1_GLbyte_raw |
#define DEST_4F trans_1_GLbyte_4f_raw |
#define DEST_1UB trans_1_GLbyte_1ub_raw |
#define DEST_1UI trans_1_GLbyte_1ui_raw |
#include "m_trans_tmp.h" |
#undef SRC |
#undef TRX_3F |
#undef TRX_4F |
#undef TRX_UB |
#undef TRX_US |
#undef TRX_UI |
#undef SRC_IDX |
/* GL_UNSIGNED_BYTE |
*/ |
#define SRC GLubyte |
#define SRC_IDX TYPE_IDX(GL_UNSIGNED_BYTE) |
#define TRX_3F(f,n) UBYTE_TO_FLOAT(PTR_ELT(f,n)) |
#define TRX_4F(f,n) UBYTE_TO_FLOAT(PTR_ELT(f,n)) |
#define TRX_UB(ub, f,n) ub = PTR_ELT(f,n) |
#define TRX_US(us, f,n) us = UBYTE_TO_USHORT(PTR_ELT(f,n)) |
#define TRX_UI(f,n) (GLuint)PTR_ELT(f,n) |
/* 4ub->4ub handled in special case below. |
*/ |
#define SZ 4 |
#define INIT init_trans_4_GLubyte_raw |
#define DEST_4F trans_4_GLubyte_4f_raw |
#define DEST_4US trans_4_GLubyte_4us_raw |
#include "m_trans_tmp.h" |
#define SZ 3 |
#define INIT init_trans_3_GLubyte_raw |
#define DEST_4UB trans_3_GLubyte_4ub_raw |
#define DEST_4US trans_3_GLubyte_4us_raw |
#define DEST_3F trans_3_GLubyte_3f_raw |
#define DEST_4F trans_3_GLubyte_4f_raw |
#include "m_trans_tmp.h" |
#define SZ 1 |
#define INIT init_trans_1_GLubyte_raw |
#define DEST_1UI trans_1_GLubyte_1ui_raw |
#define DEST_1UB trans_1_GLubyte_1ub_raw |
#include "m_trans_tmp.h" |
#undef SRC |
#undef SRC_IDX |
#undef TRX_3F |
#undef TRX_4F |
#undef TRX_UB |
#undef TRX_US |
#undef TRX_UI |
/* GL_SHORT |
*/ |
#define SRC GLshort |
#define SRC_IDX TYPE_IDX(GL_SHORT) |
#define TRX_3F(f,n) SHORT_TO_FLOAT( PTR_ELT(f,n) ) |
#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) ) |
#define TRX_UB(ub, f,n) ub = SHORT_TO_UBYTE(PTR_ELT(f,n)) |
#define TRX_US(us, f,n) us = SHORT_TO_USHORT(PTR_ELT(f,n)) |
#define TRX_UI(f,n) (PTR_ELT(f,n) < 0 ? 0 : (GLuint) PTR_ELT(f,n)) |
#define SZ 4 |
#define INIT init_trans_4_GLshort_raw |
#define DEST_4F trans_4_GLshort_4f_raw |
#define DEST_4UB trans_4_GLshort_4ub_raw |
#define DEST_4US trans_4_GLshort_4us_raw |
#include "m_trans_tmp.h" |
#define SZ 3 |
#define INIT init_trans_3_GLshort_raw |
#define DEST_4F trans_3_GLshort_4f_raw |
#define DEST_4UB trans_3_GLshort_4ub_raw |
#define DEST_4US trans_3_GLshort_4us_raw |
#define DEST_3F trans_3_GLshort_3f_raw |
#include "m_trans_tmp.h" |
#define SZ 2 |
#define INIT init_trans_2_GLshort_raw |
#define DEST_4F trans_2_GLshort_4f_raw |
#include "m_trans_tmp.h" |
#define SZ 1 |
#define INIT init_trans_1_GLshort_raw |
#define DEST_4F trans_1_GLshort_4f_raw |
#define DEST_1UB trans_1_GLshort_1ub_raw |
#define DEST_1UI trans_1_GLshort_1ui_raw |
#include "m_trans_tmp.h" |
#undef SRC |
#undef SRC_IDX |
#undef TRX_3F |
#undef TRX_4F |
#undef TRX_UB |
#undef TRX_US |
#undef TRX_UI |
/* GL_UNSIGNED_SHORT |
*/ |
#define SRC GLushort |
#define SRC_IDX TYPE_IDX(GL_UNSIGNED_SHORT) |
#define TRX_3F(f,n) USHORT_TO_FLOAT( PTR_ELT(f,n) ) |
#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) ) |
#define TRX_UB(ub,f,n) ub = (GLubyte) (PTR_ELT(f,n) >> 8) |
#define TRX_US(us,f,n) us = (GLushort) (PTR_ELT(f,n) >> 8) |
#define TRX_UI(f,n) (GLuint) PTR_ELT(f,n) |
#define SZ 4 |
#define INIT init_trans_4_GLushort_raw |
#define DEST_4F trans_4_GLushort_4f_raw |
#define DEST_4UB trans_4_GLushort_4ub_raw |
#define DEST_4US trans_4_GLushort_4us_raw |
#include "m_trans_tmp.h" |
#define SZ 3 |
#define INIT init_trans_3_GLushort_raw |
#define DEST_4F trans_3_GLushort_4f_raw |
#define DEST_4UB trans_3_GLushort_4ub_raw |
#define DEST_4US trans_3_GLushort_4us_raw |
#define DEST_3F trans_3_GLushort_3f_raw |
#include "m_trans_tmp.h" |
#define SZ 2 |
#define INIT init_trans_2_GLushort_raw |
#define DEST_4F trans_2_GLushort_4f_raw |
#include "m_trans_tmp.h" |
#define SZ 1 |
#define INIT init_trans_1_GLushort_raw |
#define DEST_4F trans_1_GLushort_4f_raw |
#define DEST_1UB trans_1_GLushort_1ub_raw |
#define DEST_1UI trans_1_GLushort_1ui_raw |
#include "m_trans_tmp.h" |
#undef SRC |
#undef SRC_IDX |
#undef TRX_3F |
#undef TRX_4F |
#undef TRX_UB |
#undef TRX_US |
#undef TRX_UI |
/* GL_INT |
*/ |
#define SRC GLint |
#define SRC_IDX TYPE_IDX(GL_INT) |
#define TRX_3F(f,n) INT_TO_FLOAT( PTR_ELT(f,n) ) |
#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) ) |
#define TRX_UB(ub, f,n) ub = INT_TO_UBYTE(PTR_ELT(f,n)) |
#define TRX_US(us, f,n) us = INT_TO_USHORT(PTR_ELT(f,n)) |
#define TRX_UI(f,n) (PTR_ELT(f,n) < 0 ? 0 : (GLuint) PTR_ELT(f,n)) |
#define SZ 4 |
#define INIT init_trans_4_GLint_raw |
#define DEST_4F trans_4_GLint_4f_raw |
#define DEST_4UB trans_4_GLint_4ub_raw |
#define DEST_4US trans_4_GLint_4us_raw |
#include "m_trans_tmp.h" |
#define SZ 3 |
#define INIT init_trans_3_GLint_raw |
#define DEST_4F trans_3_GLint_4f_raw |
#define DEST_4UB trans_3_GLint_4ub_raw |
#define DEST_4US trans_3_GLint_4us_raw |
#define DEST_3F trans_3_GLint_3f_raw |
#include "m_trans_tmp.h" |
#define SZ 2 |
#define INIT init_trans_2_GLint_raw |
#define DEST_4F trans_2_GLint_4f_raw |
#include "m_trans_tmp.h" |
#define SZ 1 |
#define INIT init_trans_1_GLint_raw |
#define DEST_4F trans_1_GLint_4f_raw |
#define DEST_1UB trans_1_GLint_1ub_raw |
#define DEST_1UI trans_1_GLint_1ui_raw |
#include "m_trans_tmp.h" |
#undef SRC |
#undef SRC_IDX |
#undef TRX_3F |
#undef TRX_4F |
#undef TRX_UB |
#undef TRX_US |
#undef TRX_UI |
/* GL_UNSIGNED_INT |
*/ |
#define SRC GLuint |
#define SRC_IDX TYPE_IDX(GL_UNSIGNED_INT) |
#define TRX_3F(f,n) INT_TO_FLOAT( PTR_ELT(f,n) ) |
#define TRX_4F(f,n) (GLfloat)( PTR_ELT(f,n) ) |
#define TRX_UB(ub, f,n) ub = (GLubyte) (PTR_ELT(f,n) >> 24) |
#define TRX_US(us, f,n) us = (GLshort) (PTR_ELT(f,n) >> 16) |
#define TRX_UI(f,n) PTR_ELT(f,n) |
#define SZ 4 |
#define INIT init_trans_4_GLuint_raw |
#define DEST_4F trans_4_GLuint_4f_raw |
#define DEST_4UB trans_4_GLuint_4ub_raw |
#define DEST_4US trans_4_GLuint_4us_raw |
#include "m_trans_tmp.h" |
#define SZ 3 |
#define INIT init_trans_3_GLuint_raw |
#define DEST_4F trans_3_GLuint_4f_raw |
#define DEST_4UB trans_3_GLuint_4ub_raw |
#define DEST_4US trans_3_GLuint_4us_raw |
#define DEST_3F trans_3_GLuint_3f_raw |
#include "m_trans_tmp.h" |
#define SZ 2 |
#define INIT init_trans_2_GLuint_raw |
#define DEST_4F trans_2_GLuint_4f_raw |
#include "m_trans_tmp.h" |
#define SZ 1 |
#define INIT init_trans_1_GLuint_raw |
#define DEST_4F trans_1_GLuint_4f_raw |
#define DEST_1UB trans_1_GLuint_1ub_raw |
#define DEST_1UI trans_1_GLuint_1ui_raw |
#include "m_trans_tmp.h" |
#undef SRC |
#undef SRC_IDX |
#undef TRX_3F |
#undef TRX_4F |
#undef TRX_UB |
#undef TRX_US |
#undef TRX_UI |
/* GL_DOUBLE |
*/ |
#define SRC GLdouble |
#define SRC_IDX TYPE_IDX(GL_DOUBLE) |
#define TRX_3F(f,n) (GLfloat) PTR_ELT(f,n) |
#define TRX_4F(f,n) (GLfloat) PTR_ELT(f,n) |
#define TRX_UB(ub,f,n) UNCLAMPED_FLOAT_TO_UBYTE(ub, PTR_ELT(f,n)) |
#define TRX_US(us,f,n) UNCLAMPED_FLOAT_TO_USHORT(us, PTR_ELT(f,n)) |
#define TRX_UI(f,n) (GLuint) (GLint) PTR_ELT(f,n) |
#define TRX_1F(f,n) (GLfloat) PTR_ELT(f,n) |
#define SZ 4 |
#define INIT init_trans_4_GLdouble_raw |
#define DEST_4F trans_4_GLdouble_4f_raw |
#define DEST_4UB trans_4_GLdouble_4ub_raw |
#define DEST_4US trans_4_GLdouble_4us_raw |
#include "m_trans_tmp.h" |
#define SZ 3 |
#define INIT init_trans_3_GLdouble_raw |
#define DEST_4F trans_3_GLdouble_4f_raw |
#define DEST_4UB trans_3_GLdouble_4ub_raw |
#define DEST_4US trans_3_GLdouble_4us_raw |
#define DEST_3F trans_3_GLdouble_3f_raw |
#include "m_trans_tmp.h" |
#define SZ 2 |
#define INIT init_trans_2_GLdouble_raw |
#define DEST_4F trans_2_GLdouble_4f_raw |
#include "m_trans_tmp.h" |
#define SZ 1 |
#define INIT init_trans_1_GLdouble_raw |
#define DEST_4F trans_1_GLdouble_4f_raw |
#define DEST_1UB trans_1_GLdouble_1ub_raw |
#define DEST_1UI trans_1_GLdouble_1ui_raw |
#define DEST_1F trans_1_GLdouble_1f_raw |
#include "m_trans_tmp.h" |
#undef SRC |
#undef SRC_IDX |
/* GL_FLOAT |
*/ |
#define SRC GLfloat |
#define SRC_IDX TYPE_IDX(GL_FLOAT) |
#define SZ 4 |
#define INIT init_trans_4_GLfloat_raw |
#define DEST_4UB trans_4_GLfloat_4ub_raw |
#define DEST_4US trans_4_GLfloat_4us_raw |
#define DEST_4F trans_4_GLfloat_4f_raw |
#include "m_trans_tmp.h" |
#define SZ 3 |
#define INIT init_trans_3_GLfloat_raw |
#define DEST_4F trans_3_GLfloat_4f_raw |
#define DEST_4UB trans_3_GLfloat_4ub_raw |
#define DEST_4US trans_3_GLfloat_4us_raw |
#define DEST_3F trans_3_GLfloat_3f_raw |
#include "m_trans_tmp.h" |
#define SZ 2 |
#define INIT init_trans_2_GLfloat_raw |
#define DEST_4F trans_2_GLfloat_4f_raw |
#include "m_trans_tmp.h" |
#define SZ 1 |
#define INIT init_trans_1_GLfloat_raw |
#define DEST_4F trans_1_GLfloat_4f_raw |
#define DEST_1UB trans_1_GLfloat_1ub_raw |
#define DEST_1UI trans_1_GLfloat_1ui_raw |
#define DEST_1F trans_1_GLfloat_1f_raw |
#include "m_trans_tmp.h" |
#undef SRC |
#undef SRC_IDX |
#undef TRX_3F |
#undef TRX_4F |
#undef TRX_UB |
#undef TRX_US |
#undef TRX_UI |
static void trans_4_GLubyte_4ub_raw(GLubyte (*t)[4], |
CONST void *Ptr, |
GLuint stride, |
ARGS ) |
{ |
const GLubyte *f = (GLubyte *) Ptr + SRC_START * stride; |
GLuint i; |
if (((((long) f | (long) stride)) & 3L) == 0L) { |
/* Aligned. |
*/ |
for (i = DST_START ; i < n ; i++, f += stride) { |
COPY_4UBV( t[i], f ); |
} |
} else { |
for (i = DST_START ; i < n ; i++, f += stride) { |
t[i][0] = f[0]; |
t[i][1] = f[1]; |
t[i][2] = f[2]; |
t[i][3] = f[3]; |
} |
} |
} |
static void init_translate_raw(void) |
{ |
MEMSET( TAB(_1ui), 0, sizeof(TAB(_1ui)) ); |
MEMSET( TAB(_1ub), 0, sizeof(TAB(_1ub)) ); |
MEMSET( TAB(_3f), 0, sizeof(TAB(_3f)) ); |
MEMSET( TAB(_4ub), 0, sizeof(TAB(_4ub)) ); |
MEMSET( TAB(_4us), 0, sizeof(TAB(_4us)) ); |
MEMSET( TAB(_4f), 0, sizeof(TAB(_4f)) ); |
init_trans_4_GLbyte_raw(); |
init_trans_3_GLbyte_raw(); |
init_trans_2_GLbyte_raw(); |
init_trans_1_GLbyte_raw(); |
init_trans_1_GLubyte_raw(); |
init_trans_3_GLubyte_raw(); |
init_trans_4_GLubyte_raw(); |
init_trans_4_GLshort_raw(); |
init_trans_3_GLshort_raw(); |
init_trans_2_GLshort_raw(); |
init_trans_1_GLshort_raw(); |
init_trans_4_GLushort_raw(); |
init_trans_3_GLushort_raw(); |
init_trans_2_GLushort_raw(); |
init_trans_1_GLushort_raw(); |
init_trans_4_GLint_raw(); |
init_trans_3_GLint_raw(); |
init_trans_2_GLint_raw(); |
init_trans_1_GLint_raw(); |
init_trans_4_GLuint_raw(); |
init_trans_3_GLuint_raw(); |
init_trans_2_GLuint_raw(); |
init_trans_1_GLuint_raw(); |
init_trans_4_GLdouble_raw(); |
init_trans_3_GLdouble_raw(); |
init_trans_2_GLdouble_raw(); |
init_trans_1_GLdouble_raw(); |
init_trans_4_GLfloat_raw(); |
init_trans_3_GLfloat_raw(); |
init_trans_2_GLfloat_raw(); |
init_trans_1_GLfloat_raw(); |
TAB(_4ub)[4][TYPE_IDX(GL_UNSIGNED_BYTE)] = trans_4_GLubyte_4ub_raw; |
} |
#undef TAB |
#undef CLASS |
#undef ARGS |
#undef CHECK |
#undef SRC_START |
#undef DST_START |
#undef NEXT_F |
#undef NEXT_F2 |
void _math_init_translate( void ) |
{ |
init_translate_raw(); |
} |
void _math_trans_1f(GLfloat *to, |
CONST void *ptr, |
GLuint stride, |
GLenum type, |
GLuint start, |
GLuint n ) |
{ |
_math_trans_1f_tab[TYPE_IDX(type)]( to, ptr, stride, start, n ); |
} |
void _math_trans_1ui(GLuint *to, |
CONST void *ptr, |
GLuint stride, |
GLenum type, |
GLuint start, |
GLuint n ) |
{ |
_math_trans_1ui_tab[TYPE_IDX(type)]( to, ptr, stride, start, n ); |
} |
void _math_trans_1ub(GLubyte *to, |
CONST void *ptr, |
GLuint stride, |
GLenum type, |
GLuint start, |
GLuint n ) |
{ |
_math_trans_1ub_tab[TYPE_IDX(type)]( to, ptr, stride, start, n ); |
} |
void _math_trans_4ub(GLubyte (*to)[4], |
CONST void *ptr, |
GLuint stride, |
GLenum type, |
GLuint size, |
GLuint start, |
GLuint n ) |
{ |
_math_trans_4ub_tab[size][TYPE_IDX(type)]( to, ptr, stride, start, n ); |
} |
void _math_trans_4chan( GLchan (*to)[4], |
CONST void *ptr, |
GLuint stride, |
GLenum type, |
GLuint size, |
GLuint start, |
GLuint n ) |
{ |
#if CHAN_TYPE == GL_UNSIGNED_BYTE |
_math_trans_4ub( to, ptr, stride, type, size, start, n ); |
#elif CHAN_TYPE == GL_UNSIGNED_SHORT |
_math_trans_4us( to, ptr, stride, type, size, start, n ); |
#elif CHAN_TYPE == GL_FLOAT |
_math_trans_4f( to, ptr, stride, type, size, start, n ); |
#endif |
} |
void _math_trans_4us(GLushort (*to)[4], |
CONST void *ptr, |
GLuint stride, |
GLenum type, |
GLuint size, |
GLuint start, |
GLuint n ) |
{ |
_math_trans_4us_tab[size][TYPE_IDX(type)]( to, ptr, stride, start, n ); |
} |
void _math_trans_4f(GLfloat (*to)[4], |
CONST void *ptr, |
GLuint stride, |
GLenum type, |
GLuint size, |
GLuint start, |
GLuint n ) |
{ |
_math_trans_4f_tab[size][TYPE_IDX(type)]( to, ptr, stride, start, n ); |
} |
void _math_trans_3f(GLfloat (*to)[3], |
CONST void *ptr, |
GLuint stride, |
GLenum type, |
GLuint start, |
GLuint n ) |
{ |
_math_trans_3f_tab[TYPE_IDX(type)]( to, ptr, stride, start, n ); |
} |
/shark/trunk/ports/mesa/src/math/m_debug_clip.c |
---|
0,0 → 1,367 |
/* $Id: m_debug_clip.c,v 1.1 2003-02-28 11:48:05 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 5.0 |
* |
* Copyright (C) 1999-2001 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: |
* Gareth Hughes |
*/ |
#include "glheader.h" |
#include "context.h" |
#include "macros.h" |
#include "imports.h" |
#include "m_matrix.h" |
#include "m_xform.h" |
#include "m_debug.h" |
#include "m_debug_util.h" |
#ifdef DEBUG /* This code only used for debugging */ |
static clip_func *clip_tab[2] = { |
_mesa_clip_tab, |
_mesa_clip_np_tab |
}; |
static char *cnames[2] = { |
"_mesa_clip_tab", |
"_mesa_clip_np_tab" |
}; |
#ifdef RUN_DEBUG_BENCHMARK |
static char *cstrings[2] = { |
"clip, perspective divide", |
"clip, no divide" |
}; |
#endif |
/* ============================================================= |
* Reference cliptests |
*/ |
static GLvector4f *ref_cliptest_points4( GLvector4f *clip_vec, |
GLvector4f *proj_vec, |
GLubyte clipMask[], |
GLubyte *orMask, |
GLubyte *andMask ) |
{ |
const GLuint stride = clip_vec->stride; |
const GLuint count = clip_vec->count; |
const GLfloat *from = (GLfloat *)clip_vec->start; |
GLuint c = 0; |
GLfloat (*vProj)[4] = (GLfloat (*)[4])proj_vec->start; |
GLubyte tmpAndMask = *andMask; |
GLubyte tmpOrMask = *orMask; |
GLuint i; |
for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) ) { |
const GLfloat cx = from[0]; |
const GLfloat cy = from[1]; |
const GLfloat cz = from[2]; |
const GLfloat cw = from[3]; |
GLubyte mask = 0; |
if ( -cx + cw < 0 ) mask |= CLIP_RIGHT_BIT; |
if ( cx + cw < 0 ) mask |= CLIP_LEFT_BIT; |
if ( -cy + cw < 0 ) mask |= CLIP_TOP_BIT; |
if ( cy + cw < 0 ) mask |= CLIP_BOTTOM_BIT; |
if ( -cz + cw < 0 ) mask |= CLIP_FAR_BIT; |
if ( cz + cw < 0 ) mask |= CLIP_NEAR_BIT; |
clipMask[i] = mask; |
if ( mask ) { |
c++; |
tmpAndMask &= mask; |
tmpOrMask |= mask; |
vProj[i][0] = 0; |
vProj[i][1] = 0; |
vProj[i][2] = 0; |
vProj[i][3] = 1; |
} else { |
GLfloat oow = 1.0F / cw; |
vProj[i][0] = cx * oow; |
vProj[i][1] = cy * oow; |
vProj[i][2] = cz * oow; |
vProj[i][3] = oow; |
} |
} |
*orMask = tmpOrMask; |
*andMask = (GLubyte) (c < count ? 0 : tmpAndMask); |
proj_vec->flags |= VEC_SIZE_4; |
proj_vec->size = 4; |
proj_vec->count = clip_vec->count; |
return proj_vec; |
} |
/* Keep these here for now, even though we don't use them... |
*/ |
static GLvector4f *ref_cliptest_points3( GLvector4f *clip_vec, |
GLvector4f *proj_vec, |
GLubyte clipMask[], |
GLubyte *orMask, |
GLubyte *andMask ) |
{ |
const GLuint stride = clip_vec->stride; |
const GLuint count = clip_vec->count; |
const GLfloat *from = (GLfloat *)clip_vec->start; |
GLubyte tmpOrMask = *orMask; |
GLubyte tmpAndMask = *andMask; |
GLuint i; |
for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) ) { |
const GLfloat cx = from[0], cy = from[1], cz = from[2]; |
GLubyte mask = 0; |
if ( cx > 1.0 ) mask |= CLIP_RIGHT_BIT; |
else if ( cx < -1.0 ) mask |= CLIP_LEFT_BIT; |
if ( cy > 1.0 ) mask |= CLIP_TOP_BIT; |
else if ( cy < -1.0 ) mask |= CLIP_BOTTOM_BIT; |
if ( cz > 1.0 ) mask |= CLIP_FAR_BIT; |
else if ( cz < -1.0 ) mask |= CLIP_NEAR_BIT; |
clipMask[i] = mask; |
tmpOrMask |= mask; |
tmpAndMask &= mask; |
} |
*orMask = tmpOrMask; |
*andMask = tmpAndMask; |
return clip_vec; |
} |
static GLvector4f * ref_cliptest_points2( GLvector4f *clip_vec, |
GLvector4f *proj_vec, |
GLubyte clipMask[], |
GLubyte *orMask, |
GLubyte *andMask ) |
{ |
const GLuint stride = clip_vec->stride; |
const GLuint count = clip_vec->count; |
const GLfloat *from = (GLfloat *)clip_vec->start; |
GLubyte tmpOrMask = *orMask; |
GLubyte tmpAndMask = *andMask; |
GLuint i; |
for ( i = 0 ; i < count ; i++, STRIDE_F(from, stride) ) { |
const GLfloat cx = from[0], cy = from[1]; |
GLubyte mask = 0; |
if ( cx > 1.0 ) mask |= CLIP_RIGHT_BIT; |
else if ( cx < -1.0 ) mask |= CLIP_LEFT_BIT; |
if ( cy > 1.0 ) mask |= CLIP_TOP_BIT; |
else if ( cy < -1.0 ) mask |= CLIP_BOTTOM_BIT; |
clipMask[i] = mask; |
tmpOrMask |= mask; |
tmpAndMask &= mask; |
} |
*orMask = tmpOrMask; |
*andMask = tmpAndMask; |
return clip_vec; |
} |
static clip_func ref_cliptest[5] = { |
0, |
0, |
ref_cliptest_points2, |
ref_cliptest_points3, |
ref_cliptest_points4 |
}; |
/* ============================================================= |
* Cliptest tests |
*/ |
static GLfloat s[TEST_COUNT][4] ALIGN16; |
static GLfloat d[TEST_COUNT][4] ALIGN16; |
static GLfloat r[TEST_COUNT][4] ALIGN16; |
static int test_cliptest_function( clip_func func, int np, |
int psize, long *cycles ) |
{ |
GLvector4f source[1], dest[1], ref[1]; |
GLubyte dm[TEST_COUNT], dco, dca; |
GLubyte rm[TEST_COUNT], rco, rca; |
int i, j; |
#ifdef RUN_DEBUG_BENCHMARK |
int cycle_i; /* the counter for the benchmarks we run */ |
#endif |
(void) cycles; |
if ( psize > 4 ) { |
_mesa_problem( NULL, "test_cliptest_function called with psize > 4\n" ); |
return 0; |
} |
for ( i = 0 ; i < TEST_COUNT ; i++) { |
ASSIGN_4V( d[i], 0.0, 0.0, 0.0, 1.0 ); |
ASSIGN_4V( s[i], 0.0, 0.0, 0.0, 1.0 ); |
for ( j = 0 ; j < psize ; j++ ) |
s[i][j] = rnd(); |
} |
source->data = (GLfloat(*)[4])s; |
source->start = (GLfloat *)s; |
source->count = TEST_COUNT; |
source->stride = sizeof(s[0]); |
source->size = 4; |
source->flags = 0; |
dest->data = (GLfloat(*)[4])d; |
dest->start = (GLfloat *)d; |
dest->count = TEST_COUNT; |
dest->stride = sizeof(float[4]); |
dest->size = 0; |
dest->flags = 0; |
ref->data = (GLfloat(*)[4])r; |
ref->start = (GLfloat *)r; |
ref->count = TEST_COUNT; |
ref->stride = sizeof(float[4]); |
ref->size = 0; |
ref->flags = 0; |
dco = rco = 0; |
dca = rca = CLIP_ALL_BITS; |
ref_cliptest[psize]( source, ref, rm, &rco, &rca ); |
if ( mesa_profile ) { |
BEGIN_RACE( *cycles ); |
func( source, dest, dm, &dco, &dca ); |
END_RACE( *cycles ); |
} |
else { |
func( source, dest, dm, &dco, &dca ); |
} |
if ( dco != rco ) { |
_mesa_printf(NULL, "\n-----------------------------\n" ); |
_mesa_printf(NULL, "dco = 0x%02x rco = 0x%02x\n", dco, rco ); |
return 0; |
} |
if ( dca != rca ) { |
_mesa_printf(NULL, "\n-----------------------------\n" ); |
_mesa_printf(NULL, "dca = 0x%02x rca = 0x%02x\n", dca, rca ); |
return 0; |
} |
for ( i = 0 ; i < TEST_COUNT ; i++ ) { |
if ( dm[i] != rm[i] ) { |
_mesa_printf(NULL, "\n-----------------------------\n" ); |
_mesa_printf(NULL, "(i = %i)\n", i ); |
_mesa_printf(NULL, "dm = 0x%02x rm = 0x%02x\n", dm[i], rm[i] ); |
return 0; |
} |
} |
/* Only verify output on projected points4 case. FIXME: Do we need |
* to test other cases? |
*/ |
if ( np || psize < 4 ) |
return 1; |
for ( i = 0 ; i < TEST_COUNT ; i++ ) { |
for ( j = 0 ; j < 4 ; j++ ) { |
if ( significand_match( d[i][j], r[i][j] ) < REQUIRED_PRECISION ) { |
_mesa_printf(NULL, "\n-----------------------------\n" ); |
_mesa_printf(NULL, "(i = %i, j = %i) dm = 0x%02x rm = 0x%02x\n", |
i, j, dm[i], rm[i] ); |
_mesa_printf(NULL, "%f \t %f \t [diff = %e - %i bit missed]\n", |
d[i][0], r[i][0], r[i][0]-d[i][0], |
MAX_PRECISION - significand_match( d[i][0], r[i][0] ) ); |
_mesa_printf(NULL, "%f \t %f \t [diff = %e - %i bit missed]\n", |
d[i][1], r[i][1], r[i][1]-d[i][1], |
MAX_PRECISION - significand_match( d[i][1], r[i][1] ) ); |
_mesa_printf(NULL, "%f \t %f \t [diff = %e - %i bit missed]\n", |
d[i][2], r[i][2], r[i][2]-d[i][2], |
MAX_PRECISION - significand_match( d[i][2], r[i][2] ) ); |
_mesa_printf(NULL, "%f \t %f \t [diff = %e - %i bit missed]\n", |
d[i][3], r[i][3], r[i][3]-d[i][3], |
MAX_PRECISION - significand_match( d[i][3], r[i][3] ) ); |
return 0; |
} |
} |
} |
return 1; |
} |
void _math_test_all_cliptest_functions( char *description ) |
{ |
int np, psize; |
long benchmark_tab[2][4]; |
static int first_time = 1; |
if ( first_time ) { |
first_time = 0; |
mesa_profile = _mesa_getenv( "MESA_PROFILE" ); |
} |
#ifdef RUN_DEBUG_BENCHMARK |
if ( mesa_profile ) { |
if ( !counter_overhead ) { |
INIT_COUNTER(); |
_mesa_printf(NULL, "counter overhead: %ld cycles\n\n", counter_overhead ); |
} |
_mesa_printf(NULL, "cliptest results after hooking in %s functions:\n", description ); |
} |
#endif |
#ifdef RUN_DEBUG_BENCHMARK |
if ( mesa_profile ) { |
_mesa_printf(NULL, "\n\t" ); |
for ( psize = 2 ; psize <= 4 ; psize++ ) { |
_mesa_printf(NULL, " p%d\t", psize ); |
} |
_mesa_printf(NULL, "\n--------------------------------------------------------\n\t" ); |
} |
#endif |
for ( np = 0 ; np < 2 ; np++ ) { |
for ( psize = 2 ; psize <= 4 ; psize++ ) { |
clip_func func = clip_tab[np][psize]; |
long *cycles = &(benchmark_tab[np][psize-1]); |
if ( test_cliptest_function( func, np, psize, cycles ) == 0 ) { |
char buf[100]; |
_mesa_sprintf(NULL, buf, "%s[%d] failed test (%s)", |
cnames[np], psize, description ); |
_mesa_problem( NULL, buf ); |
} |
#ifdef RUN_DEBUG_BENCHMARK |
if ( mesa_profile ) |
_mesa_printf(NULL, " %li\t", benchmark_tab[np][psize-1] ); |
#endif |
} |
#ifdef RUN_DEBUG_BENCHMARK |
if ( mesa_profile ) |
_mesa_printf(NULL, " | [%s]\n\t", cstrings[np] ); |
#endif |
} |
#ifdef RUN_DEBUG_BENCHMARK |
if ( mesa_profile ) |
_mesa_printf(NULL, "\n" ); |
#endif |
} |
#endif /* DEBUG */ |
/shark/trunk/ports/mesa/src/math/m_copy_tmp.h |
---|
0,0 → 1,87 |
/* $Id: m_copy_tmp.h,v 1.1 2003-02-28 11:48:04 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 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. |
*/ |
/* |
* New (3.1) transformation code written by Keith Whitwell. |
*/ |
#define COPY_FUNC( BITS ) \ |
static void TAG2(copy, BITS)( GLvector4f *to, const GLvector4f *f ) \ |
{ \ |
GLfloat (*t)[4] = (GLfloat (*)[4])to->start; \ |
GLfloat *from = f->start; \ |
GLuint stride = f->stride; \ |
GLuint count = f->count; \ |
GLuint i; \ |
\ |
if (BITS) \ |
STRIDE_LOOP { \ |
if (BITS&1) t[i][0] = from[0]; \ |
if (BITS&2) t[i][1] = from[1]; \ |
if (BITS&4) t[i][2] = from[2]; \ |
if (BITS&8) t[i][3] = from[3]; \ |
} \ |
} |
/* We got them all here: |
*/ |
COPY_FUNC( 0x0 ) /* noop */ |
COPY_FUNC( 0x1 ) |
COPY_FUNC( 0x2 ) |
COPY_FUNC( 0x3 ) |
COPY_FUNC( 0x4 ) |
COPY_FUNC( 0x5 ) |
COPY_FUNC( 0x6 ) |
COPY_FUNC( 0x7 ) |
COPY_FUNC( 0x8 ) |
COPY_FUNC( 0x9 ) |
COPY_FUNC( 0xa ) |
COPY_FUNC( 0xb ) |
COPY_FUNC( 0xc ) |
COPY_FUNC( 0xd ) |
COPY_FUNC( 0xe ) |
COPY_FUNC( 0xf ) |
static void TAG2(init_copy, 0)( void ) |
{ |
_mesa_copy_tab[0x0] = TAG2(copy, 0x0); |
_mesa_copy_tab[0x1] = TAG2(copy, 0x1); |
_mesa_copy_tab[0x2] = TAG2(copy, 0x2); |
_mesa_copy_tab[0x3] = TAG2(copy, 0x3); |
_mesa_copy_tab[0x4] = TAG2(copy, 0x4); |
_mesa_copy_tab[0x5] = TAG2(copy, 0x5); |
_mesa_copy_tab[0x6] = TAG2(copy, 0x6); |
_mesa_copy_tab[0x7] = TAG2(copy, 0x7); |
_mesa_copy_tab[0x8] = TAG2(copy, 0x8); |
_mesa_copy_tab[0x9] = TAG2(copy, 0x9); |
_mesa_copy_tab[0xa] = TAG2(copy, 0xa); |
_mesa_copy_tab[0xb] = TAG2(copy, 0xb); |
_mesa_copy_tab[0xc] = TAG2(copy, 0xc); |
_mesa_copy_tab[0xd] = TAG2(copy, 0xd); |
_mesa_copy_tab[0xe] = TAG2(copy, 0xe); |
_mesa_copy_tab[0xf] = TAG2(copy, 0xf); |
} |
/shark/trunk/ports/mesa/src/math/m_norm_tmp.h |
---|
0,0 → 1,391 |
/* $Id: m_norm_tmp.h,v 1.1 2003-02-28 11:48:05 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. |
*/ |
/* |
* New (3.1) transformation code written by Keith Whitwell. |
*/ |
/* Functions to tranform a vector of normals. This includes applying |
* the transformation matrix, rescaling and normalization. |
*/ |
/* |
* mat - the 4x4 transformation matrix |
* scale - uniform scale factor of the transformation matrix (not always used) |
* in - the source vector of normals |
* lengths - length of each incoming normal (may be NULL) (a display list |
* optimization) |
* dest - the destination vector of normals |
*/ |
static void _XFORMAPI |
TAG(transform_normalize_normals)( const GLmatrix *mat, |
GLfloat scale, |
const GLvector4f *in, |
const GLfloat *lengths, |
GLvector4f *dest ) |
{ |
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start; |
const GLfloat *from = in->start; |
const GLuint stride = in->stride; |
const GLuint count = in->count; |
const GLfloat *m = mat->inv; |
GLfloat m0 = m[0], m4 = m[4], m8 = m[8]; |
GLfloat m1 = m[1], m5 = m[5], m9 = m[9]; |
GLfloat m2 = m[2], m6 = m[6], m10 = m[10]; |
GLuint i; |
if (!lengths) { |
STRIDE_LOOP { |
GLfloat tx, ty, tz; |
{ |
const GLfloat ux = from[0], uy = from[1], uz = from[2]; |
tx = ux * m0 + uy * m1 + uz * m2; |
ty = ux * m4 + uy * m5 + uz * m6; |
tz = ux * m8 + uy * m9 + uz * m10; |
} |
{ |
GLdouble len = tx*tx + ty*ty + tz*tz; |
if (len > 1e-20) { |
GLdouble scale = 1.0 / GL_SQRT(len); |
out[i][0] = (GLfloat) (tx * scale); |
out[i][1] = (GLfloat) (ty * scale); |
out[i][2] = (GLfloat) (tz * scale); |
} |
else { |
out[i][0] = out[i][1] = out[i][2] = 0; |
} |
} |
} |
} |
else { |
if (scale != 1.0) { |
m0 *= scale, m4 *= scale, m8 *= scale; |
m1 *= scale, m5 *= scale, m9 *= scale; |
m2 *= scale, m6 *= scale, m10 *= scale; |
} |
STRIDE_LOOP { |
GLfloat tx, ty, tz; |
{ |
const GLfloat ux = from[0], uy = from[1], uz = from[2]; |
tx = ux * m0 + uy * m1 + uz * m2; |
ty = ux * m4 + uy * m5 + uz * m6; |
tz = ux * m8 + uy * m9 + uz * m10; |
} |
{ |
GLfloat len = lengths[i]; |
out[i][0] = tx * len; |
out[i][1] = ty * len; |
out[i][2] = tz * len; |
} |
} |
} |
dest->count = in->count; |
} |
static void _XFORMAPI |
TAG(transform_normalize_normals_no_rot)( const GLmatrix *mat, |
GLfloat scale, |
const GLvector4f *in, |
const GLfloat *lengths, |
GLvector4f *dest ) |
{ |
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start; |
const GLfloat *from = in->start; |
const GLuint stride = in->stride; |
const GLuint count = in->count; |
const GLfloat *m = mat->inv; |
GLfloat m0 = m[0]; |
GLfloat m5 = m[5]; |
GLfloat m10 = m[10]; |
GLuint i; |
if (!lengths) { |
STRIDE_LOOP { |
GLfloat tx, ty, tz; |
{ |
const GLfloat ux = from[0], uy = from[1], uz = from[2]; |
tx = ux * m0 ; |
ty = uy * m5 ; |
tz = uz * m10; |
} |
{ |
GLdouble len = tx*tx + ty*ty + tz*tz; |
if (len > 1e-20) { |
GLdouble scale = 1.0 / GL_SQRT(len); |
out[i][0] = (GLfloat) (tx * scale); |
out[i][1] = (GLfloat) (ty * scale); |
out[i][2] = (GLfloat) (tz * scale); |
} |
else { |
out[i][0] = out[i][1] = out[i][2] = 0; |
} |
} |
} |
} |
else { |
m0 *= scale; |
m5 *= scale; |
m10 *= scale; |
STRIDE_LOOP { |
GLfloat tx, ty, tz; |
{ |
const GLfloat ux = from[0], uy = from[1], uz = from[2]; |
tx = ux * m0 ; |
ty = uy * m5 ; |
tz = uz * m10; |
} |
{ |
GLfloat len = lengths[i]; |
out[i][0] = tx * len; |
out[i][1] = ty * len; |
out[i][2] = tz * len; |
} |
} |
} |
dest->count = in->count; |
} |
static void _XFORMAPI |
TAG(transform_rescale_normals_no_rot)( const GLmatrix *mat, |
GLfloat scale, |
const GLvector4f *in, |
const GLfloat *lengths, |
GLvector4f *dest ) |
{ |
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start; |
const GLfloat *from = in->start; |
const GLuint stride = in->stride; |
const GLuint count = in->count; |
const GLfloat *m = mat->inv; |
const GLfloat m0 = scale*m[0]; |
const GLfloat m5 = scale*m[5]; |
const GLfloat m10 = scale*m[10]; |
GLuint i; |
(void) lengths; |
STRIDE_LOOP { |
GLfloat ux = from[0], uy = from[1], uz = from[2]; |
out[i][0] = ux * m0; |
out[i][1] = uy * m5; |
out[i][2] = uz * m10; |
} |
dest->count = in->count; |
} |
static void _XFORMAPI |
TAG(transform_rescale_normals)( const GLmatrix *mat, |
GLfloat scale, |
const GLvector4f *in, |
const GLfloat *lengths, |
GLvector4f *dest ) |
{ |
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start; |
const GLfloat *from = in->start; |
const GLuint stride = in->stride; |
const GLuint count = in->count; |
/* Since we are unlikely to have < 3 vertices in the buffer, |
* it makes sense to pre-multiply by scale. |
*/ |
const GLfloat *m = mat->inv; |
const GLfloat m0 = scale*m[0], m4 = scale*m[4], m8 = scale*m[8]; |
const GLfloat m1 = scale*m[1], m5 = scale*m[5], m9 = scale*m[9]; |
const GLfloat m2 = scale*m[2], m6 = scale*m[6], m10 = scale*m[10]; |
GLuint i; |
(void) lengths; |
STRIDE_LOOP { |
GLfloat ux = from[0], uy = from[1], uz = from[2]; |
out[i][0] = ux * m0 + uy * m1 + uz * m2; |
out[i][1] = ux * m4 + uy * m5 + uz * m6; |
out[i][2] = ux * m8 + uy * m9 + uz * m10; |
} |
dest->count = in->count; |
} |
static void _XFORMAPI |
TAG(transform_normals_no_rot)( const GLmatrix *mat, |
GLfloat scale, |
const GLvector4f *in, |
const GLfloat *lengths, |
GLvector4f *dest ) |
{ |
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start; |
const GLfloat *from = in->start; |
const GLuint stride = in->stride; |
const GLuint count = in->count; |
const GLfloat *m = mat->inv; |
const GLfloat m0 = m[0]; |
const GLfloat m5 = m[5]; |
const GLfloat m10 = m[10]; |
GLuint i; |
(void) scale; |
(void) lengths; |
STRIDE_LOOP { |
GLfloat ux = from[0], uy = from[1], uz = from[2]; |
out[i][0] = ux * m0; |
out[i][1] = uy * m5; |
out[i][2] = uz * m10; |
} |
dest->count = in->count; |
} |
static void _XFORMAPI |
TAG(transform_normals)( const GLmatrix *mat, |
GLfloat scale, |
const GLvector4f *in, |
const GLfloat *lengths, |
GLvector4f *dest ) |
{ |
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start; |
const GLfloat *from = in->start; |
const GLuint stride = in->stride; |
const GLuint count = in->count; |
const GLfloat *m = mat->inv; |
const GLfloat m0 = m[0], m4 = m[4], m8 = m[8]; |
const GLfloat m1 = m[1], m5 = m[5], m9 = m[9]; |
const GLfloat m2 = m[2], m6 = m[6], m10 = m[10]; |
GLuint i; |
(void) scale; |
(void) lengths; |
STRIDE_LOOP { |
GLfloat ux = from[0], uy = from[1], uz = from[2]; |
out[i][0] = ux * m0 + uy * m1 + uz * m2; |
out[i][1] = ux * m4 + uy * m5 + uz * m6; |
out[i][2] = ux * m8 + uy * m9 + uz * m10; |
} |
dest->count = in->count; |
} |
static void _XFORMAPI |
TAG(normalize_normals)( const GLmatrix *mat, |
GLfloat scale, |
const GLvector4f *in, |
const GLfloat *lengths, |
GLvector4f *dest ) |
{ |
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start; |
const GLfloat *from = in->start; |
const GLuint stride = in->stride; |
const GLuint count = in->count; |
GLuint i; |
(void) mat; |
(void) scale; |
if (lengths) { |
STRIDE_LOOP { |
const GLfloat x = from[0], y = from[1], z = from[2]; |
GLfloat invlen = lengths[i]; |
out[i][0] = x * invlen; |
out[i][1] = y * invlen; |
out[i][2] = z * invlen; |
} |
} |
else { |
STRIDE_LOOP { |
const GLfloat x = from[0], y = from[1], z = from[2]; |
GLdouble len = x * x + y * y + z * z; |
if (len > 1e-50) { |
len = 1.0 / GL_SQRT(len); |
out[i][0] = (GLfloat) (x * len); |
out[i][1] = (GLfloat) (y * len); |
out[i][2] = (GLfloat) (z * len); |
} |
else { |
out[i][0] = x; |
out[i][1] = y; |
out[i][2] = z; |
} |
} |
} |
dest->count = in->count; |
} |
static void _XFORMAPI |
TAG(rescale_normals)( const GLmatrix *mat, |
GLfloat scale, |
const GLvector4f *in, |
const GLfloat *lengths, |
GLvector4f *dest ) |
{ |
GLfloat (*out)[4] = (GLfloat (*)[4])dest->start; |
const GLfloat *from = in->start; |
const GLuint stride = in->stride; |
const GLuint count = in->count; |
GLuint i; |
(void) mat; |
(void) lengths; |
STRIDE_LOOP { |
SCALE_SCALAR_3V( out[i], scale, from ); |
} |
dest->count = in->count; |
} |
static void _XFORMAPI |
TAG(init_c_norm_transform)( void ) |
{ |
_mesa_normal_tab[NORM_TRANSFORM_NO_ROT] = |
TAG(transform_normals_no_rot); |
_mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_RESCALE] = |
TAG(transform_rescale_normals_no_rot); |
_mesa_normal_tab[NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE] = |
TAG(transform_normalize_normals_no_rot); |
_mesa_normal_tab[NORM_TRANSFORM] = |
TAG(transform_normals); |
_mesa_normal_tab[NORM_TRANSFORM | NORM_RESCALE] = |
TAG(transform_rescale_normals); |
_mesa_normal_tab[NORM_TRANSFORM | NORM_NORMALIZE] = |
TAG(transform_normalize_normals); |
_mesa_normal_tab[NORM_RESCALE] = |
TAG(rescale_normals); |
_mesa_normal_tab[NORM_NORMALIZE] = |
TAG(normalize_normals); |
} |
/shark/trunk/ports/mesa/src/math/m_dotprod_tmp.h |
---|
0,0 → 1,103 |
/* $Id: m_dotprod_tmp.h,v 1.1 2003-02-28 11:48:05 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 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. |
*/ |
/* |
* New (3.1) transformation code written by Keith Whitwell. |
*/ |
/* Note - respects the stride of the output vector. |
*/ |
static void TAG(dotprod_vec2)( GLfloat *out, |
GLuint outstride, |
const GLvector4f *coord_vec, |
const GLfloat plane[4] ) |
{ |
GLuint stride = coord_vec->stride; |
GLfloat *coord = coord_vec->start; |
GLuint count = coord_vec->count; |
GLuint i; |
const GLfloat plane0 = plane[0], plane1 = plane[1], plane3 = plane[3]; |
for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(out,outstride)) { |
*out = (coord[0] * plane0 + |
coord[1] * plane1 + |
plane3); |
} |
} |
static void TAG(dotprod_vec3)( GLfloat *out, |
GLuint outstride, |
const GLvector4f *coord_vec, |
const GLfloat plane[4] ) |
{ |
GLuint stride = coord_vec->stride; |
GLfloat *coord = coord_vec->start; |
GLuint count = coord_vec->count; |
GLuint i; |
const GLfloat plane0 = plane[0], plane1 = plane[1], plane2 = plane[2]; |
const GLfloat plane3 = plane[3]; |
for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(out,outstride)) { |
*out = (coord[0] * plane0 + |
coord[1] * plane1 + |
coord[2] * plane2 + |
plane3); |
} |
} |
static void TAG(dotprod_vec4)( GLfloat *out, |
GLuint outstride, |
const GLvector4f *coord_vec, |
const GLfloat plane[4] ) |
{ |
GLuint stride = coord_vec->stride; |
GLfloat *coord = coord_vec->start; |
GLuint count = coord_vec->count; |
GLuint i; |
const GLfloat plane0 = plane[0], plane1 = plane[1], plane2 = plane[2]; |
const GLfloat plane3 = plane[3]; |
for (i=0;i<count;i++,STRIDE_F(coord,stride),STRIDE_F(out,outstride)) { |
*out = (coord[0] * plane0 + |
coord[1] * plane1 + |
coord[2] * plane2 + |
coord[3] * plane3); |
} |
} |
static void TAG(init_dotprod)( void ) |
{ |
_mesa_dotprod_tab[2] = TAG(dotprod_vec2); |
_mesa_dotprod_tab[3] = TAG(dotprod_vec3); |
_mesa_dotprod_tab[4] = TAG(dotprod_vec4); |
} |
/shark/trunk/ports/mesa/src/math/m_xform.h |
---|
0,0 → 1,217 |
/* $Id: m_xform.h,v 1.1 2003-02-28 11:48:05 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 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. |
*/ |
#ifndef _M_XFORM_H |
#define _M_XFORM_H |
#include "glheader.h" |
#include "config.h" |
#include "math/m_vector.h" |
#include "math/m_matrix.h" |
#ifdef USE_X86_ASM |
#define _XFORMAPI _ASMAPI |
#define _XFORMAPIP _ASMAPIP |
#else |
#define _XFORMAPI |
#define _XFORMAPIP * |
#endif |
/* |
* Transform a point (column vector) by a matrix: Q = M * P |
*/ |
#define TRANSFORM_POINT( Q, M, P ) \ |
Q[0] = M[0] * P[0] + M[4] * P[1] + M[8] * P[2] + M[12] * P[3]; \ |
Q[1] = M[1] * P[0] + M[5] * P[1] + M[9] * P[2] + M[13] * P[3]; \ |
Q[2] = M[2] * P[0] + M[6] * P[1] + M[10] * P[2] + M[14] * P[3]; \ |
Q[3] = M[3] * P[0] + M[7] * P[1] + M[11] * P[2] + M[15] * P[3]; |
#define TRANSFORM_POINT3( Q, M, P ) \ |
Q[0] = M[0] * P[0] + M[4] * P[1] + M[8] * P[2] + M[12]; \ |
Q[1] = M[1] * P[0] + M[5] * P[1] + M[9] * P[2] + M[13]; \ |
Q[2] = M[2] * P[0] + M[6] * P[1] + M[10] * P[2] + M[14]; \ |
Q[3] = M[3] * P[0] + M[7] * P[1] + M[11] * P[2] + M[15]; |
/* |
* Transform a normal (row vector) by a matrix: [NX NY NZ] = N * MAT |
*/ |
#define TRANSFORM_NORMAL( TO, N, MAT ) \ |
do { \ |
TO[0] = N[0] * MAT[0] + N[1] * MAT[1] + N[2] * MAT[2]; \ |
TO[1] = N[0] * MAT[4] + N[1] * MAT[5] + N[2] * MAT[6]; \ |
TO[2] = N[0] * MAT[8] + N[1] * MAT[9] + N[2] * MAT[10]; \ |
} while (0) |
extern void _mesa_transform_vector( GLfloat u[4], |
CONST GLfloat v[4], |
CONST GLfloat m[16] ); |
extern void |
_math_init_transformation( void ); |
/* KW: Clip functions now do projective divide as well. The projected |
* coordinates are very useful to us because they let us cull |
* backfaces and eliminate vertices from lighting, fogging, etc |
* calculations. Despite the fact that this divide could be done one |
* day in hardware, we would still have a reason to want to do it here |
* as long as those other calculations remain in software. |
* |
* Clipping is a convenient place to do the divide on x86 as it should be |
* possible to overlap with integer outcode calculations. |
* |
* There are two cases where we wouldn't want to do the divide in cliptest: |
* - When we aren't clipping. We still might want to cull backfaces |
* so the divide should be done elsewhere. This currently never |
* happens. |
* |
* - When culling isn't likely to help us, such as when the GL culling |
* is disabled and we not lighting or are only lighting |
* one-sided. In this situation, backface determination provides |
* us with no useful information. A tricky case to detect is when |
* all input data is already culled, although hopefully the |
* application wouldn't turn on culling in such cases. |
* |
* We supply a buffer to hold the [x/w,y/w,z/w,1/w] values which |
* are the result of the projection. This is only used in the |
* 4-vector case - in other cases, we just use the clip coordinates |
* as the projected coordinates - they are identical. |
* |
* This is doubly convenient because it means the Win[] array is now |
* of the same stride as all the others, so I can now turn map_vertices |
* into a straight-forward matrix transformation, with asm acceleration |
* automatically available. |
*/ |
/* Vertex buffer clipping flags |
*/ |
#define CLIP_RIGHT_SHIFT 0 |
#define CLIP_LEFT_SHIFT 1 |
#define CLIP_TOP_SHIFT 2 |
#define CLIP_BOTTOM_SHIFT 3 |
#define CLIP_NEAR_SHIFT 4 |
#define CLIP_FAR_SHIFT 5 |
#define CLIP_RIGHT_BIT 0x01 |
#define CLIP_LEFT_BIT 0x02 |
#define CLIP_TOP_BIT 0x04 |
#define CLIP_BOTTOM_BIT 0x08 |
#define CLIP_NEAR_BIT 0x10 |
#define CLIP_FAR_BIT 0x20 |
#define CLIP_USER_BIT 0x40 |
#define CLIP_ALL_BITS 0x3f |
typedef GLvector4f * (_XFORMAPIP clip_func)( GLvector4f *vClip, |
GLvector4f *vProj, |
GLubyte clipMask[], |
GLubyte *orMask, |
GLubyte *andMask ); |
typedef void (*dotprod_func)( GLfloat *out, |
GLuint out_stride, |
CONST GLvector4f *coord_vec, |
CONST GLfloat plane[4] ); |
typedef void (*vec_copy_func)( GLvector4f *to, |
CONST GLvector4f *from ); |
/* |
* Functions for transformation of normals in the VB. |
*/ |
typedef void (_NORMAPIP normal_func)( CONST GLmatrix *mat, |
GLfloat scale, |
CONST GLvector4f *in, |
CONST GLfloat lengths[], |
GLvector4f *dest ); |
/* Flags for selecting a normal transformation function. |
*/ |
#define NORM_RESCALE 0x1 /* apply the scale factor */ |
#define NORM_NORMALIZE 0x2 /* normalize */ |
#define NORM_TRANSFORM 0x4 /* apply the transformation matrix */ |
#define NORM_TRANSFORM_NO_ROT 0x8 /* apply the transformation matrix */ |
/* KW: New versions of the transform function allow a mask array |
* specifying that individual vector transform should be skipped |
* when the mask byte is zero. This is always present as a |
* parameter, to allow a unified interface. |
*/ |
typedef void (_XFORMAPIP transform_func)( GLvector4f *to_vec, |
CONST GLfloat m[16], |
CONST GLvector4f *from_vec ); |
extern GLvector4f *_mesa_project_points( GLvector4f *to, |
CONST GLvector4f *from ); |
extern void _mesa_transform_bounds3( GLubyte *orMask, GLubyte *andMask, |
CONST GLfloat m[16], |
CONST GLfloat src[][3] ); |
extern void _mesa_transform_bounds2( GLubyte *orMask, GLubyte *andMask, |
CONST GLfloat m[16], |
CONST GLfloat src[][3] ); |
extern dotprod_func _mesa_dotprod_tab[5]; |
extern vec_copy_func _mesa_copy_tab[0x10]; |
extern vec_copy_func _mesa_copy_clean_tab[5]; |
extern clip_func _mesa_clip_tab[5]; |
extern clip_func _mesa_clip_np_tab[5]; |
extern normal_func _mesa_normal_tab[0xf]; |
/* Use of 2 layers of linked 1-dimensional arrays to reduce |
* cost of lookup. |
*/ |
extern transform_func *_mesa_transform_tab[5]; |
extern void _mesa_transform_point_sz( GLfloat Q[4], CONST GLfloat M[16], |
CONST GLfloat P[4], GLuint sz ); |
#define TransformRaw( to, mat, from ) \ |
( _mesa_transform_tab[(from)->size][(mat)->type]( to, (mat)->m, from ), \ |
(to) ) |
#endif |
/shark/trunk/ports/mesa/src/math/m_debug_xform.c |
---|
0,0 → 1,335 |
/* $Id: m_debug_xform.c,v 1.1 2003-02-28 11:48:05 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 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. |
*/ |
/* |
* Updated for P6 architecture by Gareth Hughes. |
*/ |
#include "glheader.h" |
#include "context.h" |
#include "macros.h" |
#include "imports.h" |
#include "m_matrix.h" |
#include "m_xform.h" |
#include "m_debug.h" |
#include "m_debug_util.h" |
#ifdef DEBUG /* This code only used for debugging */ |
/* Overhead of profiling counter in cycles. Automatically adjusted to |
* your machine at run time - counter initialization should give very |
* consistent results. |
*/ |
long counter_overhead = 0; |
/* This is the value of the environment variable MESA_PROFILE, and is |
* used to determine if we should benchmark the functions as well as |
* verify their correctness. |
*/ |
char *mesa_profile = NULL; |
static int m_general[16] = { |
VAR, VAR, VAR, VAR, |
VAR, VAR, VAR, VAR, |
VAR, VAR, VAR, VAR, |
VAR, VAR, VAR, VAR |
}; |
static int m_identity[16] = { |
ONE, NIL, NIL, NIL, |
NIL, ONE, NIL, NIL, |
NIL, NIL, ONE, NIL, |
NIL, NIL, NIL, ONE |
}; |
static int m_2d[16] = { |
VAR, VAR, NIL, VAR, |
VAR, VAR, NIL, VAR, |
NIL, NIL, ONE, NIL, |
NIL, NIL, NIL, ONE |
}; |
static int m_2d_no_rot[16] = { |
VAR, NIL, NIL, VAR, |
NIL, VAR, NIL, VAR, |
NIL, NIL, ONE, NIL, |
NIL, NIL, NIL, ONE |
}; |
static int m_3d[16] = { |
VAR, VAR, VAR, VAR, |
VAR, VAR, VAR, VAR, |
VAR, VAR, VAR, VAR, |
NIL, NIL, NIL, ONE |
}; |
static int m_3d_no_rot[16] = { |
VAR, NIL, NIL, VAR, |
NIL, VAR, NIL, VAR, |
NIL, NIL, VAR, VAR, |
NIL, NIL, NIL, ONE |
}; |
static int m_perspective[16] = { |
VAR, NIL, VAR, NIL, |
NIL, VAR, VAR, NIL, |
NIL, NIL, VAR, VAR, |
NIL, NIL, NEG, NIL |
}; |
static int *templates[7] = { |
m_general, |
m_identity, |
m_3d_no_rot, |
m_perspective, |
m_2d, |
m_2d_no_rot, |
m_3d |
}; |
static int mtypes[7] = { |
MATRIX_GENERAL, |
MATRIX_IDENTITY, |
MATRIX_3D_NO_ROT, |
MATRIX_PERSPECTIVE, |
MATRIX_2D, |
MATRIX_2D_NO_ROT, |
MATRIX_3D |
}; |
static char *mstrings[7] = { |
"MATRIX_GENERAL", |
"MATRIX_IDENTITY", |
"MATRIX_3D_NO_ROT", |
"MATRIX_PERSPECTIVE", |
"MATRIX_2D", |
"MATRIX_2D_NO_ROT", |
"MATRIX_3D" |
}; |
/* ============================================================= |
* Reference transformations |
*/ |
static void ref_transform( GLvector4f *dst, |
const GLmatrix *mat, |
const GLvector4f *src ) |
{ |
GLuint i; |
GLfloat *s = (GLfloat *)src->start; |
GLfloat (*d)[4] = (GLfloat (*)[4])dst->start; |
const GLfloat *m = mat->m; |
for ( i = 0 ; i < src->count ; i++ ) { |
TRANSFORM_POINT( d[i], m, s ); |
s = (GLfloat *)((char *)s + src->stride); |
} |
} |
/* ============================================================= |
* Vertex transformation tests |
*/ |
static void init_matrix( GLfloat *m ) |
{ |
m[0] = 63.0; m[4] = 43.0; m[ 8] = 29.0; m[12] = 43.0; |
m[1] = 55.0; m[5] = 17.0; m[ 9] = 31.0; m[13] = 7.0; |
m[2] = 44.0; m[6] = 9.0; m[10] = 7.0; m[14] = 3.0; |
m[3] = 11.0; m[7] = 23.0; m[11] = 91.0; m[15] = 9.0; |
} |
static GLfloat s[TEST_COUNT][4] ALIGN16; |
static GLfloat d[TEST_COUNT][4] ALIGN16; |
static GLfloat r[TEST_COUNT][4] ALIGN16; |
static int test_transform_function( transform_func func, int psize, |
int mtype, long *cycles ) |
{ |
GLvector4f source[1], dest[1], ref[1]; |
GLmatrix mat[1]; |
GLfloat *m; |
int i, j; |
#ifdef RUN_DEBUG_BENCHMARK |
int cycle_i; /* the counter for the benchmarks we run */ |
#endif |
(void) cycles; |
if ( psize > 4 ) { |
_mesa_problem( NULL, "test_transform_function called with psize > 4\n" ); |
return 0; |
} |
mat->m = (GLfloat *) ALIGN_MALLOC( 16 * sizeof(GLfloat), 16 ); |
mat->type = mtypes[mtype]; |
m = mat->m; |
ASSERT( ((GLuint)m & 15) == 0 ); |
init_matrix( m ); |
for ( i = 0 ; i < 4 ; i++ ) { |
for ( j = 0 ; j < 4 ; j++ ) { |
switch ( templates[mtype][i * 4 + j] ) { |
case NIL: |
m[j * 4 + i] = 0.0; |
break; |
case ONE: |
m[j * 4 + i] = 1.0; |
break; |
case NEG: |
m[j * 4 + i] = -1.0; |
break; |
case VAR: |
break; |
default: |
abort(); |
} |
} |
} |
for ( i = 0 ; i < TEST_COUNT ; i++) { |
ASSIGN_4V( d[i], 0.0, 0.0, 0.0, 1.0 ); |
ASSIGN_4V( s[i], 0.0, 0.0, 0.0, 1.0 ); |
for ( j = 0 ; j < psize ; j++ ) |
s[i][j] = rnd(); |
} |
source->data = (GLfloat(*)[4])s; |
source->start = (GLfloat *)s; |
source->count = TEST_COUNT; |
source->stride = sizeof(s[0]); |
source->size = 4; |
source->flags = 0; |
dest->data = (GLfloat(*)[4])d; |
dest->start = (GLfloat *)d; |
dest->count = TEST_COUNT; |
dest->stride = sizeof(float[4]); |
dest->size = 0; |
dest->flags = 0; |
ref->data = (GLfloat(*)[4])r; |
ref->start = (GLfloat *)r; |
ref->count = TEST_COUNT; |
ref->stride = sizeof(float[4]); |
ref->size = 0; |
ref->flags = 0; |
ref_transform( ref, mat, source ); |
if ( mesa_profile ) { |
BEGIN_RACE( *cycles ); |
func( dest, mat->m, source ); |
END_RACE( *cycles ); |
} |
else { |
func( dest, mat->m, source ); |
} |
for ( i = 0 ; i < TEST_COUNT ; i++ ) { |
for ( j = 0 ; j < 4 ; j++ ) { |
if ( significand_match( d[i][j], r[i][j] ) < REQUIRED_PRECISION ) { |
_mesa_printf(NULL, "-----------------------------\n" ); |
_mesa_printf(NULL, "(i = %i, j = %i)\n", i, j ); |
_mesa_printf(NULL, "%f \t %f \t [diff = %e - %i bit missed]\n", |
d[i][0], r[i][0], r[i][0]-d[i][0], |
MAX_PRECISION - significand_match( d[i][0], r[i][0] ) ); |
_mesa_printf(NULL, "%f \t %f \t [diff = %e - %i bit missed]\n", |
d[i][1], r[i][1], r[i][1]-d[i][1], |
MAX_PRECISION - significand_match( d[i][1], r[i][1] ) ); |
_mesa_printf(NULL, "%f \t %f \t [diff = %e - %i bit missed]\n", |
d[i][2], r[i][2], r[i][2]-d[i][2], |
MAX_PRECISION - significand_match( d[i][2], r[i][2] ) ); |
_mesa_printf(NULL, "%f \t %f \t [diff = %e - %i bit missed]\n", |
d[i][3], r[i][3], r[i][3]-d[i][3], |
MAX_PRECISION - significand_match( d[i][3], r[i][3] ) ); |
return 0; |
} |
} |
} |
ALIGN_FREE( mat->m ); |
return 1; |
} |
void _math_test_all_transform_functions( char *description ) |
{ |
int psize, mtype; |
long benchmark_tab[4][7]; |
static int first_time = 1; |
if ( first_time ) { |
first_time = 0; |
mesa_profile = getenv( "MESA_PROFILE" ); |
} |
#ifdef RUN_DEBUG_BENCHMARK |
if ( mesa_profile ) { |
if ( !counter_overhead ) { |
INIT_COUNTER(); |
_mesa_printf(NULL, "counter overhead: %ld cycles\n\n", counter_overhead ); |
} |
_mesa_printf(NULL, "transform results after hooking in %s functions:\n", description ); |
} |
#endif |
#ifdef RUN_DEBUG_BENCHMARK |
if ( mesa_profile ) { |
_mesa_printf(NULL, "\n" ); |
for ( psize = 1 ; psize <= 4 ; psize++ ) { |
_mesa_printf(NULL, " p%d\t", psize ); |
} |
_mesa_printf(NULL, "\n--------------------------------------------------------\n" ); |
} |
#endif |
for ( mtype = 0 ; mtype < 7 ; mtype++ ) { |
for ( psize = 1 ; psize <= 4 ; psize++ ) { |
transform_func func = _mesa_transform_tab[psize][mtypes[mtype]]; |
long *cycles = &(benchmark_tab[psize-1][mtype]); |
if ( test_transform_function( func, psize, mtype, cycles ) == 0 ) { |
char buf[100]; |
_mesa_sprintf(NULL, buf, "_mesa_transform_tab[0][%d][%s] failed test (%s)", |
psize, mstrings[mtype], description ); |
_mesa_problem( NULL, buf ); |
} |
#ifdef RUN_DEBUG_BENCHMARK |
if ( mesa_profile ) |
_mesa_printf(NULL, " %li\t", benchmark_tab[psize-1][mtype] ); |
#endif |
} |
#ifdef RUN_DEBUG_BENCHMARK |
if ( mesa_profile ) |
_mesa_printf(NULL, " | [%s]\n", mstrings[mtype] ); |
#endif |
} |
#ifdef RUN_DEBUG_BENCHMARK |
if ( mesa_profile ) |
_mesa_printf(NULL, "\n" ); |
#endif |
} |
#endif /* DEBUG */ |
/shark/trunk/ports/mesa/src/math/m_vector.c |
---|
0,0 → 1,430 |
/* $Id: m_vector.c,v 1.1 2003-02-28 11:48:05 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 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. |
*/ |
/* |
* New (3.1) transformation code written by Keith Whitwell. |
*/ |
#include "glheader.h" |
#include "imports.h" |
#include "macros.h" |
#include "imports.h" |
#include "m_vector.h" |
/* |
* Given a vector [count][4] of floats, set all the [][elt] values |
* to 0 (if elt = 0, 1, 2) or 1.0 (if elt = 3). |
*/ |
void _mesa_vector4f_clean_elem( GLvector4f *vec, GLuint count, GLuint elt ) |
{ |
static const GLubyte elem_bits[4] = { |
VEC_DIRTY_0, |
VEC_DIRTY_1, |
VEC_DIRTY_2, |
VEC_DIRTY_3 |
}; |
static const GLfloat clean[4] = { 0, 0, 0, 1 }; |
const GLfloat v = clean[elt]; |
GLfloat (*data)[4] = (GLfloat (*)[4])vec->start; |
GLuint i; |
for (i = 0 ; i < count ; i++) |
data[i][elt] = v; |
vec->flags &= ~elem_bits[elt]; |
} |
static const GLubyte size_bits[5] = { |
0, |
VEC_SIZE_1, |
VEC_SIZE_2, |
VEC_SIZE_3, |
VEC_SIZE_4, |
}; |
/* |
* Initialize GLvector objects. |
* Input: v - the vector object to initialize. |
* flags - bitwise-OR of VEC_* flags |
* storage - pointer to storage for the vector's data |
*/ |
void _mesa_vector4f_init( GLvector4f *v, GLuint flags, GLfloat (*storage)[4] ) |
{ |
v->stride = 4 * sizeof(GLfloat); |
v->size = 2; /* may change: 2-4 for vertices and 1-4 for texcoords */ |
v->data = storage; |
v->start = (GLfloat *) storage; |
v->count = 0; |
v->flags = size_bits[4] | flags ; |
} |
void _mesa_vector3f_init( GLvector3f *v, GLuint flags, GLfloat (*storage)[3] ) |
{ |
v->stride = 3 * sizeof(GLfloat); |
v->data = storage; |
v->start = (GLfloat *) storage; |
v->count = 0; |
v->flags = flags ; |
} |
void _mesa_vector1f_init( GLvector1f *v, GLuint flags, GLfloat *storage ) |
{ |
v->stride = 1*sizeof(GLfloat); |
v->data = storage; |
v->start = (GLfloat *)storage; |
v->count = 0; |
v->flags = flags ; |
} |
void _mesa_vector4ub_init( GLvector4ub *v, GLuint flags, GLubyte (*storage)[4] ) |
{ |
v->stride = 4 * sizeof(GLubyte); |
v->data = storage; |
v->start = (GLubyte *) storage; |
v->count = 0; |
v->flags = flags ; |
} |
void _mesa_vector4chan_init( GLvector4chan *v, GLuint flags, GLchan (*storage)[4] ) |
{ |
v->stride = 4 * sizeof(GLchan); |
v->data = storage; |
v->start = (GLchan *) storage; |
v->count = 0; |
v->flags = flags ; |
} |
void _mesa_vector4us_init( GLvector4us *v, GLuint flags, GLushort (*storage)[4] ) |
{ |
v->stride = 4 * sizeof(GLushort); |
v->data = storage; |
v->start = (GLushort *) storage; |
v->count = 0; |
v->flags = flags ; |
} |
void _mesa_vector1ub_init( GLvector1ub *v, GLuint flags, GLubyte *storage ) |
{ |
v->stride = 1 * sizeof(GLubyte); |
v->data = storage; |
v->start = (GLubyte *) storage; |
v->count = 0; |
v->flags = flags ; |
} |
void _mesa_vector1ui_init( GLvector1ui *v, GLuint flags, GLuint *storage ) |
{ |
v->stride = 1 * sizeof(GLuint); |
v->data = storage; |
v->start = (GLuint *) storage; |
v->count = 0; |
v->flags = flags ; |
} |
/* |
* Initialize GLvector objects and allocate storage. |
* Input: v - the vector object |
* sz - unused???? |
* flags - bitwise-OR of VEC_* flags |
* count - number of elements to allocate in vector |
* alignment - desired memory alignment for the data (in bytes) |
*/ |
void _mesa_vector4f_alloc( GLvector4f *v, GLuint flags, GLuint count, |
GLuint alignment ) |
{ |
v->stride = 4 * sizeof(GLfloat); |
v->size = 2; |
v->storage = ALIGN_MALLOC( count * 4 * sizeof(GLfloat), alignment ); |
v->start = (GLfloat *) v->storage; |
v->data = (GLfloat (*)[4]) v->storage; |
v->count = 0; |
v->flags = size_bits[4] | flags | VEC_MALLOC ; |
} |
void _mesa_vector3f_alloc( GLvector3f *v, GLuint flags, GLuint count, |
GLuint alignment ) |
{ |
v->stride = 3 * sizeof(GLfloat); |
v->storage = ALIGN_MALLOC( count * 3 * sizeof(GLfloat), alignment ); |
v->start = (GLfloat *) v->storage; |
v->data = (GLfloat (*)[3]) v->storage; |
v->count = 0; |
v->flags = flags | VEC_MALLOC ; |
} |
void _mesa_vector1f_alloc( GLvector1f *v, GLuint flags, GLuint count, |
GLuint alignment ) |
{ |
v->stride = sizeof(GLfloat); |
v->storage = v->start = (GLfloat *) |
ALIGN_MALLOC( count * sizeof(GLfloat), alignment ); |
v->data = v->start; |
v->count = 0; |
v->flags = flags | VEC_MALLOC ; |
} |
void _mesa_vector4ub_alloc( GLvector4ub *v, GLuint flags, GLuint count, |
GLuint alignment ) |
{ |
v->stride = 4 * sizeof(GLubyte); |
v->storage = ALIGN_MALLOC( count * 4 * sizeof(GLubyte), alignment ); |
v->start = (GLubyte *) v->storage; |
v->data = (GLubyte (*)[4]) v->storage; |
v->count = 0; |
v->flags = flags | VEC_MALLOC ; |
} |
void _mesa_vector4chan_alloc( GLvector4chan *v, GLuint flags, GLuint count, |
GLuint alignment ) |
{ |
v->stride = 4 * sizeof(GLchan); |
v->storage = ALIGN_MALLOC( count * 4 * sizeof(GLchan), alignment ); |
v->start = (GLchan *) v->storage; |
v->data = (GLchan (*)[4]) v->storage; |
v->count = 0; |
v->flags = flags | VEC_MALLOC ; |
} |
void _mesa_vector4us_alloc( GLvector4us *v, GLuint flags, GLuint count, |
GLuint alignment ) |
{ |
v->stride = 4 * sizeof(GLushort); |
v->storage = ALIGN_MALLOC( count * 4 * sizeof(GLushort), alignment ); |
v->start = (GLushort *) v->storage; |
v->data = (GLushort (*)[4]) v->storage; |
v->count = 0; |
v->flags = flags | VEC_MALLOC ; |
} |
void _mesa_vector1ub_alloc( GLvector1ub *v, GLuint flags, GLuint count, |
GLuint alignment ) |
{ |
v->stride = 1 * sizeof(GLubyte); |
v->storage = ALIGN_MALLOC( count * sizeof(GLubyte), alignment ); |
v->start = (GLubyte *) v->storage; |
v->data = (GLubyte *) v->storage; |
v->count = 0; |
v->flags = flags | VEC_MALLOC ; |
} |
void _mesa_vector1ui_alloc( GLvector1ui *v, GLuint flags, GLuint count, |
GLuint alignment ) |
{ |
v->stride = 1 * sizeof(GLuint); |
v->storage = ALIGN_MALLOC( count * sizeof(GLuint), alignment ); |
v->start = (GLuint *) v->storage; |
v->data = (GLuint *) v->storage; |
v->count = 0; |
v->flags = flags | VEC_MALLOC ; |
} |
/* |
* Vector deallocation. Free whatever memory is pointed to by the |
* vector's storage field if the VEC_MALLOC flag is set. |
* DO NOT free the GLvector object itself, though. |
*/ |
void _mesa_vector4f_free( GLvector4f *v ) |
{ |
if (v->flags & VEC_MALLOC) { |
ALIGN_FREE( v->storage ); |
v->data = NULL; |
v->start = NULL; |
v->storage = NULL; |
v->flags &= ~VEC_MALLOC; |
} |
} |
void _mesa_vector3f_free( GLvector3f *v ) |
{ |
if (v->flags & VEC_MALLOC) { |
ALIGN_FREE( v->storage ); |
v->data = 0; |
v->start = 0; |
v->storage = 0; |
v->flags &= ~VEC_MALLOC; |
} |
} |
void _mesa_vector1f_free( GLvector1f *v ) |
{ |
if (v->flags & VEC_MALLOC) { |
ALIGN_FREE( v->storage ); |
v->data = NULL; |
v->start = NULL; |
v->storage = NULL; |
v->flags &= ~VEC_MALLOC; |
} |
} |
void _mesa_vector4ub_free( GLvector4ub *v ) |
{ |
if (v->flags & VEC_MALLOC) { |
ALIGN_FREE( v->storage ); |
v->data = NULL; |
v->start = NULL; |
v->storage = NULL; |
v->flags &= ~VEC_MALLOC; |
} |
} |
void _mesa_vector4chan_free( GLvector4chan *v ) |
{ |
if (v->flags & VEC_MALLOC) { |
ALIGN_FREE( v->storage ); |
v->data = NULL; |
v->start = NULL; |
v->storage = NULL; |
v->flags &= ~VEC_MALLOC; |
} |
} |
void _mesa_vector4us_free( GLvector4us *v ) |
{ |
if (v->flags & VEC_MALLOC) { |
ALIGN_FREE( v->storage ); |
v->data = NULL; |
v->start = NULL; |
v->storage = NULL; |
v->flags &= ~VEC_MALLOC; |
} |
} |
void _mesa_vector1ub_free( GLvector1ub *v ) |
{ |
if (v->flags & VEC_MALLOC) { |
ALIGN_FREE( v->storage ); |
v->data = NULL; |
v->start = NULL; |
v->storage = NULL; |
v->flags &= ~VEC_MALLOC; |
} |
} |
void _mesa_vector1ui_free( GLvector1ui *v ) |
{ |
if (v->flags & VEC_MALLOC) { |
ALIGN_FREE( v->storage ); |
v->data = NULL; |
v->start = NULL; |
v->storage = NULL; |
v->flags &= ~VEC_MALLOC; |
} |
} |
/* |
* For debugging |
*/ |
void _mesa_vector4f_print( GLvector4f *v, GLubyte *cullmask, GLboolean culling ) |
{ |
GLfloat c[4] = { 0, 0, 0, 1 }; |
const char *templates[5] = { |
"%d:\t0, 0, 0, 1\n", |
"%d:\t%f, 0, 0, 1\n", |
"%d:\t%f, %f, 0, 1\n", |
"%d:\t%f, %f, %f, 1\n", |
"%d:\t%f, %f, %f, %f\n" |
}; |
const char *t = templates[v->size]; |
GLfloat *d = (GLfloat *)v->data; |
GLuint j, i = 0, count; |
_mesa_printf(NULL, "data-start\n"); |
for ( ; d != v->start ; STRIDE_F(d, v->stride), i++) |
_mesa_printf(NULL, t, i, d[0], d[1], d[2], d[3]); |
_mesa_printf(NULL, "start-count(%u)\n", v->count); |
count = i + v->count; |
if (culling) { |
for ( ; i < count ; STRIDE_F(d, v->stride), i++) |
if (cullmask[i]) |
_mesa_printf(NULL, t, i, d[0], d[1], d[2], d[3]); |
} |
else { |
for ( ; i < count ; STRIDE_F(d, v->stride), i++) |
_mesa_printf(NULL, t, i, d[0], d[1], d[2], d[3]); |
} |
for (j = v->size ; j < 4; j++) { |
if ((v->flags & (1<<j)) == 0) { |
_mesa_printf(NULL, "checking col %u is clean as advertised ", j); |
for (i = 0, d = (GLfloat *) v->data ; |
i < count && d[j] == c[j] ; |
i++, STRIDE_F(d, v->stride)) {}; |
if (i == count) |
_mesa_printf(NULL, " --> ok\n"); |
else |
_mesa_printf(NULL, " --> Failed at %u ******\n", i); |
} |
} |
} |
/* |
* For debugging |
*/ |
void _mesa_vector3f_print( GLvector3f *v, GLubyte *cullmask, GLboolean culling ) |
{ |
GLfloat *d = (GLfloat *)v->data; |
GLuint i = 0, count; |
_mesa_printf(NULL, "data-start\n"); |
for ( ; d != v->start ; STRIDE_F(d,v->stride), i++) |
_mesa_printf(NULL, "%u:\t%f, %f, %f\n", i, d[0], d[1], d[2]); |
_mesa_printf(NULL, "start-count(%u)\n", v->count); |
count = i + v->count; |
if (culling) { |
for ( ; i < count ; STRIDE_F(d,v->stride), i++) |
if (cullmask[i]) |
_mesa_printf(NULL, "%u:\t%f, %f, %f\n", i, d[0], d[1], d[2]); |
} |
else { |
for ( ; i < count ; STRIDE_F(d,v->stride), i++) |
_mesa_printf(NULL, "%u:\t%f, %f, %f\n", i, d[0], d[1], d[2]); |
} |
} |
/shark/trunk/ports/mesa/src/math/m_translate.h |
---|
0,0 → 1,99 |
/* $Id: m_translate.h,v 1.1 2003-02-28 11:48:05 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 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. |
*/ |
#ifndef _M_TRANSLATE_H_ |
#define _M_TRANSLATE_H_ |
#include "config.h" |
#include "mtypes.h" /* hack for GLchan */ |
extern void _math_trans_1f(GLfloat *to, |
CONST void *ptr, |
GLuint stride, |
GLenum type, |
GLuint start, |
GLuint n ); |
extern void _math_trans_1ui(GLuint *to, |
CONST void *ptr, |
GLuint stride, |
GLenum type, |
GLuint start, |
GLuint n ); |
extern void _math_trans_1ub(GLubyte *to, |
CONST void *ptr, |
GLuint stride, |
GLenum type, |
GLuint start, |
GLuint n ); |
extern void _math_trans_4ub(GLubyte (*to)[4], |
CONST void *ptr, |
GLuint stride, |
GLenum type, |
GLuint size, |
GLuint start, |
GLuint n ); |
extern void _math_trans_4chan( GLchan (*to)[4], |
CONST void *ptr, |
GLuint stride, |
GLenum type, |
GLuint size, |
GLuint start, |
GLuint n ); |
extern void _math_trans_4us(GLushort (*to)[4], |
CONST void *ptr, |
GLuint stride, |
GLenum type, |
GLuint size, |
GLuint start, |
GLuint n ); |
extern void _math_trans_4f(GLfloat (*to)[4], |
CONST void *ptr, |
GLuint stride, |
GLenum type, |
GLuint size, |
GLuint start, |
GLuint n ); |
extern void _math_trans_3f(GLfloat (*to)[3], |
CONST void *ptr, |
GLuint stride, |
GLenum type, |
GLuint start, |
GLuint n ); |
extern void _math_init_translate( void ); |
#endif |
/shark/trunk/ports/mesa/src/math/m_matrix.c |
---|
0,0 → 1,1181 |
/* $Id: m_matrix.c,v 1.1 2003-02-28 11:48:05 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. |
*/ |
/* |
* Matrix operations |
* |
* NOTES: |
* 1. 4x4 transformation matrices are stored in memory in column major order. |
* 2. Points/vertices are to be thought of as column vectors. |
* 3. Transformation of a point p by a matrix M is: p' = M * p |
*/ |
#include "glheader.h" |
#include "imports.h" |
#include "macros.h" |
#include "imports.h" |
#include "mmath.h" |
#include "m_matrix.h" |
static const char *types[] = { |
"MATRIX_GENERAL", |
"MATRIX_IDENTITY", |
"MATRIX_3D_NO_ROT", |
"MATRIX_PERSPECTIVE", |
"MATRIX_2D", |
"MATRIX_2D_NO_ROT", |
"MATRIX_3D" |
}; |
static GLfloat Identity[16] = { |
1.0, 0.0, 0.0, 0.0, |
0.0, 1.0, 0.0, 0.0, |
0.0, 0.0, 1.0, 0.0, |
0.0, 0.0, 0.0, 1.0 |
}; |
/* |
* This matmul was contributed by Thomas Malik |
* |
* Perform a 4x4 matrix multiplication (product = a x b). |
* Input: a, b - matrices to multiply |
* Output: product - product of a and b |
* WARNING: (product != b) assumed |
* NOTE: (product == a) allowed |
* |
* KW: 4*16 = 64 muls |
*/ |
#define A(row,col) a[(col<<2)+row] |
#define B(row,col) b[(col<<2)+row] |
#define P(row,col) product[(col<<2)+row] |
static void matmul4( GLfloat *product, const GLfloat *a, const GLfloat *b ) |
{ |
GLint i; |
for (i = 0; i < 4; i++) { |
const GLfloat ai0=A(i,0), ai1=A(i,1), ai2=A(i,2), ai3=A(i,3); |
P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0) + ai3 * B(3,0); |
P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1) + ai3 * B(3,1); |
P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2) + ai3 * B(3,2); |
P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3 * B(3,3); |
} |
} |
/* Multiply two matrices known to occupy only the top three rows, such |
* as typical model matrices, and ortho matrices. |
*/ |
static void matmul34( GLfloat *product, const GLfloat *a, const GLfloat *b ) |
{ |
GLint i; |
for (i = 0; i < 3; i++) { |
const GLfloat ai0=A(i,0), ai1=A(i,1), ai2=A(i,2), ai3=A(i,3); |
P(i,0) = ai0 * B(0,0) + ai1 * B(1,0) + ai2 * B(2,0); |
P(i,1) = ai0 * B(0,1) + ai1 * B(1,1) + ai2 * B(2,1); |
P(i,2) = ai0 * B(0,2) + ai1 * B(1,2) + ai2 * B(2,2); |
P(i,3) = ai0 * B(0,3) + ai1 * B(1,3) + ai2 * B(2,3) + ai3; |
} |
P(3,0) = 0; |
P(3,1) = 0; |
P(3,2) = 0; |
P(3,3) = 1; |
} |
#undef A |
#undef B |
#undef P |
/* |
* Multiply a matrix by an array of floats with known properties. |
*/ |
static void matrix_multf( GLmatrix *mat, const GLfloat *m, GLuint flags ) |
{ |
mat->flags |= (flags | MAT_DIRTY_TYPE | MAT_DIRTY_INVERSE); |
if (TEST_MAT_FLAGS(mat, MAT_FLAGS_3D)) |
matmul34( mat->m, mat->m, m ); |
else |
matmul4( mat->m, mat->m, m ); |
} |
static void print_matrix_floats( const GLfloat m[16] ) |
{ |
int i; |
for (i=0;i<4;i++) { |
_mesa_debug(NULL,"\t%f %f %f %f\n", m[i], m[4+i], m[8+i], m[12+i] ); |
} |
} |
void |
_math_matrix_print( const GLmatrix *m ) |
{ |
_mesa_debug(NULL, "Matrix type: %s, flags: %x\n", types[m->type], m->flags); |
print_matrix_floats(m->m); |
_mesa_debug(NULL, "Inverse: \n"); |
if (m->inv) { |
GLfloat prod[16]; |
print_matrix_floats(m->inv); |
matmul4(prod, m->m, m->inv); |
_mesa_debug(NULL, "Mat * Inverse:\n"); |
print_matrix_floats(prod); |
} |
else { |
_mesa_debug(NULL, " - not available\n"); |
} |
} |
#define SWAP_ROWS(a, b) { GLfloat *_tmp = a; (a)=(b); (b)=_tmp; } |
#define MAT(m,r,c) (m)[(c)*4+(r)] |
/* |
* Compute inverse of 4x4 transformation matrix. |
* Code contributed by Jacques Leroy jle@star.be |
* Return GL_TRUE for success, GL_FALSE for failure (singular matrix) |
*/ |
static GLboolean invert_matrix_general( GLmatrix *mat ) |
{ |
const GLfloat *m = mat->m; |
GLfloat *out = mat->inv; |
GLfloat wtmp[4][8]; |
GLfloat m0, m1, m2, m3, s; |
GLfloat *r0, *r1, *r2, *r3; |
r0 = wtmp[0], r1 = wtmp[1], r2 = wtmp[2], r3 = wtmp[3]; |
r0[0] = MAT(m,0,0), r0[1] = MAT(m,0,1), |
r0[2] = MAT(m,0,2), r0[3] = MAT(m,0,3), |
r0[4] = 1.0, r0[5] = r0[6] = r0[7] = 0.0, |
r1[0] = MAT(m,1,0), r1[1] = MAT(m,1,1), |
r1[2] = MAT(m,1,2), r1[3] = MAT(m,1,3), |
r1[5] = 1.0, r1[4] = r1[6] = r1[7] = 0.0, |
r2[0] = MAT(m,2,0), r2[1] = MAT(m,2,1), |
r2[2] = MAT(m,2,2), r2[3] = MAT(m,2,3), |
r2[6] = 1.0, r2[4] = r2[5] = r2[7] = 0.0, |
r3[0] = MAT(m,3,0), r3[1] = MAT(m,3,1), |
r3[2] = MAT(m,3,2), r3[3] = MAT(m,3,3), |
r3[7] = 1.0, r3[4] = r3[5] = r3[6] = 0.0; |
/* choose pivot - or die */ |
if (fabs(r3[0])>fabs(r2[0])) SWAP_ROWS(r3, r2); |
if (fabs(r2[0])>fabs(r1[0])) SWAP_ROWS(r2, r1); |
if (fabs(r1[0])>fabs(r0[0])) SWAP_ROWS(r1, r0); |
if (0.0 == r0[0]) return GL_FALSE; |
/* eliminate first variable */ |
m1 = r1[0]/r0[0]; m2 = r2[0]/r0[0]; m3 = r3[0]/r0[0]; |
s = r0[1]; r1[1] -= m1 * s; r2[1] -= m2 * s; r3[1] -= m3 * s; |
s = r0[2]; r1[2] -= m1 * s; r2[2] -= m2 * s; r3[2] -= m3 * s; |
s = r0[3]; r1[3] -= m1 * s; r2[3] -= m2 * s; r3[3] -= m3 * s; |
s = r0[4]; |
if (s != 0.0) { r1[4] -= m1 * s; r2[4] -= m2 * s; r3[4] -= m3 * s; } |
s = r0[5]; |
if (s != 0.0) { r1[5] -= m1 * s; r2[5] -= m2 * s; r3[5] -= m3 * s; } |
s = r0[6]; |
if (s != 0.0) { r1[6] -= m1 * s; r2[6] -= m2 * s; r3[6] -= m3 * s; } |
s = r0[7]; |
if (s != 0.0) { r1[7] -= m1 * s; r2[7] -= m2 * s; r3[7] -= m3 * s; } |
/* choose pivot - or die */ |
if (fabs(r3[1])>fabs(r2[1])) SWAP_ROWS(r3, r2); |
if (fabs(r2[1])>fabs(r1[1])) SWAP_ROWS(r2, r1); |
if (0.0 == r1[1]) return GL_FALSE; |
/* eliminate second variable */ |
m2 = r2[1]/r1[1]; m3 = r3[1]/r1[1]; |
r2[2] -= m2 * r1[2]; r3[2] -= m3 * r1[2]; |
r2[3] -= m2 * r1[3]; r3[3] -= m3 * r1[3]; |
s = r1[4]; if (0.0 != s) { r2[4] -= m2 * s; r3[4] -= m3 * s; } |
s = r1[5]; if (0.0 != s) { r2[5] -= m2 * s; r3[5] -= m3 * s; } |
s = r1[6]; if (0.0 != s) { r2[6] -= m2 * s; r3[6] -= m3 * s; } |
s = r1[7]; if (0.0 != s) { r2[7] -= m2 * s; r3[7] -= m3 * s; } |
/* choose pivot - or die */ |
if (fabs(r3[2])>fabs(r2[2])) SWAP_ROWS(r3, r2); |
if (0.0 == r2[2]) return GL_FALSE; |
/* eliminate third variable */ |
m3 = r3[2]/r2[2]; |
r3[3] -= m3 * r2[3], r3[4] -= m3 * r2[4], |
r3[5] -= m3 * r2[5], r3[6] -= m3 * r2[6], |
r3[7] -= m3 * r2[7]; |
/* last check */ |
if (0.0 == r3[3]) return GL_FALSE; |
s = 1.0F/r3[3]; /* now back substitute row 3 */ |
r3[4] *= s; r3[5] *= s; r3[6] *= s; r3[7] *= s; |
m2 = r2[3]; /* now back substitute row 2 */ |
s = 1.0F/r2[2]; |
r2[4] = s * (r2[4] - r3[4] * m2), r2[5] = s * (r2[5] - r3[5] * m2), |
r2[6] = s * (r2[6] - r3[6] * m2), r2[7] = s * (r2[7] - r3[7] * m2); |
m1 = r1[3]; |
r1[4] -= r3[4] * m1, r1[5] -= r3[5] * m1, |
r1[6] -= r3[6] * m1, r1[7] -= r3[7] * m1; |
m0 = r0[3]; |
r0[4] -= r3[4] * m0, r0[5] -= r3[5] * m0, |
r0[6] -= r3[6] * m0, r0[7] -= r3[7] * m0; |
m1 = r1[2]; /* now back substitute row 1 */ |
s = 1.0F/r1[1]; |
r1[4] = s * (r1[4] - r2[4] * m1), r1[5] = s * (r1[5] - r2[5] * m1), |
r1[6] = s * (r1[6] - r2[6] * m1), r1[7] = s * (r1[7] - r2[7] * m1); |
m0 = r0[2]; |
r0[4] -= r2[4] * m0, r0[5] -= r2[5] * m0, |
r0[6] -= r2[6] * m0, r0[7] -= r2[7] * m0; |
m0 = r0[1]; /* now back substitute row 0 */ |
s = 1.0F/r0[0]; |
r0[4] = s * (r0[4] - r1[4] * m0), r0[5] = s * (r0[5] - r1[5] * m0), |
r0[6] = s * (r0[6] - r1[6] * m0), r0[7] = s * (r0[7] - r1[7] * m0); |
MAT(out,0,0) = r0[4]; MAT(out,0,1) = r0[5], |
MAT(out,0,2) = r0[6]; MAT(out,0,3) = r0[7], |
MAT(out,1,0) = r1[4]; MAT(out,1,1) = r1[5], |
MAT(out,1,2) = r1[6]; MAT(out,1,3) = r1[7], |
MAT(out,2,0) = r2[4]; MAT(out,2,1) = r2[5], |
MAT(out,2,2) = r2[6]; MAT(out,2,3) = r2[7], |
MAT(out,3,0) = r3[4]; MAT(out,3,1) = r3[5], |
MAT(out,3,2) = r3[6]; MAT(out,3,3) = r3[7]; |
return GL_TRUE; |
} |
#undef SWAP_ROWS |
/* Adapted from graphics gems II. |
*/ |
static GLboolean invert_matrix_3d_general( GLmatrix *mat ) |
{ |
const GLfloat *in = mat->m; |
GLfloat *out = mat->inv; |
GLfloat pos, neg, t; |
GLfloat det; |
/* Calculate the determinant of upper left 3x3 submatrix and |
* determine if the matrix is singular. |
*/ |
pos = neg = 0.0; |
t = MAT(in,0,0) * MAT(in,1,1) * MAT(in,2,2); |
if (t >= 0.0) pos += t; else neg += t; |
t = MAT(in,1,0) * MAT(in,2,1) * MAT(in,0,2); |
if (t >= 0.0) pos += t; else neg += t; |
t = MAT(in,2,0) * MAT(in,0,1) * MAT(in,1,2); |
if (t >= 0.0) pos += t; else neg += t; |
t = -MAT(in,2,0) * MAT(in,1,1) * MAT(in,0,2); |
if (t >= 0.0) pos += t; else neg += t; |
t = -MAT(in,1,0) * MAT(in,0,1) * MAT(in,2,2); |
if (t >= 0.0) pos += t; else neg += t; |
t = -MAT(in,0,0) * MAT(in,2,1) * MAT(in,1,2); |
if (t >= 0.0) pos += t; else neg += t; |
det = pos + neg; |
if (det*det < 1e-25) |
return GL_FALSE; |
det = 1.0F / det; |
MAT(out,0,0) = ( (MAT(in,1,1)*MAT(in,2,2) - MAT(in,2,1)*MAT(in,1,2) )*det); |
MAT(out,0,1) = (- (MAT(in,0,1)*MAT(in,2,2) - MAT(in,2,1)*MAT(in,0,2) )*det); |
MAT(out,0,2) = ( (MAT(in,0,1)*MAT(in,1,2) - MAT(in,1,1)*MAT(in,0,2) )*det); |
MAT(out,1,0) = (- (MAT(in,1,0)*MAT(in,2,2) - MAT(in,2,0)*MAT(in,1,2) )*det); |
MAT(out,1,1) = ( (MAT(in,0,0)*MAT(in,2,2) - MAT(in,2,0)*MAT(in,0,2) )*det); |
MAT(out,1,2) = (- (MAT(in,0,0)*MAT(in,1,2) - MAT(in,1,0)*MAT(in,0,2) )*det); |
MAT(out,2,0) = ( (MAT(in,1,0)*MAT(in,2,1) - MAT(in,2,0)*MAT(in,1,1) )*det); |
MAT(out,2,1) = (- (MAT(in,0,0)*MAT(in,2,1) - MAT(in,2,0)*MAT(in,0,1) )*det); |
MAT(out,2,2) = ( (MAT(in,0,0)*MAT(in,1,1) - MAT(in,1,0)*MAT(in,0,1) )*det); |
/* Do the translation part */ |
MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0) + |
MAT(in,1,3) * MAT(out,0,1) + |
MAT(in,2,3) * MAT(out,0,2) ); |
MAT(out,1,3) = - (MAT(in,0,3) * MAT(out,1,0) + |
MAT(in,1,3) * MAT(out,1,1) + |
MAT(in,2,3) * MAT(out,1,2) ); |
MAT(out,2,3) = - (MAT(in,0,3) * MAT(out,2,0) + |
MAT(in,1,3) * MAT(out,2,1) + |
MAT(in,2,3) * MAT(out,2,2) ); |
return GL_TRUE; |
} |
static GLboolean invert_matrix_3d( GLmatrix *mat ) |
{ |
const GLfloat *in = mat->m; |
GLfloat *out = mat->inv; |
if (!TEST_MAT_FLAGS(mat, MAT_FLAGS_ANGLE_PRESERVING)) { |
return invert_matrix_3d_general( mat ); |
} |
if (mat->flags & MAT_FLAG_UNIFORM_SCALE) { |
GLfloat scale = (MAT(in,0,0) * MAT(in,0,0) + |
MAT(in,0,1) * MAT(in,0,1) + |
MAT(in,0,2) * MAT(in,0,2)); |
if (scale == 0.0) |
return GL_FALSE; |
scale = 1.0F / scale; |
/* Transpose and scale the 3 by 3 upper-left submatrix. */ |
MAT(out,0,0) = scale * MAT(in,0,0); |
MAT(out,1,0) = scale * MAT(in,0,1); |
MAT(out,2,0) = scale * MAT(in,0,2); |
MAT(out,0,1) = scale * MAT(in,1,0); |
MAT(out,1,1) = scale * MAT(in,1,1); |
MAT(out,2,1) = scale * MAT(in,1,2); |
MAT(out,0,2) = scale * MAT(in,2,0); |
MAT(out,1,2) = scale * MAT(in,2,1); |
MAT(out,2,2) = scale * MAT(in,2,2); |
} |
else if (mat->flags & MAT_FLAG_ROTATION) { |
/* Transpose the 3 by 3 upper-left submatrix. */ |
MAT(out,0,0) = MAT(in,0,0); |
MAT(out,1,0) = MAT(in,0,1); |
MAT(out,2,0) = MAT(in,0,2); |
MAT(out,0,1) = MAT(in,1,0); |
MAT(out,1,1) = MAT(in,1,1); |
MAT(out,2,1) = MAT(in,1,2); |
MAT(out,0,2) = MAT(in,2,0); |
MAT(out,1,2) = MAT(in,2,1); |
MAT(out,2,2) = MAT(in,2,2); |
} |
else { |
/* pure translation */ |
MEMCPY( out, Identity, sizeof(Identity) ); |
MAT(out,0,3) = - MAT(in,0,3); |
MAT(out,1,3) = - MAT(in,1,3); |
MAT(out,2,3) = - MAT(in,2,3); |
return GL_TRUE; |
} |
if (mat->flags & MAT_FLAG_TRANSLATION) { |
/* Do the translation part */ |
MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0) + |
MAT(in,1,3) * MAT(out,0,1) + |
MAT(in,2,3) * MAT(out,0,2) ); |
MAT(out,1,3) = - (MAT(in,0,3) * MAT(out,1,0) + |
MAT(in,1,3) * MAT(out,1,1) + |
MAT(in,2,3) * MAT(out,1,2) ); |
MAT(out,2,3) = - (MAT(in,0,3) * MAT(out,2,0) + |
MAT(in,1,3) * MAT(out,2,1) + |
MAT(in,2,3) * MAT(out,2,2) ); |
} |
else { |
MAT(out,0,3) = MAT(out,1,3) = MAT(out,2,3) = 0.0; |
} |
return GL_TRUE; |
} |
static GLboolean invert_matrix_identity( GLmatrix *mat ) |
{ |
MEMCPY( mat->inv, Identity, sizeof(Identity) ); |
return GL_TRUE; |
} |
static GLboolean invert_matrix_3d_no_rot( GLmatrix *mat ) |
{ |
const GLfloat *in = mat->m; |
GLfloat *out = mat->inv; |
if (MAT(in,0,0) == 0 || MAT(in,1,1) == 0 || MAT(in,2,2) == 0 ) |
return GL_FALSE; |
MEMCPY( out, Identity, 16 * sizeof(GLfloat) ); |
MAT(out,0,0) = 1.0F / MAT(in,0,0); |
MAT(out,1,1) = 1.0F / MAT(in,1,1); |
MAT(out,2,2) = 1.0F / MAT(in,2,2); |
if (mat->flags & MAT_FLAG_TRANSLATION) { |
MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0)); |
MAT(out,1,3) = - (MAT(in,1,3) * MAT(out,1,1)); |
MAT(out,2,3) = - (MAT(in,2,3) * MAT(out,2,2)); |
} |
return GL_TRUE; |
} |
static GLboolean invert_matrix_2d_no_rot( GLmatrix *mat ) |
{ |
const GLfloat *in = mat->m; |
GLfloat *out = mat->inv; |
if (MAT(in,0,0) == 0 || MAT(in,1,1) == 0) |
return GL_FALSE; |
MEMCPY( out, Identity, 16 * sizeof(GLfloat) ); |
MAT(out,0,0) = 1.0F / MAT(in,0,0); |
MAT(out,1,1) = 1.0F / MAT(in,1,1); |
if (mat->flags & MAT_FLAG_TRANSLATION) { |
MAT(out,0,3) = - (MAT(in,0,3) * MAT(out,0,0)); |
MAT(out,1,3) = - (MAT(in,1,3) * MAT(out,1,1)); |
} |
return GL_TRUE; |
} |
#if 0 |
/* broken */ |
static GLboolean invert_matrix_perspective( GLmatrix *mat ) |
{ |
const GLfloat *in = mat->m; |
GLfloat *out = mat->inv; |
if (MAT(in,2,3) == 0) |
return GL_FALSE; |
MEMCPY( out, Identity, 16 * sizeof(GLfloat) ); |
MAT(out,0,0) = 1.0F / MAT(in,0,0); |
MAT(out,1,1) = 1.0F / MAT(in,1,1); |
MAT(out,0,3) = MAT(in,0,2); |
MAT(out,1,3) = MAT(in,1,2); |
MAT(out,2,2) = 0; |
MAT(out,2,3) = -1; |
MAT(out,3,2) = 1.0F / MAT(in,2,3); |
MAT(out,3,3) = MAT(in,2,2) * MAT(out,3,2); |
return GL_TRUE; |
} |
#endif |
typedef GLboolean (*inv_mat_func)( GLmatrix *mat ); |
static inv_mat_func inv_mat_tab[7] = { |
invert_matrix_general, |
invert_matrix_identity, |
invert_matrix_3d_no_rot, |
#if 0 |
/* Don't use this function for now - it fails when the projection matrix |
* is premultiplied by a translation (ala Chromium's tilesort SPU). |
*/ |
invert_matrix_perspective, |
#else |
invert_matrix_general, |
#endif |
invert_matrix_3d, /* lazy! */ |
invert_matrix_2d_no_rot, |
invert_matrix_3d |
}; |
static GLboolean matrix_invert( GLmatrix *mat ) |
{ |
if (inv_mat_tab[mat->type](mat)) { |
mat->flags &= ~MAT_FLAG_SINGULAR; |
return GL_TRUE; |
} else { |
mat->flags |= MAT_FLAG_SINGULAR; |
MEMCPY( mat->inv, Identity, sizeof(Identity) ); |
return GL_FALSE; |
} |
} |
/* |
* Generate a 4x4 transformation matrix from glRotate parameters, and |
* postmultiply the input matrix by it. |
* This function contributed by Erich Boleyn (erich@uruk.org). |
* Optimizatios contributed by Rudolf Opalla (rudi@khm.de). |
*/ |
void |
_math_matrix_rotate( GLmatrix *mat, |
GLfloat angle, GLfloat x, GLfloat y, GLfloat z ) |
{ |
GLfloat xx, yy, zz, xy, yz, zx, xs, ys, zs, one_c, s, c; |
GLfloat m[16]; |
GLboolean optimized; |
s = (GLfloat) sin( angle * DEG2RAD ); |
c = (GLfloat) cos( angle * DEG2RAD ); |
MEMCPY(m, Identity, sizeof(GLfloat)*16); |
optimized = GL_FALSE; |
#define M(row,col) m[col*4+row] |
if (x == 0.0F) { |
if (y == 0.0F) { |
if (z != 0.0F) { |
optimized = GL_TRUE; |
/* rotate only around z-axis */ |
M(0,0) = c; |
M(1,1) = c; |
if (z < 0.0F) { |
M(0,1) = s; |
M(1,0) = -s; |
} |
else { |
M(0,1) = -s; |
M(1,0) = s; |
} |
} |
} |
else if (z == 0.0F) { |
optimized = GL_TRUE; |
/* rotate only around y-axis */ |
M(0,0) = c; |
M(2,2) = c; |
if (y < 0.0F) { |
M(0,2) = -s; |
M(2,0) = s; |
} |
else { |
M(0,2) = s; |
M(2,0) = -s; |
} |
} |
} |
else if (y == 0.0F) { |
if (z == 0.0F) { |
optimized = GL_TRUE; |
/* rotate only around x-axis */ |
M(1,1) = c; |
M(2,2) = c; |
if (y < 0.0F) { |
M(1,2) = s; |
M(2,1) = -s; |
} |
else { |
M(1,2) = -s; |
M(2,1) = s; |
} |
} |
} |
if (!optimized) { |
const GLfloat mag = (GLfloat) GL_SQRT(x * x + y * y + z * z); |
if (mag <= 1.0e-4) { |
/* no rotation, leave mat as-is */ |
return; |
} |
x /= mag; |
y /= mag; |
z /= mag; |
/* |
* Arbitrary axis rotation matrix. |
* |
* This is composed of 5 matrices, Rz, Ry, T, Ry', Rz', multiplied |
* like so: Rz * Ry * T * Ry' * Rz'. T is the final rotation |
* (which is about the X-axis), and the two composite transforms |
* Ry' * Rz' and Rz * Ry are (respectively) the rotations necessary |
* from the arbitrary axis to the X-axis then back. They are |
* all elementary rotations. |
* |
* Rz' is a rotation about the Z-axis, to bring the axis vector |
* into the x-z plane. Then Ry' is applied, rotating about the |
* Y-axis to bring the axis vector parallel with the X-axis. The |
* rotation about the X-axis is then performed. Ry and Rz are |
* simply the respective inverse transforms to bring the arbitrary |
* axis back to it's original orientation. The first transforms |
* Rz' and Ry' are considered inverses, since the data from the |
* arbitrary axis gives you info on how to get to it, not how |
* to get away from it, and an inverse must be applied. |
* |
* The basic calculation used is to recognize that the arbitrary |
* axis vector (x, y, z), since it is of unit length, actually |
* represents the sines and cosines of the angles to rotate the |
* X-axis to the same orientation, with theta being the angle about |
* Z and phi the angle about Y (in the order described above) |
* as follows: |
* |
* cos ( theta ) = x / sqrt ( 1 - z^2 ) |
* sin ( theta ) = y / sqrt ( 1 - z^2 ) |
* |
* cos ( phi ) = sqrt ( 1 - z^2 ) |
* sin ( phi ) = z |
* |
* Note that cos ( phi ) can further be inserted to the above |
* formulas: |
* |
* cos ( theta ) = x / cos ( phi ) |
* sin ( theta ) = y / sin ( phi ) |
* |
* ...etc. Because of those relations and the standard trigonometric |
* relations, it is pssible to reduce the transforms down to what |
* is used below. It may be that any primary axis chosen will give the |
* same results (modulo a sign convention) using thie method. |
* |
* Particularly nice is to notice that all divisions that might |
* have caused trouble when parallel to certain planes or |
* axis go away with care paid to reducing the expressions. |
* After checking, it does perform correctly under all cases, since |
* in all the cases of division where the denominator would have |
* been zero, the numerator would have been zero as well, giving |
* the expected result. |
*/ |
xx = x * x; |
yy = y * y; |
zz = z * z; |
xy = x * y; |
yz = y * z; |
zx = z * x; |
xs = x * s; |
ys = y * s; |
zs = z * s; |
one_c = 1.0F - c; |
/* We already hold the identity-matrix so we can skip some statements */ |
M(0,0) = (one_c * xx) + c; |
M(0,1) = (one_c * xy) - zs; |
M(0,2) = (one_c * zx) + ys; |
/* M(0,3) = 0.0F; */ |
M(1,0) = (one_c * xy) + zs; |
M(1,1) = (one_c * yy) + c; |
M(1,2) = (one_c * yz) - xs; |
/* M(1,3) = 0.0F; */ |
M(2,0) = (one_c * zx) - ys; |
M(2,1) = (one_c * yz) + xs; |
M(2,2) = (one_c * zz) + c; |
/* M(2,3) = 0.0F; */ |
/* |
M(3,0) = 0.0F; |
M(3,1) = 0.0F; |
M(3,2) = 0.0F; |
M(3,3) = 1.0F; |
*/ |
} |
#undef M |
matrix_multf( mat, m, MAT_FLAG_ROTATION ); |
} |
void |
_math_matrix_frustum( GLmatrix *mat, |
GLfloat left, GLfloat right, |
GLfloat bottom, GLfloat top, |
GLfloat nearval, GLfloat farval ) |
{ |
GLfloat x, y, a, b, c, d; |
GLfloat m[16]; |
x = (2.0F*nearval) / (right-left); |
y = (2.0F*nearval) / (top-bottom); |
a = (right+left) / (right-left); |
b = (top+bottom) / (top-bottom); |
c = -(farval+nearval) / ( farval-nearval); |
d = -(2.0F*farval*nearval) / (farval-nearval); /* error? */ |
#define M(row,col) m[col*4+row] |
M(0,0) = x; M(0,1) = 0.0F; M(0,2) = a; M(0,3) = 0.0F; |
M(1,0) = 0.0F; M(1,1) = y; M(1,2) = b; M(1,3) = 0.0F; |
M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = c; M(2,3) = d; |
M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = -1.0F; M(3,3) = 0.0F; |
#undef M |
matrix_multf( mat, m, MAT_FLAG_PERSPECTIVE ); |
} |
void |
_math_matrix_ortho( GLmatrix *mat, |
GLfloat left, GLfloat right, |
GLfloat bottom, GLfloat top, |
GLfloat nearval, GLfloat farval ) |
{ |
GLfloat x, y, z; |
GLfloat tx, ty, tz; |
GLfloat m[16]; |
x = 2.0F / (right-left); |
y = 2.0F / (top-bottom); |
z = -2.0F / (farval-nearval); |
tx = -(right+left) / (right-left); |
ty = -(top+bottom) / (top-bottom); |
tz = -(farval+nearval) / (farval-nearval); |
#define M(row,col) m[col*4+row] |
M(0,0) = x; M(0,1) = 0.0F; M(0,2) = 0.0F; M(0,3) = tx; |
M(1,0) = 0.0F; M(1,1) = y; M(1,2) = 0.0F; M(1,3) = ty; |
M(2,0) = 0.0F; M(2,1) = 0.0F; M(2,2) = z; M(2,3) = tz; |
M(3,0) = 0.0F; M(3,1) = 0.0F; M(3,2) = 0.0F; M(3,3) = 1.0F; |
#undef M |
matrix_multf( mat, m, (MAT_FLAG_GENERAL_SCALE|MAT_FLAG_TRANSLATION)); |
} |
#define ZERO(x) (1<<x) |
#define ONE(x) (1<<(x+16)) |
#define MASK_NO_TRX (ZERO(12) | ZERO(13) | ZERO(14)) |
#define MASK_NO_2D_SCALE ( ONE(0) | ONE(5)) |
#define MASK_IDENTITY ( ONE(0) | ZERO(4) | ZERO(8) | ZERO(12) |\ |
ZERO(1) | ONE(5) | ZERO(9) | ZERO(13) |\ |
ZERO(2) | ZERO(6) | ONE(10) | ZERO(14) |\ |
ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) ) |
#define MASK_2D_NO_ROT ( ZERO(4) | ZERO(8) | \ |
ZERO(1) | ZERO(9) | \ |
ZERO(2) | ZERO(6) | ONE(10) | ZERO(14) |\ |
ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) ) |
#define MASK_2D ( ZERO(8) | \ |
ZERO(9) | \ |
ZERO(2) | ZERO(6) | ONE(10) | ZERO(14) |\ |
ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) ) |
#define MASK_3D_NO_ROT ( ZERO(4) | ZERO(8) | \ |
ZERO(1) | ZERO(9) | \ |
ZERO(2) | ZERO(6) | \ |
ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) ) |
#define MASK_3D ( \ |
\ |
\ |
ZERO(3) | ZERO(7) | ZERO(11) | ONE(15) ) |
#define MASK_PERSPECTIVE ( ZERO(4) | ZERO(12) |\ |
ZERO(1) | ZERO(13) |\ |
ZERO(2) | ZERO(6) | \ |
ZERO(3) | ZERO(7) | ZERO(15) ) |
#define SQ(x) ((x)*(x)) |
/* Determine type and flags from scratch. This is expensive enough to |
* only want to do it once. |
*/ |
static void analyse_from_scratch( GLmatrix *mat ) |
{ |
const GLfloat *m = mat->m; |
GLuint mask = 0; |
GLuint i; |
for (i = 0 ; i < 16 ; i++) { |
if (m[i] == 0.0) mask |= (1<<i); |
} |
if (m[0] == 1.0F) mask |= (1<<16); |
if (m[5] == 1.0F) mask |= (1<<21); |
if (m[10] == 1.0F) mask |= (1<<26); |
if (m[15] == 1.0F) mask |= (1<<31); |
mat->flags &= ~MAT_FLAGS_GEOMETRY; |
/* Check for translation - no-one really cares |
*/ |
if ((mask & MASK_NO_TRX) != MASK_NO_TRX) |
mat->flags |= MAT_FLAG_TRANSLATION; |
/* Do the real work |
*/ |
if (mask == (GLuint) MASK_IDENTITY) { |
mat->type = MATRIX_IDENTITY; |
} |
else if ((mask & MASK_2D_NO_ROT) == (GLuint) MASK_2D_NO_ROT) { |
mat->type = MATRIX_2D_NO_ROT; |
if ((mask & MASK_NO_2D_SCALE) != MASK_NO_2D_SCALE) |
mat->flags = MAT_FLAG_GENERAL_SCALE; |
} |
else if ((mask & MASK_2D) == (GLuint) MASK_2D) { |
GLfloat mm = DOT2(m, m); |
GLfloat m4m4 = DOT2(m+4,m+4); |
GLfloat mm4 = DOT2(m,m+4); |
mat->type = MATRIX_2D; |
/* Check for scale */ |
if (SQ(mm-1) > SQ(1e-6) || |
SQ(m4m4-1) > SQ(1e-6)) |
mat->flags |= MAT_FLAG_GENERAL_SCALE; |
/* Check for rotation */ |
if (SQ(mm4) > SQ(1e-6)) |
mat->flags |= MAT_FLAG_GENERAL_3D; |
else |
mat->flags |= MAT_FLAG_ROTATION; |
} |
else if ((mask & MASK_3D_NO_ROT) == (GLuint) MASK_3D_NO_ROT) { |
mat->type = MATRIX_3D_NO_ROT; |
/* Check for scale */ |
if (SQ(m[0]-m[5]) < SQ(1e-6) && |
SQ(m[0]-m[10]) < SQ(1e-6)) { |
if (SQ(m[0]-1.0) > SQ(1e-6)) { |
mat->flags |= MAT_FLAG_UNIFORM_SCALE; |
} |
} |
else { |
mat->flags |= MAT_FLAG_GENERAL_SCALE; |
} |
} |
else if ((mask & MASK_3D) == (GLuint) MASK_3D) { |
GLfloat c1 = DOT3(m,m); |
GLfloat c2 = DOT3(m+4,m+4); |
GLfloat c3 = DOT3(m+8,m+8); |
GLfloat d1 = DOT3(m, m+4); |
GLfloat cp[3]; |
mat->type = MATRIX_3D; |
/* Check for scale */ |
if (SQ(c1-c2) < SQ(1e-6) && SQ(c1-c3) < SQ(1e-6)) { |
if (SQ(c1-1.0) > SQ(1e-6)) |
mat->flags |= MAT_FLAG_UNIFORM_SCALE; |
/* else no scale at all */ |
} |
else { |
mat->flags |= MAT_FLAG_GENERAL_SCALE; |
} |
/* Check for rotation */ |
if (SQ(d1) < SQ(1e-6)) { |
CROSS3( cp, m, m+4 ); |
SUB_3V( cp, cp, (m+8) ); |
if (LEN_SQUARED_3FV(cp) < SQ(1e-6)) |
mat->flags |= MAT_FLAG_ROTATION; |
else |
mat->flags |= MAT_FLAG_GENERAL_3D; |
} |
else { |
mat->flags |= MAT_FLAG_GENERAL_3D; /* shear, etc */ |
} |
} |
else if ((mask & MASK_PERSPECTIVE) == MASK_PERSPECTIVE && m[11]==-1.0F) { |
mat->type = MATRIX_PERSPECTIVE; |
mat->flags |= MAT_FLAG_GENERAL; |
} |
else { |
mat->type = MATRIX_GENERAL; |
mat->flags |= MAT_FLAG_GENERAL; |
} |
} |
/* Analyse a matrix given that its flags are accurate - this is the |
* more common operation, hopefully. |
*/ |
static void analyse_from_flags( GLmatrix *mat ) |
{ |
const GLfloat *m = mat->m; |
if (TEST_MAT_FLAGS(mat, 0)) { |
mat->type = MATRIX_IDENTITY; |
} |
else if (TEST_MAT_FLAGS(mat, (MAT_FLAG_TRANSLATION | |
MAT_FLAG_UNIFORM_SCALE | |
MAT_FLAG_GENERAL_SCALE))) { |
if ( m[10]==1.0F && m[14]==0.0F ) { |
mat->type = MATRIX_2D_NO_ROT; |
} |
else { |
mat->type = MATRIX_3D_NO_ROT; |
} |
} |
else if (TEST_MAT_FLAGS(mat, MAT_FLAGS_3D)) { |
if ( m[ 8]==0.0F |
&& m[ 9]==0.0F |
&& m[2]==0.0F && m[6]==0.0F && m[10]==1.0F && m[14]==0.0F) { |
mat->type = MATRIX_2D; |
} |
else { |
mat->type = MATRIX_3D; |
} |
} |
else if ( m[4]==0.0F && m[12]==0.0F |
&& m[1]==0.0F && m[13]==0.0F |
&& m[2]==0.0F && m[6]==0.0F |
&& m[3]==0.0F && m[7]==0.0F && m[11]==-1.0F && m[15]==0.0F) { |
mat->type = MATRIX_PERSPECTIVE; |
} |
else { |
mat->type = MATRIX_GENERAL; |
} |
} |
void |
_math_matrix_analyse( GLmatrix *mat ) |
{ |
if (mat->flags & MAT_DIRTY_TYPE) { |
if (mat->flags & MAT_DIRTY_FLAGS) |
analyse_from_scratch( mat ); |
else |
analyse_from_flags( mat ); |
} |
if (mat->inv && (mat->flags & MAT_DIRTY_INVERSE)) { |
matrix_invert( mat ); |
} |
mat->flags &= ~(MAT_DIRTY_FLAGS| |
MAT_DIRTY_TYPE| |
MAT_DIRTY_INVERSE); |
} |
void |
_math_matrix_copy( GLmatrix *to, const GLmatrix *from ) |
{ |
MEMCPY( to->m, from->m, sizeof(Identity) ); |
to->flags = from->flags; |
to->type = from->type; |
if (to->inv != 0) { |
if (from->inv == 0) { |
matrix_invert( to ); |
} |
else { |
MEMCPY(to->inv, from->inv, sizeof(GLfloat)*16); |
} |
} |
} |
void |
_math_matrix_scale( GLmatrix *mat, GLfloat x, GLfloat y, GLfloat z ) |
{ |
GLfloat *m = mat->m; |
m[0] *= x; m[4] *= y; m[8] *= z; |
m[1] *= x; m[5] *= y; m[9] *= z; |
m[2] *= x; m[6] *= y; m[10] *= z; |
m[3] *= x; m[7] *= y; m[11] *= z; |
if (fabs(x - y) < 1e-8 && fabs(x - z) < 1e-8) |
mat->flags |= MAT_FLAG_UNIFORM_SCALE; |
else |
mat->flags |= MAT_FLAG_GENERAL_SCALE; |
mat->flags |= (MAT_DIRTY_TYPE | |
MAT_DIRTY_INVERSE); |
} |
void |
_math_matrix_translate( GLmatrix *mat, GLfloat x, GLfloat y, GLfloat z ) |
{ |
GLfloat *m = mat->m; |
m[12] = m[0] * x + m[4] * y + m[8] * z + m[12]; |
m[13] = m[1] * x + m[5] * y + m[9] * z + m[13]; |
m[14] = m[2] * x + m[6] * y + m[10] * z + m[14]; |
m[15] = m[3] * x + m[7] * y + m[11] * z + m[15]; |
mat->flags |= (MAT_FLAG_TRANSLATION | |
MAT_DIRTY_TYPE | |
MAT_DIRTY_INVERSE); |
} |
void |
_math_matrix_loadf( GLmatrix *mat, const GLfloat *m ) |
{ |
MEMCPY( mat->m, m, 16*sizeof(GLfloat) ); |
mat->flags = (MAT_FLAG_GENERAL | MAT_DIRTY); |
} |
void |
_math_matrix_ctr( GLmatrix *m ) |
{ |
m->m = (GLfloat *) ALIGN_MALLOC( 16 * sizeof(GLfloat), 16 ); |
if (m->m) |
MEMCPY( m->m, Identity, sizeof(Identity) ); |
m->inv = NULL; |
m->type = MATRIX_IDENTITY; |
m->flags = 0; |
} |
void |
_math_matrix_dtr( GLmatrix *m ) |
{ |
if (m->m) { |
ALIGN_FREE( m->m ); |
m->m = NULL; |
} |
if (m->inv) { |
ALIGN_FREE( m->inv ); |
m->inv = NULL; |
} |
} |
void |
_math_matrix_alloc_inv( GLmatrix *m ) |
{ |
if (!m->inv) { |
m->inv = (GLfloat *) ALIGN_MALLOC( 16 * sizeof(GLfloat), 16 ); |
if (m->inv) |
MEMCPY( m->inv, Identity, 16 * sizeof(GLfloat) ); |
} |
} |
void |
_math_matrix_mul_matrix( GLmatrix *dest, const GLmatrix *a, const GLmatrix *b ) |
{ |
dest->flags = (a->flags | |
b->flags | |
MAT_DIRTY_TYPE | |
MAT_DIRTY_INVERSE); |
if (TEST_MAT_FLAGS(dest, MAT_FLAGS_3D)) |
matmul34( dest->m, a->m, b->m ); |
else |
matmul4( dest->m, a->m, b->m ); |
} |
void |
_math_matrix_mul_floats( GLmatrix *dest, const GLfloat *m ) |
{ |
dest->flags |= (MAT_FLAG_GENERAL | |
MAT_DIRTY_TYPE | |
MAT_DIRTY_INVERSE); |
matmul4( dest->m, dest->m, m ); |
} |
void |
_math_matrix_set_identity( GLmatrix *mat ) |
{ |
MEMCPY( mat->m, Identity, 16*sizeof(GLfloat) ); |
if (mat->inv) |
MEMCPY( mat->inv, Identity, 16*sizeof(GLfloat) ); |
mat->type = MATRIX_IDENTITY; |
mat->flags &= ~(MAT_DIRTY_FLAGS| |
MAT_DIRTY_TYPE| |
MAT_DIRTY_INVERSE); |
} |
void |
_math_transposef( GLfloat to[16], const GLfloat from[16] ) |
{ |
to[0] = from[0]; |
to[1] = from[4]; |
to[2] = from[8]; |
to[3] = from[12]; |
to[4] = from[1]; |
to[5] = from[5]; |
to[6] = from[9]; |
to[7] = from[13]; |
to[8] = from[2]; |
to[9] = from[6]; |
to[10] = from[10]; |
to[11] = from[14]; |
to[12] = from[3]; |
to[13] = from[7]; |
to[14] = from[11]; |
to[15] = from[15]; |
} |
void |
_math_transposed( GLdouble to[16], const GLdouble from[16] ) |
{ |
to[0] = from[0]; |
to[1] = from[4]; |
to[2] = from[8]; |
to[3] = from[12]; |
to[4] = from[1]; |
to[5] = from[5]; |
to[6] = from[9]; |
to[7] = from[13]; |
to[8] = from[2]; |
to[9] = from[6]; |
to[10] = from[10]; |
to[11] = from[14]; |
to[12] = from[3]; |
to[13] = from[7]; |
to[14] = from[11]; |
to[15] = from[15]; |
} |
void |
_math_transposefd( GLfloat to[16], const GLdouble from[16] ) |
{ |
to[0] = (GLfloat) from[0]; |
to[1] = (GLfloat) from[4]; |
to[2] = (GLfloat) from[8]; |
to[3] = (GLfloat) from[12]; |
to[4] = (GLfloat) from[1]; |
to[5] = (GLfloat) from[5]; |
to[6] = (GLfloat) from[9]; |
to[7] = (GLfloat) from[13]; |
to[8] = (GLfloat) from[2]; |
to[9] = (GLfloat) from[6]; |
to[10] = (GLfloat) from[10]; |
to[11] = (GLfloat) from[14]; |
to[12] = (GLfloat) from[3]; |
to[13] = (GLfloat) from[7]; |
to[14] = (GLfloat) from[11]; |
to[15] = (GLfloat) from[15]; |
} |
/shark/trunk/ports/mesa/src/math/m_vector.h |
---|
0,0 → 1,222 |
/* $Id: m_vector.h,v 1.1 2003-02-28 11:48:05 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 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. |
*/ |
/* |
* New (3.1) transformation code written by Keith Whitwell. |
*/ |
#ifndef _M_VECTOR_H_ |
#define _M_VECTOR_H_ |
#include "glheader.h" |
#include "mtypes.h" /* hack for GLchan */ |
#define VEC_DIRTY_0 0x1 |
#define VEC_DIRTY_1 0x2 |
#define VEC_DIRTY_2 0x4 |
#define VEC_DIRTY_3 0x8 |
#define VEC_MALLOC 0x10 /* storage field points to self-allocated mem*/ |
#define VEC_NOT_WRITEABLE 0x40 /* writable elements to hold clipped data */ |
#define VEC_BAD_STRIDE 0x100 /* matches tnl's prefered stride */ |
#define VEC_SIZE_1 VEC_DIRTY_0 |
#define VEC_SIZE_2 (VEC_DIRTY_0|VEC_DIRTY_1) |
#define VEC_SIZE_3 (VEC_DIRTY_0|VEC_DIRTY_1|VEC_DIRTY_2) |
#define VEC_SIZE_4 (VEC_DIRTY_0|VEC_DIRTY_1|VEC_DIRTY_2|VEC_DIRTY_3) |
/* Wrap all the information about vectors up in a struct. Has |
* additional fields compared to the other vectors to help us track of |
* different vertex sizes, and whether we need to clean columns out |
* because they contain non-(0,0,0,1) values. |
* |
* The start field is used to reserve data for copied vertices at the |
* end of _mesa_transform_vb, and avoids the need for a multiplication in |
* the transformation routines. |
*/ |
typedef struct { |
GLfloat (*data)[4]; /* may be malloc'd or point to client data */ |
GLfloat *start; /* points somewhere inside of <data> */ |
GLuint count; /* size of the vector (in elements) */ |
GLuint stride; /* stride from one element to the next (in bytes) */ |
GLuint size; /* 2-4 for vertices and 1-4 for texcoords */ |
GLuint flags; /* which columns are dirty */ |
void *storage; /* self-allocated storage */ |
} GLvector4f; |
extern void _mesa_vector4f_init( GLvector4f *v, GLuint flags, |
GLfloat (*storage)[4] ); |
extern void _mesa_vector4f_alloc( GLvector4f *v, GLuint flags, |
GLuint count, GLuint alignment ); |
extern void _mesa_vector4f_free( GLvector4f *v ); |
extern void _mesa_vector4f_print( GLvector4f *v, GLubyte *, GLboolean ); |
extern void _mesa_vector4f_clean_elem( GLvector4f *vec, GLuint nr, GLuint elt ); |
/* Could use a single vector type for normals and vertices, but |
* this way avoids some casts. |
*/ |
typedef struct { |
GLfloat (*data)[3]; |
GLfloat *start; |
GLuint count; |
GLuint stride; |
GLuint flags; |
void *storage; |
} GLvector3f; |
extern void _mesa_vector3f_init( GLvector3f *v, GLuint flags, GLfloat (*)[3] ); |
extern void _mesa_vector3f_alloc( GLvector3f *v, GLuint flags, GLuint count, |
GLuint alignment ); |
extern void _mesa_vector3f_free( GLvector3f *v ); |
extern void _mesa_vector3f_print( GLvector3f *v, GLubyte *, GLboolean ); |
typedef struct { |
GLfloat *data; |
GLfloat *start; |
GLuint count; |
GLuint stride; |
GLuint flags; |
void *storage; |
} GLvector1f; |
extern void _mesa_vector1f_free( GLvector1f *v ); |
extern void _mesa_vector1f_init( GLvector1f *v, GLuint flags, GLfloat * ); |
extern void _mesa_vector1f_alloc( GLvector1f *v, GLuint flags, GLuint count, |
GLuint alignment ); |
/* For 4ub rgba values. |
*/ |
typedef struct { |
GLubyte (*data)[4]; |
GLubyte *start; |
GLuint count; |
GLuint stride; |
GLuint flags; |
void *storage; |
} GLvector4ub; |
extern void _mesa_vector4ub_init( GLvector4ub *v, GLuint flags, |
GLubyte (*storage)[4] ); |
extern void _mesa_vector4ub_alloc( GLvector4ub *v, GLuint flags, GLuint count, |
GLuint alignment ); |
extern void _mesa_vector4ub_free( GLvector4ub * ); |
/* For 4 * GLchan values. |
*/ |
typedef struct { |
GLchan (*data)[4]; |
GLchan *start; |
GLuint count; |
GLuint stride; |
GLuint flags; |
void *storage; |
} GLvector4chan; |
extern void _mesa_vector4chan_init( GLvector4chan *v, GLuint flags, |
GLchan (*storage)[4] ); |
extern void _mesa_vector4chan_alloc( GLvector4chan *v, GLuint flags, GLuint count, |
GLuint alignment ); |
extern void _mesa_vector4chan_free( GLvector4chan * ); |
/* For 4 * GLushort rgba values. |
*/ |
typedef struct { |
GLushort (*data)[4]; |
GLushort *start; |
GLuint count; |
GLuint stride; |
GLuint flags; |
void *storage; |
} GLvector4us; |
extern void _mesa_vector4us_init( GLvector4us *v, GLuint flags, |
GLushort (*storage)[4] ); |
extern void _mesa_vector4us_alloc( GLvector4us *v, GLuint flags, GLuint count, |
GLuint alignment ); |
extern void _mesa_vector4us_free( GLvector4us * ); |
/* For 1ub values, eg edgeflag. |
*/ |
typedef struct { |
GLubyte *data; |
GLubyte *start; |
GLuint count; |
GLuint stride; |
GLuint flags; |
void *storage; |
} GLvector1ub; |
extern void _mesa_vector1ub_init( GLvector1ub *v, GLuint flags, GLubyte *storage); |
extern void _mesa_vector1ub_alloc( GLvector1ub *v, GLuint flags, GLuint count, |
GLuint alignment ); |
extern void _mesa_vector1ub_free( GLvector1ub * ); |
/* For, eg Index, Array element. |
*/ |
typedef struct { |
GLuint *data; |
GLuint *start; |
GLuint count; |
GLuint stride; |
GLuint flags; |
void *storage; |
} GLvector1ui; |
extern void _mesa_vector1ui_init( GLvector1ui *v, GLuint flags, GLuint *storage ); |
extern void _mesa_vector1ui_alloc( GLvector1ui *v, GLuint flags, GLuint count, |
GLuint alignment ); |
extern void _mesa_vector1ui_free( GLvector1ui * ); |
/* |
* Given vector <v>, return a pointer (cast to <type *> to the <i>-th element. |
* |
* End up doing a lot of slow imuls if not careful. |
*/ |
#define VEC_ELT( v, type, i ) \ |
( (type *) ( ((GLbyte *) ((v)->data)) + (i) * (v)->stride) ) |
#endif |
/shark/trunk/ports/mesa/src/math/m_matrix.h |
---|
0,0 → 1,176 |
/* $Id: m_matrix.h,v 1.1 2003-02-28 11:48:05 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 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. |
*/ |
#ifndef _M_MATRIX_H |
#define _M_MATRIX_H |
/* Give symbolic names to some of the entries in the matrix to help |
* out with the rework of the viewport_map as a matrix transform. |
*/ |
#define MAT_SX 0 |
#define MAT_SY 5 |
#define MAT_SZ 10 |
#define MAT_TX 12 |
#define MAT_TY 13 |
#define MAT_TZ 14 |
/* |
* Different kinds of 4x4 transformation matrices: |
*/ |
#define MATRIX_GENERAL 0 /* general 4x4 matrix */ |
#define MATRIX_IDENTITY 1 /* identity matrix */ |
#define MATRIX_3D_NO_ROT 2 /* ortho projection and others... */ |
#define MATRIX_PERSPECTIVE 3 /* perspective projection matrix */ |
#define MATRIX_2D 4 /* 2-D transformation */ |
#define MATRIX_2D_NO_ROT 5 /* 2-D scale & translate only */ |
#define MATRIX_3D 6 /* 3-D transformation */ |
#define MAT_FLAG_IDENTITY 0 |
#define MAT_FLAG_GENERAL 0x1 |
#define MAT_FLAG_ROTATION 0x2 |
#define MAT_FLAG_TRANSLATION 0x4 |
#define MAT_FLAG_UNIFORM_SCALE 0x8 |
#define MAT_FLAG_GENERAL_SCALE 0x10 |
#define MAT_FLAG_GENERAL_3D 0x20 |
#define MAT_FLAG_PERSPECTIVE 0x40 |
#define MAT_FLAG_SINGULAR 0x80 |
#define MAT_DIRTY_TYPE 0x100 |
#define MAT_DIRTY_FLAGS 0x200 |
#define MAT_DIRTY_INVERSE 0x400 |
#define MAT_FLAGS_ANGLE_PRESERVING (MAT_FLAG_ROTATION | \ |
MAT_FLAG_TRANSLATION | \ |
MAT_FLAG_UNIFORM_SCALE) |
#define MAT_FLAGS_LENGTH_PRESERVING (MAT_FLAG_ROTATION | \ |
MAT_FLAG_TRANSLATION) |
#define MAT_FLAGS_3D (MAT_FLAG_ROTATION | \ |
MAT_FLAG_TRANSLATION | \ |
MAT_FLAG_UNIFORM_SCALE | \ |
MAT_FLAG_GENERAL_SCALE | \ |
MAT_FLAG_GENERAL_3D) |
#define MAT_FLAGS_GEOMETRY (MAT_FLAG_GENERAL | \ |
MAT_FLAG_ROTATION | \ |
MAT_FLAG_TRANSLATION | \ |
MAT_FLAG_UNIFORM_SCALE | \ |
MAT_FLAG_GENERAL_SCALE | \ |
MAT_FLAG_GENERAL_3D | \ |
MAT_FLAG_PERSPECTIVE | \ |
MAT_FLAG_SINGULAR) |
#define MAT_DIRTY (MAT_DIRTY_TYPE | \ |
MAT_DIRTY_FLAGS | \ |
MAT_DIRTY_INVERSE) |
#define TEST_MAT_FLAGS(mat, a) \ |
((MAT_FLAGS_GEOMETRY & (~(a)) & ((mat)->flags) ) == 0) |
typedef struct { |
GLfloat *m; /* 16-byte aligned */ |
GLfloat *inv; /* optional, 16-byte aligned */ |
GLuint flags; |
GLuint type; /* one of the MATRIX_* values */ |
} GLmatrix; |
extern void |
_math_matrix_ctr( GLmatrix *m ); |
extern void |
_math_matrix_dtr( GLmatrix *m ); |
extern void |
_math_matrix_alloc_inv( GLmatrix *m ); |
extern void |
_math_matrix_mul_matrix( GLmatrix *dest, const GLmatrix *a, const GLmatrix *b ); |
extern void |
_math_matrix_mul_floats( GLmatrix *dest, const GLfloat *b ); |
extern void |
_math_matrix_loadf( GLmatrix *mat, const GLfloat *m ); |
extern void |
_math_matrix_translate( GLmatrix *mat, GLfloat x, GLfloat y, GLfloat z ); |
extern void |
_math_matrix_rotate( GLmatrix *m, GLfloat angle, |
GLfloat x, GLfloat y, GLfloat z ); |
extern void |
_math_matrix_scale( GLmatrix *mat, GLfloat x, GLfloat y, GLfloat z ); |
extern void |
_math_matrix_ortho( GLmatrix *mat, |
GLfloat left, GLfloat right, |
GLfloat bottom, GLfloat top, |
GLfloat nearval, GLfloat farval ); |
extern void |
_math_matrix_frustum( GLmatrix *mat, |
GLfloat left, GLfloat right, |
GLfloat bottom, GLfloat top, |
GLfloat nearval, GLfloat farval ); |
extern void |
_math_matrix_set_identity( GLmatrix *dest ); |
extern void |
_math_matrix_copy( GLmatrix *to, const GLmatrix *from ); |
extern void |
_math_matrix_analyse( GLmatrix *mat ); |
extern void |
_math_matrix_print( const GLmatrix *m ); |
/* Related functions that don't actually operate on GLmatrix structs: |
*/ |
extern void |
_math_transposef( GLfloat to[16], const GLfloat from[16] ); |
extern void |
_math_transposed( GLdouble to[16], const GLdouble from[16] ); |
extern void |
_math_transposefd( GLfloat to[16], const GLdouble from[16] ); |
#endif |
/shark/trunk/ports/mesa/src/math/m_trans_tmp.h |
---|
0,0 → 1,236 |
/* $Id: m_trans_tmp.h,v 1.1 2003-02-28 11:48:05 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 4.0.2 |
* |
* 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. |
*/ |
/* |
* New (3.1) transformation code written by Keith Whitwell. |
*/ |
/* KW: This file also included by tnl/trans_elt.c to build code |
* specific to the implementation of array-elements in the |
* tnl module. |
*/ |
#ifdef DEST_4F |
static void DEST_4F( GLfloat (*t)[4], |
CONST void *ptr, |
GLuint stride, |
ARGS ) |
{ |
const GLubyte *f = (GLubyte *) ptr + SRC_START * stride; |
const GLubyte *first = f; |
GLuint i; |
(void) first; |
(void) start; |
for (i = DST_START ; i < n ; i++, NEXT_F) { |
CHECK { |
NEXT_F2; |
if (SZ >= 1) t[i][0] = TRX_4F(f, 0); |
if (SZ >= 2) t[i][1] = TRX_4F(f, 1); |
if (SZ >= 3) t[i][2] = TRX_4F(f, 2); |
if (SZ == 4) t[i][3] = TRX_4F(f, 3); else t[i][3] = 1.0; |
} |
} |
} |
#endif |
#ifdef DEST_3F |
static void DEST_3F( GLfloat (*t)[3], |
CONST void *ptr, |
GLuint stride, |
ARGS ) |
{ |
const GLubyte *f = (GLubyte *) ptr + SRC_START * stride; |
const GLubyte *first = f; |
GLuint i; |
(void) first; |
(void) start; |
for (i = DST_START ; i < n ; i++, NEXT_F) { |
CHECK { |
NEXT_F2; |
t[i][0] = TRX_3F(f, 0); |
t[i][1] = TRX_3F(f, 1); |
t[i][2] = TRX_3F(f, 2); |
} |
} |
} |
#endif |
#ifdef DEST_1F |
static void DEST_1F( GLfloat *t, |
CONST void *ptr, |
GLuint stride, |
ARGS ) |
{ |
const GLubyte *f = (GLubyte *) ptr + SRC_START * stride; |
const GLubyte *first = f; |
GLuint i; |
(void) first; |
(void) start; |
for (i = DST_START ; i < n ; i++, NEXT_F) { |
CHECK { |
NEXT_F2; |
t[i] = TRX_1F(f, 0); |
} |
} |
} |
#endif |
#ifdef DEST_4UB |
static void DEST_4UB( GLubyte (*t)[4], |
CONST void *ptr, |
GLuint stride, |
ARGS ) |
{ |
const GLubyte *f = (GLubyte *) ptr + SRC_START * stride; |
const GLubyte *first = f; |
GLuint i; |
(void) start; |
(void) first; |
for (i = DST_START ; i < n ; i++, NEXT_F) { |
CHECK { |
NEXT_F2; |
if (SZ >= 1) TRX_UB(t[i][0], f, 0); |
if (SZ >= 2) TRX_UB(t[i][1], f, 1); |
if (SZ >= 3) TRX_UB(t[i][2], f, 2); |
if (SZ == 4) TRX_UB(t[i][3], f, 3); else t[i][3] = 255; |
} |
} |
} |
#endif |
#ifdef DEST_4US |
static void DEST_4US( GLushort (*t)[4], |
CONST void *ptr, |
GLuint stride, |
ARGS ) |
{ |
const GLubyte *f = (GLubyte *) ((GLubyte *) ptr + SRC_START * stride); |
const GLubyte *first = f; |
GLuint i; |
(void) start; |
(void) first; |
for (i = DST_START ; i < n ; i++, NEXT_F) { |
CHECK { |
NEXT_F2; |
if (SZ >= 1) TRX_US(t[i][0], f, 0); |
if (SZ >= 2) TRX_US(t[i][1], f, 1); |
if (SZ >= 3) TRX_US(t[i][2], f, 2); |
if (SZ == 4) TRX_US(t[i][3], f, 3); else t[i][3] = 65535; |
} |
} |
} |
#endif |
#ifdef DEST_1UB |
static void DEST_1UB( GLubyte *t, |
CONST void *ptr, |
GLuint stride, |
ARGS ) |
{ |
const GLubyte *f = (GLubyte *) ptr + SRC_START * stride; |
const GLubyte *first = f; |
GLuint i; |
(void) start; |
(void) first; |
for (i = DST_START ; i < n ; i++, NEXT_F) { |
CHECK { |
NEXT_F2; |
TRX_UB(t[i], f, 0); |
} |
} |
} |
#endif |
#ifdef DEST_1UI |
static void DEST_1UI( GLuint *t, |
CONST void *ptr, |
GLuint stride, |
ARGS ) |
{ |
const GLubyte *f = (GLubyte *) ptr + SRC_START * stride; |
const GLubyte *first = f; |
GLuint i; |
(void) start; |
(void) first; |
for (i = DST_START ; i < n ; i++, NEXT_F) { |
CHECK { |
NEXT_F2; |
t[i] = TRX_UI(f, 0); |
} |
} |
} |
#endif |
static void INIT(void) |
{ |
#ifdef DEST_1UI |
ASSERT(SZ == 1); |
TAB(_1ui)[SRC_IDX] = DEST_1UI; |
#endif |
#ifdef DEST_1UB |
ASSERT(SZ == 1); |
TAB(_1ub)[SRC_IDX] = DEST_1UB; |
#endif |
#ifdef DEST_1F |
ASSERT(SZ == 1); |
TAB(_1f)[SRC_IDX] = DEST_1F; |
#endif |
#ifdef DEST_3F |
ASSERT(SZ == 3); |
TAB(_3f)[SRC_IDX] = DEST_3F; |
#endif |
#ifdef DEST_4UB |
TAB(_4ub)[SZ][SRC_IDX] = DEST_4UB; |
#endif |
#ifdef DEST_4US |
TAB(_4us)[SZ][SRC_IDX] = DEST_4US; |
#endif |
#ifdef DEST_4F |
TAB(_4f)[SZ][SRC_IDX] = DEST_4F; |
#endif |
} |
#undef INIT |
#undef DEST_1UI |
#undef DEST_1UB |
#undef DEST_4UB |
#undef DEST_4US |
#undef DEST_3F |
#undef DEST_4F |
#undef DEST_1F |
#undef SZ |
#undef TAG |
/shark/trunk/ports/mesa/src/math/m_clip_tmp.h |
---|
0,0 → 1,229 |
/* $Id: m_clip_tmp.h,v 1.1 2003-02-28 11:48:04 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 4.0.3 |
* |
* 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. |
*/ |
/* |
* New (3.1) transformation code written by Keith Whitwell. |
*/ |
/* KW: a clever asm implementation would nestle integer versions |
* of the outcode calculation underneath the division. Gcc won't |
* do this, strangely enough, so I only do the divide in |
* the case where the cliptest passes. This isn't essential, |
* and an asm implementation needn't replicate that behaviour. |
*/ |
static GLvector4f * _XFORMAPI TAG(cliptest_points4)( GLvector4f *clip_vec, |
GLvector4f *proj_vec, |
GLubyte clipMask[], |
GLubyte *orMask, |
GLubyte *andMask ) |
{ |
const GLuint stride = clip_vec->stride; |
const GLfloat *from = (GLfloat *)clip_vec->start; |
const GLuint count = clip_vec->count; |
GLuint c = 0; |
GLfloat (*vProj)[4] = (GLfloat (*)[4])proj_vec->start; |
GLubyte tmpAndMask = *andMask; |
GLubyte tmpOrMask = *orMask; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat cx = from[0]; |
const GLfloat cy = from[1]; |
const GLfloat cz = from[2]; |
const GLfloat cw = from[3]; |
#if defined(macintosh) || defined(__powerpc__) |
/* on powerpc cliptest is 17% faster in this way. */ |
GLuint mask; |
mask = (((cw < cx) << CLIP_RIGHT_SHIFT)); |
mask |= (((cw < -cx) << CLIP_LEFT_SHIFT)); |
mask |= (((cw < cy) << CLIP_TOP_SHIFT)); |
mask |= (((cw < -cy) << CLIP_BOTTOM_SHIFT)); |
mask |= (((cw < cz) << CLIP_FAR_SHIFT)); |
mask |= (((cw < -cz) << CLIP_NEAR_SHIFT)); |
#else /* !defined(macintosh)) */ |
GLubyte mask = 0; |
if (-cx + cw < 0) mask |= CLIP_RIGHT_BIT; |
if ( cx + cw < 0) mask |= CLIP_LEFT_BIT; |
if (-cy + cw < 0) mask |= CLIP_TOP_BIT; |
if ( cy + cw < 0) mask |= CLIP_BOTTOM_BIT; |
if (-cz + cw < 0) mask |= CLIP_FAR_BIT; |
if ( cz + cw < 0) mask |= CLIP_NEAR_BIT; |
#endif /* defined(macintosh) */ |
clipMask[i] = mask; |
if (mask) { |
c++; |
tmpAndMask &= mask; |
tmpOrMask |= mask; |
vProj[i][0] = 0; |
vProj[i][1] = 0; |
vProj[i][2] = 0; |
vProj[i][3] = 1; |
} else { |
GLfloat oow = 1.0F / cw; |
vProj[i][0] = cx * oow; |
vProj[i][1] = cy * oow; |
vProj[i][2] = cz * oow; |
vProj[i][3] = oow; |
} |
} |
*orMask = tmpOrMask; |
*andMask = (GLubyte) (c < count ? 0 : tmpAndMask); |
proj_vec->flags |= VEC_SIZE_4; |
proj_vec->size = 4; |
proj_vec->count = clip_vec->count; |
return proj_vec; |
} |
static GLvector4f * _XFORMAPI TAG(cliptest_np_points4)( GLvector4f *clip_vec, |
GLvector4f *proj_vec, |
GLubyte clipMask[], |
GLubyte *orMask, |
GLubyte *andMask ) |
{ |
const GLuint stride = clip_vec->stride; |
const GLuint count = clip_vec->count; |
const GLfloat *from = (GLfloat *)clip_vec->start; |
GLuint c = 0; |
GLubyte tmpAndMask = *andMask; |
GLubyte tmpOrMask = *orMask; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat cx = from[0]; |
const GLfloat cy = from[1]; |
const GLfloat cz = from[2]; |
const GLfloat cw = from[3]; |
#if defined(macintosh) || defined(__powerpc__) |
/* on powerpc cliptest is 17% faster in this way. */ |
GLuint mask; |
mask = (((cw < cx) << CLIP_RIGHT_SHIFT)); |
mask |= (((cw < -cx) << CLIP_LEFT_SHIFT)); |
mask |= (((cw < cy) << CLIP_TOP_SHIFT)); |
mask |= (((cw < -cy) << CLIP_BOTTOM_SHIFT)); |
mask |= (((cw < cz) << CLIP_FAR_SHIFT)); |
mask |= (((cw < -cz) << CLIP_NEAR_SHIFT)); |
#else /* !defined(macintosh)) */ |
GLubyte mask = 0; |
if (-cx + cw < 0) mask |= CLIP_RIGHT_BIT; |
if ( cx + cw < 0) mask |= CLIP_LEFT_BIT; |
if (-cy + cw < 0) mask |= CLIP_TOP_BIT; |
if ( cy + cw < 0) mask |= CLIP_BOTTOM_BIT; |
if (-cz + cw < 0) mask |= CLIP_FAR_BIT; |
if ( cz + cw < 0) mask |= CLIP_NEAR_BIT; |
#endif /* defined(macintosh) */ |
clipMask[i] = mask; |
if (mask) { |
c++; |
tmpAndMask &= mask; |
tmpOrMask |= mask; |
} |
} |
*orMask = tmpOrMask; |
*andMask = (GLubyte) (c < count ? 0 : tmpAndMask); |
return clip_vec; |
} |
static GLvector4f * _XFORMAPI TAG(cliptest_points3)( GLvector4f *clip_vec, |
GLvector4f *proj_vec, |
GLubyte clipMask[], |
GLubyte *orMask, |
GLubyte *andMask ) |
{ |
const GLuint stride = clip_vec->stride; |
const GLuint count = clip_vec->count; |
const GLfloat *from = (GLfloat *)clip_vec->start; |
GLubyte tmpOrMask = *orMask; |
GLubyte tmpAndMask = *andMask; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat cx = from[0], cy = from[1], cz = from[2]; |
GLubyte mask = 0; |
if (cx > 1.0) mask |= CLIP_RIGHT_BIT; |
else if (cx < -1.0) mask |= CLIP_LEFT_BIT; |
if (cy > 1.0) mask |= CLIP_TOP_BIT; |
else if (cy < -1.0) mask |= CLIP_BOTTOM_BIT; |
if (cz > 1.0) mask |= CLIP_FAR_BIT; |
else if (cz < -1.0) mask |= CLIP_NEAR_BIT; |
clipMask[i] = mask; |
tmpOrMask |= mask; |
tmpAndMask &= mask; |
} |
*orMask = tmpOrMask; |
*andMask = tmpAndMask; |
return clip_vec; |
} |
static GLvector4f * _XFORMAPI TAG(cliptest_points2)( GLvector4f *clip_vec, |
GLvector4f *proj_vec, |
GLubyte clipMask[], |
GLubyte *orMask, |
GLubyte *andMask ) |
{ |
const GLuint stride = clip_vec->stride; |
const GLuint count = clip_vec->count; |
const GLfloat *from = (GLfloat *)clip_vec->start; |
GLubyte tmpOrMask = *orMask; |
GLubyte tmpAndMask = *andMask; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat cx = from[0], cy = from[1]; |
GLubyte mask = 0; |
if (cx > 1.0) mask |= CLIP_RIGHT_BIT; |
else if (cx < -1.0) mask |= CLIP_LEFT_BIT; |
if (cy > 1.0) mask |= CLIP_TOP_BIT; |
else if (cy < -1.0) mask |= CLIP_BOTTOM_BIT; |
clipMask[i] = mask; |
tmpOrMask |= mask; |
tmpAndMask &= mask; |
} |
*orMask = tmpOrMask; |
*andMask = tmpAndMask; |
return clip_vec; |
} |
static void TAG(init_c_cliptest)( void ) |
{ |
_mesa_clip_tab[4] = TAG(cliptest_points4); |
_mesa_clip_tab[3] = TAG(cliptest_points3); |
_mesa_clip_tab[2] = TAG(cliptest_points2); |
_mesa_clip_np_tab[4] = TAG(cliptest_np_points4); |
_mesa_clip_np_tab[3] = TAG(cliptest_points3); |
_mesa_clip_np_tab[2] = TAG(cliptest_points2); |
} |
/shark/trunk/ports/mesa/src/math/m_xform_tmp.h |
---|
0,0 → 1,807 |
/* $Id: m_xform_tmp.h,v 1.1 2003-02-28 11:48:05 pj Exp $ */ |
/* |
* Mesa 3-D graphics library |
* Version: 3.5 |
* |
* Copyright (C) 1999-2001 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. |
*/ |
/* |
* New (3.1) transformation code written by Keith Whitwell. |
*/ |
/*---------------------------------------------------------------------- |
* Begin Keith's new code |
* |
*---------------------------------------------------------------------- |
*/ |
/* KW: Fixed stride, now measured in bytes as is the OpenGL array stride. |
*/ |
/* KW: These are now parameterized to produce two versions, one |
* which transforms all incoming points, and a second which |
* takes notice of a cullmask array, and only transforms |
* unculled vertices. |
*/ |
/* KW: 1-vectors can sneak into the texture pipeline via the array |
* interface. These functions are here because I want consistant |
* treatment of the vertex sizes and a lazy strategy for |
* cleaning unused parts of the vector, and so as not to exclude |
* them from the vertex array interface. |
* |
* Under our current analysis of matrices, there is no way that |
* the product of a matrix and a 1-vector can remain a 1-vector, |
* with the exception of the identity transform. |
*/ |
/* KW: No longer zero-pad outgoing vectors. Now that external |
* vectors can get into the pipeline we cannot ever assume |
* that there is more to a vector than indicated by its |
* size. |
*/ |
/* KW: Now uses clipmask and a flag to allow us to skip both/either |
* cliped and/or culled vertices. |
*/ |
/* GH: Not any more -- it's easier (and faster) to just process the |
* entire vector. Clipping and culling are handled further down |
* the pipe, most often during or after the conversion to some |
* driver-specific vertex format. |
*/ |
static void _XFORMAPI |
TAG(transform_points1_general)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m12 = m[12]; |
const GLfloat m1 = m[1], m13 = m[13]; |
const GLfloat m2 = m[2], m14 = m[14]; |
const GLfloat m3 = m[3], m15 = m[15]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0]; |
to[i][0] = m0 * ox + m12; |
to[i][1] = m1 * ox + m13; |
to[i][2] = m2 * ox + m14; |
to[i][3] = m3 * ox + m15; |
} |
to_vec->size = 4; |
to_vec->flags |= VEC_SIZE_4; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points1_identity)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLuint count = from_vec->count; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint i; |
if (to_vec == from_vec) return; |
STRIDE_LOOP { |
to[i][0] = from[0]; |
} |
to_vec->size = 1; |
to_vec->flags |= VEC_SIZE_1; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points1_2d)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m1 = m[1]; |
const GLfloat m12 = m[12], m13 = m[13]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0]; |
to[i][0] = m0 * ox + m12; |
to[i][1] = m1 * ox + m13; |
} |
to_vec->size = 2; |
to_vec->flags |= VEC_SIZE_2; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points1_2d_no_rot)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m12 = m[12], m13 = m[13]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0]; |
to[i][0] = m0 * ox + m12; |
to[i][1] = m13; |
} |
to_vec->size = 2; |
to_vec->flags |= VEC_SIZE_2; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points1_3d)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m1 = m[1], m2 = m[2]; |
const GLfloat m12 = m[12], m13 = m[13], m14 = m[14]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0]; |
to[i][0] = m0 * ox + m12; |
to[i][1] = m1 * ox + m13; |
to[i][2] = m2 * ox + m14; |
} |
to_vec->size = 3; |
to_vec->flags |= VEC_SIZE_3; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points1_3d_no_rot)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0]; |
const GLfloat m12 = m[12], m13 = m[13], m14 = m[14]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0]; |
to[i][0] = m0 * ox + m12; |
to[i][1] = m13; |
to[i][2] = m14; |
} |
to_vec->size = 3; |
to_vec->flags |= VEC_SIZE_3; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points1_perspective)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m14 = m[14]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0]; |
to[i][0] = m0 * ox ; |
to[i][1] = 0 ; |
to[i][2] = m14; |
to[i][3] = 0; |
} |
to_vec->size = 4; |
to_vec->flags |= VEC_SIZE_4; |
to_vec->count = from_vec->count; |
} |
/* 2-vectors, which are a lot more relevant than 1-vectors, are |
* present early in the geometry pipeline and throughout the |
* texture pipeline. |
*/ |
static void _XFORMAPI |
TAG(transform_points2_general)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m4 = m[4], m12 = m[12]; |
const GLfloat m1 = m[1], m5 = m[5], m13 = m[13]; |
const GLfloat m2 = m[2], m6 = m[6], m14 = m[14]; |
const GLfloat m3 = m[3], m7 = m[7], m15 = m[15]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1]; |
to[i][0] = m0 * ox + m4 * oy + m12; |
to[i][1] = m1 * ox + m5 * oy + m13; |
to[i][2] = m2 * ox + m6 * oy + m14; |
to[i][3] = m3 * ox + m7 * oy + m15; |
} |
to_vec->size = 4; |
to_vec->flags |= VEC_SIZE_4; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points2_identity)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
GLuint i; |
if (to_vec == from_vec) return; |
STRIDE_LOOP { |
to[i][0] = from[0]; |
to[i][1] = from[1]; |
} |
to_vec->size = 2; |
to_vec->flags |= VEC_SIZE_2; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points2_2d)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5]; |
const GLfloat m12 = m[12], m13 = m[13]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1]; |
to[i][0] = m0 * ox + m4 * oy + m12; |
to[i][1] = m1 * ox + m5 * oy + m13; |
} |
to_vec->size = 2; |
to_vec->flags |= VEC_SIZE_2; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points2_2d_no_rot)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1]; |
to[i][0] = m0 * ox + m12; |
to[i][1] = m5 * oy + m13; |
} |
to_vec->size = 2; |
to_vec->flags |= VEC_SIZE_2; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points2_3d)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5]; |
const GLfloat m6 = m[6], m12 = m[12], m13 = m[13], m14 = m[14]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1]; |
to[i][0] = m0 * ox + m4 * oy + m12; |
to[i][1] = m1 * ox + m5 * oy + m13; |
to[i][2] = m2 * ox + m6 * oy + m14; |
} |
to_vec->size = 3; |
to_vec->flags |= VEC_SIZE_3; |
to_vec->count = from_vec->count; |
} |
/* I would actually say this was a fairly important function, from |
* a texture transformation point of view. |
*/ |
static void _XFORMAPI |
TAG(transform_points2_3d_no_rot)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m5 = m[5]; |
const GLfloat m12 = m[12], m13 = m[13], m14 = m[14]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1]; |
to[i][0] = m0 * ox + m12; |
to[i][1] = m5 * oy + m13; |
to[i][2] = m14; |
} |
if (m14 == 0) { |
to_vec->size = 2; |
to_vec->flags |= VEC_SIZE_2; |
} else { |
to_vec->size = 3; |
to_vec->flags |= VEC_SIZE_3; |
} |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points2_perspective)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m5 = m[5], m14 = m[14]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1]; |
to[i][0] = m0 * ox ; |
to[i][1] = m5 * oy ; |
to[i][2] = m14; |
to[i][3] = 0; |
} |
to_vec->size = 4; |
to_vec->flags |= VEC_SIZE_4; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points3_general)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m4 = m[4], m8 = m[8], m12 = m[12]; |
const GLfloat m1 = m[1], m5 = m[5], m9 = m[9], m13 = m[13]; |
const GLfloat m2 = m[2], m6 = m[6], m10 = m[10], m14 = m[14]; |
const GLfloat m3 = m[3], m7 = m[7], m11 = m[11], m15 = m[15]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1], oz = from[2]; |
to[i][0] = m0 * ox + m4 * oy + m8 * oz + m12; |
to[i][1] = m1 * ox + m5 * oy + m9 * oz + m13; |
to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14; |
to[i][3] = m3 * ox + m7 * oy + m11 * oz + m15; |
} |
to_vec->size = 4; |
to_vec->flags |= VEC_SIZE_4; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points3_identity)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
GLuint i; |
if (to_vec == from_vec) return; |
STRIDE_LOOP { |
to[i][0] = from[0]; |
to[i][1] = from[1]; |
to[i][2] = from[2]; |
} |
to_vec->size = 3; |
to_vec->flags |= VEC_SIZE_3; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points3_2d)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5]; |
const GLfloat m12 = m[12], m13 = m[13]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1], oz = from[2]; |
to[i][0] = m0 * ox + m4 * oy + m12 ; |
to[i][1] = m1 * ox + m5 * oy + m13 ; |
to[i][2] = + oz ; |
} |
to_vec->size = 3; |
to_vec->flags |= VEC_SIZE_3; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points3_2d_no_rot)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1], oz = from[2]; |
to[i][0] = m0 * ox + m12 ; |
to[i][1] = m5 * oy + m13 ; |
to[i][2] = + oz ; |
} |
to_vec->size = 3; |
to_vec->flags |= VEC_SIZE_3; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points3_3d)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5]; |
const GLfloat m6 = m[6], m8 = m[8], m9 = m[9], m10 = m[10]; |
const GLfloat m12 = m[12], m13 = m[13], m14 = m[14]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1], oz = from[2]; |
to[i][0] = m0 * ox + m4 * oy + m8 * oz + m12 ; |
to[i][1] = m1 * ox + m5 * oy + m9 * oz + m13 ; |
to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 ; |
} |
to_vec->size = 3; |
to_vec->flags |= VEC_SIZE_3; |
to_vec->count = from_vec->count; |
} |
/* previously known as ortho... |
*/ |
static void _XFORMAPI |
TAG(transform_points3_3d_no_rot)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m5 = m[5]; |
const GLfloat m10 = m[10], m12 = m[12], m13 = m[13], m14 = m[14]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1], oz = from[2]; |
to[i][0] = m0 * ox + m12 ; |
to[i][1] = m5 * oy + m13 ; |
to[i][2] = m10 * oz + m14 ; |
} |
to_vec->size = 3; |
to_vec->flags |= VEC_SIZE_3; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points3_perspective)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m5 = m[5], m8 = m[8], m9 = m[9]; |
const GLfloat m10 = m[10], m14 = m[14]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1], oz = from[2]; |
to[i][0] = m0 * ox + m8 * oz ; |
to[i][1] = m5 * oy + m9 * oz ; |
to[i][2] = m10 * oz + m14 ; |
to[i][3] = -oz ; |
} |
to_vec->size = 4; |
to_vec->flags |= VEC_SIZE_4; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points4_general)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m4 = m[4], m8 = m[8], m12 = m[12]; |
const GLfloat m1 = m[1], m5 = m[5], m9 = m[9], m13 = m[13]; |
const GLfloat m2 = m[2], m6 = m[6], m10 = m[10], m14 = m[14]; |
const GLfloat m3 = m[3], m7 = m[7], m11 = m[11], m15 = m[15]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3]; |
to[i][0] = m0 * ox + m4 * oy + m8 * oz + m12 * ow; |
to[i][1] = m1 * ox + m5 * oy + m9 * oz + m13 * ow; |
to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 * ow; |
to[i][3] = m3 * ox + m7 * oy + m11 * oz + m15 * ow; |
} |
to_vec->size = 4; |
to_vec->flags |= VEC_SIZE_4; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points4_identity)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
GLuint i; |
if (to_vec == from_vec) return; |
STRIDE_LOOP { |
to[i][0] = from[0]; |
to[i][1] = from[1]; |
to[i][2] = from[2]; |
to[i][3] = from[3]; |
} |
to_vec->size = 4; |
to_vec->flags |= VEC_SIZE_4; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points4_2d)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m1 = m[1], m4 = m[4], m5 = m[5]; |
const GLfloat m12 = m[12], m13 = m[13]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3]; |
to[i][0] = m0 * ox + m4 * oy + m12 * ow; |
to[i][1] = m1 * ox + m5 * oy + m13 * ow; |
to[i][2] = + oz ; |
to[i][3] = ow; |
} |
to_vec->size = 4; |
to_vec->flags |= VEC_SIZE_4; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points4_2d_no_rot)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m5 = m[5], m12 = m[12], m13 = m[13]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3]; |
to[i][0] = m0 * ox + m12 * ow; |
to[i][1] = m5 * oy + m13 * ow; |
to[i][2] = + oz ; |
to[i][3] = ow; |
} |
to_vec->size = 4; |
to_vec->flags |= VEC_SIZE_4; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points4_3d)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m1 = m[1], m2 = m[2], m4 = m[4], m5 = m[5]; |
const GLfloat m6 = m[6], m8 = m[8], m9 = m[9], m10 = m[10]; |
const GLfloat m12 = m[12], m13 = m[13], m14 = m[14]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3]; |
to[i][0] = m0 * ox + m4 * oy + m8 * oz + m12 * ow; |
to[i][1] = m1 * ox + m5 * oy + m9 * oz + m13 * ow; |
to[i][2] = m2 * ox + m6 * oy + m10 * oz + m14 * ow; |
to[i][3] = ow; |
} |
to_vec->size = 4; |
to_vec->flags |= VEC_SIZE_4; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points4_3d_no_rot)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m5 = m[5]; |
const GLfloat m10 = m[10], m12 = m[12], m13 = m[13], m14 = m[14]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3]; |
to[i][0] = m0 * ox + m12 * ow; |
to[i][1] = m5 * oy + m13 * ow; |
to[i][2] = m10 * oz + m14 * ow; |
to[i][3] = ow; |
} |
to_vec->size = 4; |
to_vec->flags |= VEC_SIZE_4; |
to_vec->count = from_vec->count; |
} |
static void _XFORMAPI |
TAG(transform_points4_perspective)( GLvector4f *to_vec, |
const GLfloat m[16], |
const GLvector4f *from_vec ) |
{ |
const GLuint stride = from_vec->stride; |
GLfloat *from = from_vec->start; |
GLfloat (*to)[4] = (GLfloat (*)[4])to_vec->start; |
GLuint count = from_vec->count; |
const GLfloat m0 = m[0], m5 = m[5], m8 = m[8], m9 = m[9]; |
const GLfloat m10 = m[10], m14 = m[14]; |
GLuint i; |
STRIDE_LOOP { |
const GLfloat ox = from[0], oy = from[1], oz = from[2], ow = from[3]; |
to[i][0] = m0 * ox + m8 * oz ; |
to[i][1] = m5 * oy + m9 * oz ; |
to[i][2] = m10 * oz + m14 * ow ; |
to[i][3] = -oz ; |
} |
to_vec->size = 4; |
to_vec->flags |= VEC_SIZE_4; |
to_vec->count = from_vec->count; |
} |
static transform_func _XFORMAPI TAG(transform_tab_1)[7]; |
static transform_func _XFORMAPI TAG(transform_tab_2)[7]; |
static transform_func _XFORMAPI TAG(transform_tab_3)[7]; |
static transform_func _XFORMAPI TAG(transform_tab_4)[7]; |
/* Similar functions could be called several times, with more highly |
* optimized routines overwriting the arrays. This only occurs during |
* startup. |
*/ |
static void _XFORMAPI TAG(init_c_transformations)( void ) |
{ |
#define TAG_TAB _mesa_transform_tab |
#define TAG_TAB_1 TAG(transform_tab_1) |
#define TAG_TAB_2 TAG(transform_tab_2) |
#define TAG_TAB_3 TAG(transform_tab_3) |
#define TAG_TAB_4 TAG(transform_tab_4) |
TAG_TAB[1] = TAG_TAB_1; |
TAG_TAB[2] = TAG_TAB_2; |
TAG_TAB[3] = TAG_TAB_3; |
TAG_TAB[4] = TAG_TAB_4; |
/* 1-D points (ie texcoords) */ |
TAG_TAB_1[MATRIX_GENERAL] = TAG(transform_points1_general); |
TAG_TAB_1[MATRIX_IDENTITY] = TAG(transform_points1_identity); |
TAG_TAB_1[MATRIX_3D_NO_ROT] = TAG(transform_points1_3d_no_rot); |
TAG_TAB_1[MATRIX_PERSPECTIVE] = TAG(transform_points1_perspective); |
TAG_TAB_1[MATRIX_2D] = TAG(transform_points1_2d); |
TAG_TAB_1[MATRIX_2D_NO_ROT] = TAG(transform_points1_2d_no_rot); |
TAG_TAB_1[MATRIX_3D] = TAG(transform_points1_3d); |
/* 2-D points */ |
TAG_TAB_2[MATRIX_GENERAL] = TAG(transform_points2_general); |
TAG_TAB_2[MATRIX_IDENTITY] = TAG(transform_points2_identity); |
TAG_TAB_2[MATRIX_3D_NO_ROT] = TAG(transform_points2_3d_no_rot); |
TAG_TAB_2[MATRIX_PERSPECTIVE] = TAG(transform_points2_perspective); |
TAG_TAB_2[MATRIX_2D] = TAG(transform_points2_2d); |
TAG_TAB_2[MATRIX_2D_NO_ROT] = TAG(transform_points2_2d_no_rot); |
TAG_TAB_2[MATRIX_3D] = TAG(transform_points2_3d); |
/* 3-D points */ |
TAG_TAB_3[MATRIX_GENERAL] = TAG(transform_points3_general); |
TAG_TAB_3[MATRIX_IDENTITY] = TAG(transform_points3_identity); |
TAG_TAB_3[MATRIX_3D_NO_ROT] = TAG(transform_points3_3d_no_rot); |
TAG_TAB_3[MATRIX_PERSPECTIVE] = TAG(transform_points3_perspective); |
TAG_TAB_3[MATRIX_2D] = TAG(transform_points3_2d); |
TAG_TAB_3[MATRIX_2D_NO_ROT] = TAG(transform_points3_2d_no_rot); |
TAG_TAB_3[MATRIX_3D] = TAG(transform_points3_3d); |
/* 4-D points */ |
TAG_TAB_4[MATRIX_GENERAL] = TAG(transform_points4_general); |
TAG_TAB_4[MATRIX_IDENTITY] = TAG(transform_points4_identity); |
TAG_TAB_4[MATRIX_3D_NO_ROT] = TAG(transform_points4_3d_no_rot); |
TAG_TAB_4[MATRIX_PERSPECTIVE] = TAG(transform_points4_perspective); |
TAG_TAB_4[MATRIX_2D] = TAG(transform_points4_2d); |
TAG_TAB_4[MATRIX_2D_NO_ROT] = TAG(transform_points4_2d_no_rot); |
TAG_TAB_4[MATRIX_3D] = TAG(transform_points4_3d); |
#undef TAG_TAB |
#undef TAG_TAB_1 |
#undef TAG_TAB_2 |
#undef TAG_TAB_3 |
#undef TAG_TAB_4 |
} |
/shark/trunk/ports/mesa/src/math/m_debug_norm.c |
---|
0,0 → 1,381 |
/* $Id: m_debug_norm.c,v 1.1 2003-02-28 11:48:05 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: |
* Gareth Hughes |
*/ |
#include "glheader.h" |
#include "context.h" |
#include "macros.h" |
#include "imports.h" |
#include "mmath.h" |
#include "m_matrix.h" |
#include "m_xform.h" |
#include "m_debug.h" |
#include "m_debug_util.h" |
#ifdef DEBUG /* This code only used for debugging */ |
static int m_norm_identity[16] = { |
ONE, NIL, NIL, NIL, |
NIL, ONE, NIL, NIL, |
NIL, NIL, ONE, NIL, |
NIL, NIL, NIL, NIL |
}; |
static int m_norm_general[16] = { |
VAR, VAR, VAR, NIL, |
VAR, VAR, VAR, NIL, |
VAR, VAR, VAR, NIL, |
NIL, NIL, NIL, NIL |
}; |
static int m_norm_no_rot[16] = { |
VAR, NIL, NIL, NIL, |
NIL, VAR, NIL, NIL, |
NIL, NIL, VAR, NIL, |
NIL, NIL, NIL, NIL |
}; |
static int *norm_templates[8] = { |
m_norm_no_rot, |
m_norm_no_rot, |
m_norm_no_rot, |
m_norm_general, |
m_norm_general, |
m_norm_general, |
m_norm_identity, |
m_norm_identity |
}; |
static int norm_types[8] = { |
NORM_TRANSFORM_NO_ROT, |
NORM_TRANSFORM_NO_ROT | NORM_RESCALE, |
NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE, |
NORM_TRANSFORM, |
NORM_TRANSFORM | NORM_RESCALE, |
NORM_TRANSFORM | NORM_NORMALIZE, |
NORM_RESCALE, |
NORM_NORMALIZE |
}; |
static int norm_scale_types[8] = { /* rescale factor */ |
NIL, /* NIL disables rescaling */ |
VAR, |
NIL, |
NIL, |
VAR, |
NIL, |
VAR, |
NIL |
}; |
static int norm_normalize_types[8] = { /* normalizing ?? (no = 0) */ |
0, |
0, |
1, |
0, |
0, |
1, |
0, |
1 |
}; |
static char *norm_strings[8] = { |
"NORM_TRANSFORM_NO_ROT", |
"NORM_TRANSFORM_NO_ROT | NORM_RESCALE", |
"NORM_TRANSFORM_NO_ROT | NORM_NORMALIZE", |
"NORM_TRANSFORM", |
"NORM_TRANSFORM | NORM_RESCALE", |
"NORM_TRANSFORM | NORM_NORMALIZE", |
"NORM_RESCALE", |
"NORM_NORMALIZE" |
}; |
/* ============================================================= |
* Reference transformations |
*/ |
static void ref_norm_transform_rescale( const GLmatrix *mat, |
GLfloat scale, |
const GLvector4f *in, |
const GLfloat *lengths, |
GLvector4f *dest ) |
{ |
GLuint i; |
const GLfloat *s = in->start; |
const GLfloat *m = mat->inv; |
GLfloat (*out)[4] = (GLfloat (*)[4]) dest->start; |
(void) lengths; |
for ( i = 0 ; i < in->count ; i++ ) { |
GLfloat t[3]; |
TRANSFORM_NORMAL( t, s, m ); |
SCALE_SCALAR_3V( out[i], scale, t ); |
s = (GLfloat *)((char *)s + in->stride); |
} |
} |
static void ref_norm_transform_normalize( const GLmatrix *mat, |
GLfloat scale, |
const GLvector4f *in, |
const GLfloat *lengths, |
GLvector4f *dest ) |
{ |
GLuint i; |
const GLfloat *s = in->start; |
const GLfloat *m = mat->inv; |
GLfloat (*out)[4] = (GLfloat (*)[4]) dest->start; |
for ( i = 0 ; i < in->count ; i++ ) { |
GLfloat t[3]; |
TRANSFORM_NORMAL( t, s, m ); |
if ( !lengths ) { |
GLfloat len = LEN_SQUARED_3FV( t ); |
if ( len > 1e-20 ) { |
/* Hmmm, don't know how we could test the precalculated |
* length case... |
*/ |
scale = 1.0 / sqrt( len ); |
SCALE_SCALAR_3V( out[i], scale, t ); |
} else { |
out[i][0] = out[i][1] = out[i][2] = 0; |
} |
} else { |
scale = lengths[i];; |
SCALE_SCALAR_3V( out[i], scale, t ); |
} |
s = (GLfloat *)((char *)s + in->stride); |
} |
} |
/* ============================================================= |
* Normal transformation tests |
*/ |
static void init_matrix( GLfloat *m ) |
{ |
m[0] = 63.0; m[4] = 43.0; m[ 8] = 29.0; m[12] = 43.0; |
m[1] = 55.0; m[5] = 17.0; m[ 9] = 31.0; m[13] = 7.0; |
m[2] = 44.0; m[6] = 9.0; m[10] = 7.0; m[14] = 3.0; |
m[3] = 11.0; m[7] = 23.0; m[11] = 91.0; m[15] = 9.0; |
} |
static int test_norm_function( normal_func func, int mtype, long *cycles ) |
{ |
GLvector4f source[1], dest[1], dest2[1], ref[1], ref2[1]; |
GLmatrix mat[1]; |
GLfloat s[TEST_COUNT][5], d[TEST_COUNT][4], r[TEST_COUNT][4]; |
GLfloat d2[TEST_COUNT][4], r2[TEST_COUNT][4], length[TEST_COUNT]; |
GLfloat scale; |
GLfloat *m; |
int i, j; |
#ifdef RUN_DEBUG_BENCHMARK |
int cycle_i; /* the counter for the benchmarks we run */ |
#endif |
(void) cycles; |
mat->m = (GLfloat *) ALIGN_MALLOC( 16 * sizeof(GLfloat), 16 ); |
mat->inv = m = mat->m; |
init_matrix( m ); |
scale = 1.0F + rnd () * norm_scale_types[mtype]; |
for ( i = 0 ; i < 4 ; i++ ) { |
for ( j = 0 ; j < 4 ; j++ ) { |
switch ( norm_templates[mtype][i * 4 + j] ) { |
case NIL: |
m[j * 4 + i] = 0.0; |
break; |
case ONE: |
m[j * 4 + i] = 1.0; |
break; |
case NEG: |
m[j * 4 + i] = -1.0; |
break; |
case VAR: |
break; |
default: |
abort(); |
} |
} |
} |
for ( i = 0 ; i < TEST_COUNT ; i++ ) { |
ASSIGN_3V( d[i], 0.0, 0.0, 0.0 ); |
ASSIGN_3V( s[i], 0.0, 0.0, 0.0 ); |
ASSIGN_3V( d2[i], 0.0, 0.0, 0.0 ); |
for ( j = 0 ; j < 3 ; j++ ) |
s[i][j] = rnd(); |
length[i] = 1 / sqrt( LEN_SQUARED_3FV( s[i] ) ); |
} |
source->data = (GLfloat(*)[4]) s; |
source->start = (GLfloat *) s; |
source->count = TEST_COUNT; |
source->stride = sizeof(s[0]); |
source->flags = 0; |
dest->data = d; |
dest->start = (GLfloat *) d; |
dest->count = TEST_COUNT; |
dest->stride = sizeof(float[4]); |
dest->flags = 0; |
dest2->data = d2; |
dest2->start = (GLfloat *) d2; |
dest2->count = TEST_COUNT; |
dest2->stride = sizeof(float[4]); |
dest2->flags = 0; |
ref->data = r; |
ref->start = (GLfloat *) r; |
ref->count = TEST_COUNT; |
ref->stride = sizeof(float[4]); |
ref->flags = 0; |
ref2->data = r2; |
ref2->start = (GLfloat *) r2; |
ref2->count = TEST_COUNT; |
ref2->stride = sizeof(float[4]); |
ref2->flags = 0; |
if ( norm_normalize_types[mtype] == 0 ) { |
ref_norm_transform_rescale( mat, scale, source, NULL, ref ); |
} else { |
ref_norm_transform_normalize( mat, scale, source, NULL, ref ); |
ref_norm_transform_normalize( mat, scale, source, length, ref2 ); |
} |
if ( mesa_profile ) { |
BEGIN_RACE( *cycles ); |
func( mat, scale, source, NULL, dest ); |
END_RACE( *cycles ); |
func( mat, scale, source, length, dest2 ); |
} else { |
func( mat, scale, source, NULL, dest ); |
func( mat, scale, source, length, dest2 ); |
} |
for ( i = 0 ; i < TEST_COUNT ; i++ ) { |
for ( j = 0 ; j < 3 ; j++ ) { |
if ( significand_match( d[i][j], r[i][j] ) < REQUIRED_PRECISION ) { |
_mesa_printf(NULL, "-----------------------------\n" ); |
_mesa_printf(NULL, "(i = %i, j = %i)\n", i, j ); |
_mesa_printf(NULL, "%f \t %f \t [ratio = %e - %i bit missed]\n", |
d[i][0], r[i][0], r[i][0]/d[i][0], |
MAX_PRECISION - significand_match( d[i][0], r[i][0] ) ); |
_mesa_printf(NULL, "%f \t %f \t [ratio = %e - %i bit missed]\n", |
d[i][1], r[i][1], r[i][1]/d[i][1], |
MAX_PRECISION - significand_match( d[i][1], r[i][1] ) ); |
_mesa_printf(NULL, "%f \t %f \t [ratio = %e - %i bit missed]\n", |
d[i][2], r[i][2], r[i][2]/d[i][2], |
MAX_PRECISION - significand_match( d[i][2], r[i][2] ) ); |
return 0; |
} |
if ( norm_normalize_types[mtype] != 0 ) { |
if ( significand_match( d2[i][j], r2[i][j] ) < REQUIRED_PRECISION ) { |
_mesa_printf(NULL, "------------------- precalculated length case ------\n" ); |
_mesa_printf(NULL, "(i = %i, j = %i)\n", i, j ); |
_mesa_printf(NULL, "%f \t %f \t [ratio = %e - %i bit missed]\n", |
d2[i][0], r2[i][0], r2[i][0]/d2[i][0], |
MAX_PRECISION - significand_match( d2[i][0], r2[i][0] ) ); |
_mesa_printf(NULL, "%f \t %f \t [ratio = %e - %i bit missed]\n", |
d2[i][1], r2[i][1], r2[i][1]/d2[i][1], |
MAX_PRECISION - significand_match( d2[i][1], r2[i][1] ) ); |
_mesa_printf(NULL, "%f \t %f \t [ratio = %e - %i bit missed]\n", |
d2[i][2], r2[i][2], r2[i][2]/d2[i][2], |
MAX_PRECISION - significand_match( d2[i][2], r2[i][2] ) ); |
return 0; |
} |
} |
} |
} |
ALIGN_FREE( mat->m ); |
return 1; |
} |
void _math_test_all_normal_transform_functions( char *description ) |
{ |
int mtype; |
long benchmark_tab[0xf]; |
static int first_time = 1; |
if ( first_time ) { |
first_time = 0; |
mesa_profile = getenv( "MESA_PROFILE" ); |
} |
#ifdef RUN_DEBUG_BENCHMARK |
if ( mesa_profile ) { |
if ( !counter_overhead ) { |
INIT_COUNTER(); |
_mesa_printf(NULL, "counter overhead: %ld cycles\n\n", counter_overhead ); |
} |
_mesa_printf(NULL, "normal transform results after hooking in %s functions:\n", |
description ); |
_mesa_printf(NULL, "\n-------------------------------------------------------\n" ); |
} |
#endif |
for ( mtype = 0 ; mtype < 8 ; mtype++ ) { |
normal_func func = _mesa_normal_tab[norm_types[mtype]]; |
long *cycles = &benchmark_tab[mtype]; |
if ( test_norm_function( func, mtype, cycles ) == 0 ) { |
char buf[100]; |
_mesa_sprintf(NULL, buf, "_mesa_normal_tab[0][%s] failed test (%s)", |
norm_strings[mtype], description ); |
_mesa_problem( NULL, buf ); |
} |
#ifdef RUN_DEBUG_BENCHMARK |
if ( mesa_profile ) { |
_mesa_printf(NULL, " %li\t", benchmark_tab[mtype] ); |
_mesa_printf(NULL, " | [%s]\n", norm_strings[mtype] ); |
} |
#endif |
} |
#ifdef RUN_DEBUG_BENCHMARK |
if ( mesa_profile ) { |
_mesa_printf(NULL, "\n" ); |
fflush( stdout ); |
} |
#endif |
} |
#endif /* DEBUG */ |