From 352d4dbfb24c65f327759c00c7db7d30a9482e35 Mon Sep 17 00:00:00 2001 From: Keith Whitwell Date: Mon, 10 May 2004 18:16:03 +0000 Subject: [PATCH] Add EXT_vertex_cull support to mesa --- src/mesa/main/clip.c | 42 +++++++++++++ src/mesa/main/clip.h | 7 +++ src/mesa/main/enable.c | 9 +++ src/mesa/main/extensions.c | 1 + src/mesa/main/matrix.c | 13 +++- src/mesa/main/mtypes.h | 5 ++ src/mesa/main/state.c | 2 + src/mesa/math/m_xform.h | 1 + src/mesa/tnl/t_context.h | 1 + src/mesa/tnl/t_pipeline.h | 1 + src/mesa/tnl/t_vb_cull.c | 111 ++++++++++++++++++++++++++++++++++ src/mesa/tnl/t_vb_render.c | 11 ++-- src/mesa/tnl/t_vb_vertex.c | 2 + src/mesa/tnl_dd/t_dd_dmatmp.h | 2 +- 14 files changed, 202 insertions(+), 6 deletions(-) create mode 100644 src/mesa/tnl/t_vb_cull.c diff --git a/src/mesa/main/clip.c b/src/mesa/main/clip.c index 31e6af91bd1..a1eda32ebf7 100644 --- a/src/mesa/main/clip.c +++ b/src/mesa/main/clip.c @@ -117,3 +117,45 @@ _mesa_GetClipPlane( GLenum plane, GLdouble *equation ) equation[3] = (GLdouble) ctx->Transform.EyeUserPlane[p][3]; } +void GLAPIENTRY +_mesa_CullParameterfvEXT (GLenum cap, GLfloat *v) +{ + GET_CURRENT_CONTEXT(ctx); + ASSERT_OUTSIDE_BEGIN_END(ctx); + + switch (cap) { + case GL_CULL_VERTEX_EYE_POSITION_EXT: + FLUSH_VERTICES(ctx, _NEW_TRANSFORM); + COPY_4FV(ctx->Transform.CullEyePos, v); + + _mesa_transform_vector( ctx->Transform.CullObjPos, + ctx->Transform.CullEyePos, + ctx->ModelviewMatrixStack.Top->inv ); + break; + + case GL_CULL_VERTEX_OBJECT_POSITION_EXT: + FLUSH_VERTICES(ctx, _NEW_TRANSFORM); + COPY_4FV(ctx->Transform.CullObjPos, v); + + _mesa_transform_vector( ctx->Transform.CullEyePos, + ctx->Transform.CullObjPos, + ctx->ModelviewMatrixStack.Top->m ); + break; + default: + _mesa_error( ctx, GL_INVALID_ENUM, "glCullParameterfvEXT" ); + } +} + +void GLAPIENTRY +_mesa_CullParameterdvEXT (GLenum cap, GLdouble *v) +{ + GLfloat f[4]; + + f[0] = (GLfloat)v[0]; + f[1] = (GLfloat)v[1]; + f[2] = (GLfloat)v[2]; + f[3] = (GLfloat)v[3]; + + _mesa_CullParameterfvEXT(cap, f); +} + diff --git a/src/mesa/main/clip.h b/src/mesa/main/clip.h index 9442e864395..d53afb45bdf 100644 --- a/src/mesa/main/clip.h +++ b/src/mesa/main/clip.h @@ -39,4 +39,11 @@ _mesa_ClipPlane( GLenum plane, const GLdouble *equation ); extern void GLAPIENTRY _mesa_GetClipPlane( GLenum plane, GLdouble *equation ); +extern void GLAPIENTRY +_mesa_CullParameterfvEXT (GLenum cap, GLfloat *v); + +extern void GLAPIENTRY +_mesa_CullParameterdvEXT (GLenum cap, GLdouble *v); + + #endif diff --git a/src/mesa/main/enable.c b/src/mesa/main/enable.c index 64cc4d17ca7..25bb7938c01 100644 --- a/src/mesa/main/enable.c +++ b/src/mesa/main/enable.c @@ -290,6 +290,15 @@ void _mesa_set_enable( GLcontext *ctx, GLenum cap, GLboolean state ) FLUSH_VERTICES(ctx, _NEW_POLYGON); ctx->Polygon.CullFlag = state; break; + + case GL_CULL_VERTEX_EXT: + CHECK_EXTENSION(EXT_cull_vertex, cap); + if (ctx->Transform.CullVertexFlag == state) + return; + FLUSH_VERTICES(ctx, _NEW_TRANSFORM); + ctx->Transform.CullVertexFlag = state; + break; + case GL_DEPTH_TEST: if (state && ctx->Visual.depthBits==0) { _mesa_warning(ctx,"glEnable(GL_DEPTH_TEST) but no depth buffer"); diff --git a/src/mesa/main/extensions.c b/src/mesa/main/extensions.c index f840b3fe086..172843a4a4e 100644 --- a/src/mesa/main/extensions.c +++ b/src/mesa/main/extensions.c @@ -75,6 +75,7 @@ static const struct { { OFF, "GL_EXT_blend_minmax", F(EXT_blend_minmax) }, { OFF, "GL_EXT_blend_subtract", F(EXT_blend_subtract) }, { ON, "GL_EXT_clip_volume_hint", F(EXT_clip_volume_hint) }, + { OFF, "GL_EXT_cull_vertex", F(EXT_cull_vertex) }, { ON, "GL_EXT_compiled_vertex_array", F(EXT_compiled_vertex_array) }, { OFF, "GL_EXT_convolution", F(EXT_convolution) }, { ON, "GL_EXT_copy_texture", F(EXT_copy_texture) }, diff --git a/src/mesa/main/matrix.c b/src/mesa/main/matrix.c index 19e8dc3a5a0..1e6b9dd3947 100644 --- a/src/mesa/main/matrix.c +++ b/src/mesa/main/matrix.c @@ -745,8 +745,16 @@ calculate_model_project_matrix( GLcontext *ctx ) */ void _mesa_update_modelview_project( GLcontext *ctx, GLuint new_state ) { - if (new_state & _NEW_MODELVIEW) + if (new_state & _NEW_MODELVIEW) { _math_matrix_analyse( ctx->ModelviewMatrixStack.Top ); + + /* Bring cull position uptodate. + */ + TRANSFORM_POINT3( ctx->Transform.CullObjPos, + ctx->ModelviewMatrixStack.Top->inv, + ctx->Transform.CullEyePos ); + } + if (new_state & _NEW_PROJECTION) update_projection( ctx ); @@ -898,6 +906,9 @@ void _mesa_init_transform( GLcontext *ctx ) ASSIGN_4V( ctx->Transform.EyeUserPlane[i], 0.0, 0.0, 0.0, 0.0 ); } ctx->Transform.ClipPlanesEnabled = 0; + + ASSIGN_4V( ctx->Transform.CullObjPos, 0.0, 0.0, 1.0, 0.0 ); + ASSIGN_4V( ctx->Transform.CullEyePos, 0.0, 0.0, 1.0, 0.0 ); } diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index e045c1f35b8..1458f16a537 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -1323,6 +1323,10 @@ struct gl_transform_attrib { GLboolean Normalize; /**< Normalize all normals? */ GLboolean RescaleNormals; /**< GL_EXT_rescale_normal */ GLboolean RasterPositionUnclipped; /**< GL_IBM_rasterpos_clip */ + + GLboolean CullVertexFlag; /**< True if GL_CULL_VERTEX_EXT is enabled */ + GLfloat CullEyePos[4]; + GLfloat CullObjPos[4]; }; @@ -1885,6 +1889,7 @@ struct gl_extensions GLboolean EXT_blend_minmax; GLboolean EXT_blend_subtract; GLboolean EXT_clip_volume_hint; + GLboolean EXT_cull_vertex; GLboolean EXT_convolution; GLboolean EXT_compiled_vertex_array; GLboolean EXT_copy_texture; diff --git a/src/mesa/main/state.c b/src/mesa/main/state.c index c894241a739..0f3750e61ca 100644 --- a/src/mesa/main/state.c +++ b/src/mesa/main/state.c @@ -211,6 +211,8 @@ _mesa_init_exec_table(struct _glapi_table *exec, GLuint tableSize) exec->ClipPlane = _mesa_ClipPlane; exec->ColorMaterial = _mesa_ColorMaterial; exec->CopyPixels = _mesa_CopyPixels; + exec->CullParameterfvEXT = _mesa_CullParameterfvEXT; + exec->CullParameterdvEXT = _mesa_CullParameterdvEXT; exec->DeleteLists = _mesa_DeleteLists; exec->DepthFunc = _mesa_DepthFunc; exec->DepthMask = _mesa_DepthMask; diff --git a/src/mesa/math/m_xform.h b/src/mesa/math/m_xform.h index 5c96cea3d5a..63f1062fc85 100644 --- a/src/mesa/math/m_xform.h +++ b/src/mesa/math/m_xform.h @@ -98,6 +98,7 @@ _math_init_transformation(void); #define CLIP_NEAR_BIT 0x10 #define CLIP_FAR_BIT 0x20 #define CLIP_USER_BIT 0x40 +#define CLIP_CULL_BIT 0x80 #define CLIP_ALL_BITS 0x3f diff --git a/src/mesa/tnl/t_context.h b/src/mesa/tnl/t_context.h index b9fc7b8ea0d..3d099b205a0 100644 --- a/src/mesa/tnl/t_context.h +++ b/src/mesa/tnl/t_context.h @@ -432,6 +432,7 @@ struct vertex_buffer GLvector4f *ClipPtr; /* _TNL_BIT_POS */ GLvector4f *NdcPtr; /* _TNL_BIT_POS */ GLubyte ClipOrMask; /* _TNL_BIT_POS */ + GLubyte ClipAndMask; /* _TNL_BIT_POS */ GLubyte *ClipMask; /* _TNL_BIT_POS */ GLvector4f *NormalPtr; /* _TNL_BIT_NORMAL */ GLfloat *NormalLengthPtr; /* _TNL_BIT_NORMAL */ diff --git a/src/mesa/tnl/t_pipeline.h b/src/mesa/tnl/t_pipeline.h index 02128ea8fd3..d356ee4532c 100644 --- a/src/mesa/tnl/t_pipeline.h +++ b/src/mesa/tnl/t_pipeline.h @@ -47,6 +47,7 @@ extern void _tnl_install_pipeline( GLcontext *ctx, /* These are implemented in the t_vb_*.c files: */ extern const struct tnl_pipeline_stage _tnl_vertex_transform_stage; +extern const struct tnl_pipeline_stage _tnl_vertex_cull_stage; extern const struct tnl_pipeline_stage _tnl_normal_transform_stage; extern const struct tnl_pipeline_stage _tnl_lighting_stage; extern const struct tnl_pipeline_stage _tnl_fog_coordinate_stage; diff --git a/src/mesa/tnl/t_vb_cull.c b/src/mesa/tnl/t_vb_cull.c new file mode 100644 index 00000000000..9527ead9430 --- /dev/null +++ b/src/mesa/tnl/t_vb_cull.c @@ -0,0 +1,111 @@ +/* + * Mesa 3-D graphics library + * Version: 6.1 + * + * Copyright (C) 1999-2004 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 + */ + + +#include "glheader.h" +#include "colormac.h" +#include "context.h" +#include "macros.h" +#include "imports.h" +#include "mtypes.h" + +#include "math/m_xform.h" + +#include "t_context.h" +#include "t_pipeline.h" + + + +/* EXT_vertex_cull. Not really a big win, but probably depends on + * your application. This stage not included in the default pipeline. + */ +static GLboolean run_cull_stage( GLcontext *ctx, + struct tnl_pipeline_stage *stage ) +{ + TNLcontext *tnl = TNL_CONTEXT(ctx); + struct vertex_buffer *VB = &tnl->vb; + + const GLfloat a = ctx->Transform.CullObjPos[0]; + const GLfloat b = ctx->Transform.CullObjPos[1]; + const GLfloat c = ctx->Transform.CullObjPos[2]; + GLfloat *norm = (GLfloat *)VB->NormalPtr->data; + GLuint stride = VB->NormalPtr->stride; + GLuint count = VB->Count; + GLuint i; + + VB->ClipOrMask &= ~CLIP_CULL_BIT; + VB->ClipAndMask |= CLIP_CULL_BIT; + + for (i = 0 ; i < count ; i++) { + GLfloat dp = (norm[0] * a + + norm[1] * b + + norm[2] * c); + + if (dp < 0) { + VB->ClipMask[i] |= CLIP_CULL_BIT; + VB->ClipOrMask |= CLIP_CULL_BIT; + } + else { + VB->ClipMask[i] &= ~CLIP_CULL_BIT; + VB->ClipAndMask &= ~CLIP_CULL_BIT; + } + + STRIDE_F(norm, stride); + } + + return !(VB->ClipAndMask & CLIP_CULL_BIT); +} + + +static void check_cull( GLcontext *ctx, struct tnl_pipeline_stage *stage ) +{ + stage->active = (!ctx->VertexProgram._Enabled && + ctx->Transform.CullVertexFlag); +} + + +static void dtr( struct tnl_pipeline_stage *stage ) +{ +} + + +const struct tnl_pipeline_stage _tnl_vertex_cull_stage = +{ + "EXT_cull_vertex", + _NEW_PROGRAM | + _NEW_TRANSFORM, + _NEW_TRANSFORM, + GL_TRUE, /* active */ + _TNL_BIT_NORMAL | + _TNL_BIT_POS, /* inputs */ + _TNL_BIT_POS, /* outputs */ + 0, /* changed_inputs */ + NULL, /* private data */ + dtr, /* destructor */ + check_cull, /* check */ + run_cull_stage /* run -- initially set to init */ +}; diff --git a/src/mesa/tnl/t_vb_render.c b/src/mesa/tnl/t_vb_render.c index 1c501689683..f8e41f5d9be 100644 --- a/src/mesa/tnl/t_vb_render.c +++ b/src/mesa/tnl/t_vb_render.c @@ -77,6 +77,9 @@ #define EDGEFLAG_SET(idx, val) VB->EdgeFlag[idx] = val +#define CLIPMASK (CLIP_ALL_BITS|CLIP_CULL_BIT) + + /* Vertices, with the possibility of clipping. */ #define RENDER_POINTS( start, count ) \ @@ -88,7 +91,7 @@ do { \ GLubyte ormask = c1|c2; \ if (!ormask) \ LineFunc( ctx, v1, v2 ); \ - else if (!(c1 & c2 & 0x3f)) \ + else if (!(c1 & c2 & CLIPMASK)) \ clip_line_4( ctx, v1, v2, ormask ); \ } while (0) @@ -98,7 +101,7 @@ do { \ GLubyte ormask = c1|c2|c3; \ if (!ormask) \ TriangleFunc( ctx, v1, v2, v3 ); \ - else if (!(c1 & c2 & c3 & 0x3f)) \ + else if (!(c1 & c2 & c3 & CLIPMASK)) \ clip_tri_4( ctx, v1, v2, v3, ormask ); \ } while (0) @@ -109,7 +112,7 @@ do { \ GLubyte ormask = c1|c2|c3|c4; \ if (!ormask) \ QuadFunc( ctx, v1, v2, v3, v4 ); \ - else if (!(c1 & c2 & c3 & c4 & 0x3f)) \ + else if (!(c1 & c2 & c3 & c4 & CLIPMASK)) \ clip_quad_4( ctx, v1, v2, v3, v4, ormask ); \ } while (0) @@ -170,7 +173,7 @@ static void clip_elt_triangles( GLcontext *ctx, if (ormask) { if (start < j) render_tris( ctx, start, j, 0 ); - if (!(c1&c2&c3&0x3f)) + if (!(c1&c2&c3&CLIPMASK)) clip_tri_4( ctx, elt[j], elt[j+1], elt[j+2], ormask ); start = j+3; } diff --git a/src/mesa/tnl/t_vb_vertex.c b/src/mesa/tnl/t_vb_vertex.c index b483a9522d1..3d642818821 100644 --- a/src/mesa/tnl/t_vb_vertex.c +++ b/src/mesa/tnl/t_vb_vertex.c @@ -208,6 +208,7 @@ static GLboolean run_vertex_stage( GLcontext *ctx, return GL_FALSE; } + VB->ClipAndMask = store->andmask; VB->ClipOrMask = store->ormask; VB->ClipMask = store->clipmask; @@ -222,6 +223,7 @@ static GLboolean run_vertex_stage( GLcontext *ctx, VB->ClipPtr = store->save_clipptr; VB->NdcPtr = store->save_ndcptr; VB->ClipMask = store->clipmask; + VB->ClipAndMask = store->andmask; VB->ClipOrMask = store->ormask; if (store->andmask) return GL_FALSE; diff --git a/src/mesa/tnl_dd/t_dd_dmatmp.h b/src/mesa/tnl_dd/t_dd_dmatmp.h index e8681dcd034..43d50308566 100644 --- a/src/mesa/tnl_dd/t_dd_dmatmp.h +++ b/src/mesa/tnl_dd/t_dd_dmatmp.h @@ -1152,7 +1152,7 @@ static GLboolean TAG(validate_render)( GLcontext *ctx, { GLint i; - if (VB->ClipOrMask) + if (VB->ClipOrMask & ~CLIP_CULL_BIT) return GL_FALSE; if (VB->Elts && !HAVE_ELTS)