Store clipping distance for user clip planes as part of vertex processing
Once the clipping distance is calculated and stored per vertex, the distances can be re-used when clipping is actually performed. This doesn't have any immediate benefit, but it paves the way for implementing gl_ClipDistance in vertex shaders and result.clip[] in vertex programs. This has not produces any oglconform regressions on my G31 system which uses software TNL. Signed-off-by: Ian Romanick <ian.d.romanick@intel.com> Reviewed-by: Brian Paul <brianp@vmware.com>
This commit is contained in:
@@ -207,6 +207,7 @@ struct vertex_buffer
|
|||||||
GLvector4f *EyePtr; /* _TNL_BIT_POS */
|
GLvector4f *EyePtr; /* _TNL_BIT_POS */
|
||||||
GLvector4f *ClipPtr; /* _TNL_BIT_POS */
|
GLvector4f *ClipPtr; /* _TNL_BIT_POS */
|
||||||
GLvector4f *NdcPtr; /* _TNL_BIT_POS */
|
GLvector4f *NdcPtr; /* _TNL_BIT_POS */
|
||||||
|
GLfloat *ClipDistancePtr[MAX_CLIP_PLANES]; /* _TNL_BIT_POS */
|
||||||
GLubyte ClipOrMask; /* _TNL_BIT_POS */
|
GLubyte ClipOrMask; /* _TNL_BIT_POS */
|
||||||
GLubyte ClipAndMask; /* _TNL_BIT_POS */
|
GLubyte ClipAndMask; /* _TNL_BIT_POS */
|
||||||
GLubyte *ClipMask; /* _TNL_BIT_POS */
|
GLubyte *ClipMask; /* _TNL_BIT_POS */
|
||||||
|
@@ -80,6 +80,58 @@ do { \
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
#define POLY_USERCLIP(PLANE) \
|
||||||
|
do { \
|
||||||
|
if (mask & CLIP_USER_BIT) { \
|
||||||
|
GLuint idxPrev = inlist[0]; \
|
||||||
|
GLfloat dpPrev = VB->ClipDistancePtr[PLANE][idxPrev]; \
|
||||||
|
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 = VB->ClipDistancePtr[PLANE][idx]; \
|
||||||
|
\
|
||||||
|
if (!IS_NEGATIVE(dpPrev)) { \
|
||||||
|
outlist[outcount++] = idxPrev; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
if (DIFFERENT_SIGNS(dp, dpPrev)) { \
|
||||||
|
if (IS_NEGATIVE(dp)) { \
|
||||||
|
/* Going out of bounds. Avoid division by zero as we \
|
||||||
|
* know dp != dpPrev from DIFFERENT_SIGNS, above. \
|
||||||
|
*/ \
|
||||||
|
GLfloat t = dp / (dp - dpPrev); \
|
||||||
|
INTERP_4F( t, coord[newvert], coord[idx], coord[idxPrev]); \
|
||||||
|
interp( ctx, t, newvert, idx, idxPrev, GL_TRUE ); \
|
||||||
|
} else { \
|
||||||
|
/* Coming back in. \
|
||||||
|
*/ \
|
||||||
|
GLfloat t = dpPrev / (dpPrev - dp); \
|
||||||
|
INTERP_4F( t, coord[newvert], coord[idxPrev], coord[idx]); \
|
||||||
|
interp( ctx, t, newvert, idxPrev, idx, GL_FALSE ); \
|
||||||
|
} \
|
||||||
|
outlist[outcount++] = newvert++; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
idxPrev = idx; \
|
||||||
|
dpPrev = dp; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
if (outcount < 3) \
|
||||||
|
return; \
|
||||||
|
\
|
||||||
|
{ \
|
||||||
|
GLuint *tmp = inlist; \
|
||||||
|
inlist = outlist; \
|
||||||
|
outlist = tmp; \
|
||||||
|
n = outcount; \
|
||||||
|
} \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
#define LINE_CLIP(PLANE_BIT, A, B, C, D ) \
|
#define LINE_CLIP(PLANE_BIT, A, B, C, D ) \
|
||||||
do { \
|
do { \
|
||||||
if (mask & PLANE_BIT) { \
|
if (mask & PLANE_BIT) { \
|
||||||
@@ -111,6 +163,37 @@ do { \
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
#define LINE_USERCLIP(PLANE) \
|
||||||
|
do { \
|
||||||
|
if (mask & CLIP_USER_BIT) { \
|
||||||
|
const GLfloat dp0 = VB->ClipDistancePtr[PLANE][v0]; \
|
||||||
|
const GLfloat dp1 = VB->ClipDistancePtr[PLANE][v1]; \
|
||||||
|
const GLboolean neg_dp0 = IS_NEGATIVE(dp0); \
|
||||||
|
const GLboolean neg_dp1 = IS_NEGATIVE(dp1); \
|
||||||
|
\
|
||||||
|
/* For regular clipping, we know from the clipmask that one \
|
||||||
|
* (or both) of these must be negative (otherwise we wouldn't \
|
||||||
|
* be here). \
|
||||||
|
* For userclip, there is only a single bit for all active \
|
||||||
|
* planes, so we can end up here when there is nothing to do, \
|
||||||
|
* hence the second IS_NEGATIVE() test: \
|
||||||
|
*/ \
|
||||||
|
if (neg_dp0 && neg_dp1) \
|
||||||
|
return; /* both vertices outside clip plane: discard */ \
|
||||||
|
\
|
||||||
|
if (neg_dp1) { \
|
||||||
|
GLfloat t = dp1 / (dp1 - dp0); \
|
||||||
|
if (t > t1) t1 = t; \
|
||||||
|
} else if (neg_dp0) { \
|
||||||
|
GLfloat t = dp0 / (dp0 - dp1); \
|
||||||
|
if (t > t0) t0 = t; \
|
||||||
|
} \
|
||||||
|
if (t0 + t1 >= 1.0) \
|
||||||
|
return; /* discard */ \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Clip a line against the viewport and user clip planes.
|
/* Clip a line against the viewport and user clip planes.
|
||||||
*/
|
*/
|
||||||
@@ -139,11 +222,7 @@ TAG(clip_line)( GLcontext *ctx, GLuint v0, GLuint v1, GLubyte mask )
|
|||||||
if (mask & CLIP_USER_BIT) {
|
if (mask & CLIP_USER_BIT) {
|
||||||
for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
|
for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
|
||||||
if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
|
if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
|
||||||
const GLfloat a = ctx->Transform._ClipUserPlane[p][0];
|
LINE_USERCLIP(p);
|
||||||
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 );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -228,11 +307,7 @@ TAG(clip_tri)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLubyte mask )
|
|||||||
if (mask & CLIP_USER_BIT) {
|
if (mask & CLIP_USER_BIT) {
|
||||||
for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
|
for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
|
||||||
if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
|
if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
|
||||||
const GLfloat a = ctx->Transform._ClipUserPlane[p][0];
|
POLY_USERCLIP(p);
|
||||||
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 );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -291,11 +366,7 @@ TAG(clip_quad)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3,
|
|||||||
if (mask & CLIP_USER_BIT) {
|
if (mask & CLIP_USER_BIT) {
|
||||||
for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
|
for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {
|
||||||
if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
|
if (ctx->Transform.ClipPlanesEnabled & (1 << p)) {
|
||||||
const GLfloat a = ctx->Transform._ClipUserPlane[p][0];
|
POLY_USERCLIP(p);
|
||||||
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 );
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -317,4 +388,6 @@ TAG(clip_quad)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3,
|
|||||||
#undef SIZE
|
#undef SIZE
|
||||||
#undef TAG
|
#undef TAG
|
||||||
#undef POLY_CLIP
|
#undef POLY_CLIP
|
||||||
|
#undef POLY_USERCLIP
|
||||||
#undef LINE_CLIP
|
#undef LINE_CLIP
|
||||||
|
#undef LINE_USERCLIP
|
||||||
|
@@ -66,6 +66,7 @@ struct vp_stage_data {
|
|||||||
GLvector4f results[VERT_RESULT_MAX];
|
GLvector4f results[VERT_RESULT_MAX];
|
||||||
|
|
||||||
GLvector4f ndcCoords; /**< normalized device coords */
|
GLvector4f ndcCoords; /**< normalized device coords */
|
||||||
|
GLfloat *clipdistance[MAX_CLIP_PLANES];
|
||||||
GLubyte *clipmask; /**< clip flags */
|
GLubyte *clipmask; /**< clip flags */
|
||||||
GLubyte ormask, andmask; /**< for clipping */
|
GLubyte ormask, andmask; /**< for clipping */
|
||||||
};
|
};
|
||||||
@@ -77,6 +78,7 @@ struct vp_stage_data {
|
|||||||
static void
|
static void
|
||||||
userclip( GLcontext *ctx,
|
userclip( GLcontext *ctx,
|
||||||
GLvector4f *clip,
|
GLvector4f *clip,
|
||||||
|
GLfloat *clipdistance[MAX_CLIP_PLANES],
|
||||||
GLubyte *clipmask,
|
GLubyte *clipmask,
|
||||||
GLubyte *clipormask,
|
GLubyte *clipormask,
|
||||||
GLubyte *clipandmask )
|
GLubyte *clipandmask )
|
||||||
@@ -105,6 +107,8 @@ userclip( GLcontext *ctx,
|
|||||||
clipmask[i] |= CLIP_USER_BIT;
|
clipmask[i] |= CLIP_USER_BIT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
clipdistance[p][i] = dp;
|
||||||
|
|
||||||
STRIDE_F(coord, stride);
|
STRIDE_F(coord, stride);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,6 +168,7 @@ do_ndc_cliptest(GLcontext *ctx, struct vp_stage_data *store)
|
|||||||
ctx->VertexProgram.Current->IsPositionInvariant)) {
|
ctx->VertexProgram.Current->IsPositionInvariant)) {
|
||||||
userclip( ctx,
|
userclip( ctx,
|
||||||
VB->ClipPtr,
|
VB->ClipPtr,
|
||||||
|
store->clipdistance,
|
||||||
store->clipmask,
|
store->clipmask,
|
||||||
&store->ormask,
|
&store->ormask,
|
||||||
&store->andmask );
|
&store->andmask );
|
||||||
@@ -171,6 +176,9 @@ do_ndc_cliptest(GLcontext *ctx, struct vp_stage_data *store)
|
|||||||
if (store->andmask) {
|
if (store->andmask) {
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memcpy(VB->ClipDistancePtr, store->clipdistance,
|
||||||
|
sizeof(store->clipdistance));
|
||||||
}
|
}
|
||||||
|
|
||||||
VB->ClipAndMask = store->andmask;
|
VB->ClipAndMask = store->andmask;
|
||||||
@@ -514,6 +522,10 @@ init_vp(GLcontext *ctx, struct tnl_pipeline_stage *stage)
|
|||||||
_mesa_vector4f_alloc( &store->ndcCoords, 0, size, 32 );
|
_mesa_vector4f_alloc( &store->ndcCoords, 0, size, 32 );
|
||||||
store->clipmask = (GLubyte *) ALIGN_MALLOC(sizeof(GLubyte)*size, 32 );
|
store->clipmask = (GLubyte *) ALIGN_MALLOC(sizeof(GLubyte)*size, 32 );
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_CLIP_PLANES; i++)
|
||||||
|
store->clipdistance[i] =
|
||||||
|
(GLfloat *) ALIGN_MALLOC(sizeof(GLfloat) * size, 32);
|
||||||
|
|
||||||
return GL_TRUE;
|
return GL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -537,6 +549,9 @@ dtr(struct tnl_pipeline_stage *stage)
|
|||||||
_mesa_vector4f_free( &store->ndcCoords );
|
_mesa_vector4f_free( &store->ndcCoords );
|
||||||
ALIGN_FREE( store->clipmask );
|
ALIGN_FREE( store->clipmask );
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_CLIP_PLANES; i++)
|
||||||
|
ALIGN_FREE(store->clipdistance[i]);
|
||||||
|
|
||||||
FREE( store );
|
FREE( store );
|
||||||
stage->privatePtr = NULL;
|
stage->privatePtr = NULL;
|
||||||
}
|
}
|
||||||
|
@@ -44,6 +44,7 @@ struct vertex_stage_data {
|
|||||||
GLvector4f eye;
|
GLvector4f eye;
|
||||||
GLvector4f clip;
|
GLvector4f clip;
|
||||||
GLvector4f proj;
|
GLvector4f proj;
|
||||||
|
GLfloat *clipdistance[MAX_CLIP_PLANES];
|
||||||
GLubyte *clipmask;
|
GLubyte *clipmask;
|
||||||
GLubyte ormask;
|
GLubyte ormask;
|
||||||
GLubyte andmask;
|
GLubyte andmask;
|
||||||
@@ -56,11 +57,12 @@ struct vertex_stage_data {
|
|||||||
|
|
||||||
/* This function implements cliptesting for user-defined clip planes.
|
/* This function implements cliptesting for user-defined clip planes.
|
||||||
* The clipping of primitives to these planes is implemented in
|
* The clipping of primitives to these planes is implemented in
|
||||||
* t_render_clip.h.
|
* t_vp_cliptmp.h.
|
||||||
*/
|
*/
|
||||||
#define USER_CLIPTEST(NAME, SZ) \
|
#define USER_CLIPTEST(NAME, SZ) \
|
||||||
static void NAME( GLcontext *ctx, \
|
static void NAME( GLcontext *ctx, \
|
||||||
GLvector4f *clip, \
|
GLvector4f *clip, \
|
||||||
|
GLfloat *clipdistances[MAX_CLIP_PLANES], \
|
||||||
GLubyte *clipmask, \
|
GLubyte *clipmask, \
|
||||||
GLubyte *clipormask, \
|
GLubyte *clipormask, \
|
||||||
GLubyte *clipandmask ) \
|
GLubyte *clipandmask ) \
|
||||||
@@ -88,6 +90,8 @@ static void NAME( GLcontext *ctx, \
|
|||||||
clipmask[i] |= CLIP_USER_BIT; \
|
clipmask[i] |= CLIP_USER_BIT; \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
|
clipdistances[p][i] = dp; \
|
||||||
|
\
|
||||||
STRIDE_F(coord, stride); \
|
STRIDE_F(coord, stride); \
|
||||||
} \
|
} \
|
||||||
\
|
\
|
||||||
@@ -107,8 +111,9 @@ USER_CLIPTEST(userclip3, 3)
|
|||||||
USER_CLIPTEST(userclip4, 4)
|
USER_CLIPTEST(userclip4, 4)
|
||||||
|
|
||||||
static void (*(usercliptab[5]))( GLcontext *,
|
static void (*(usercliptab[5]))( GLcontext *,
|
||||||
GLvector4f *, GLubyte *,
|
GLvector4f *,
|
||||||
GLubyte *, GLubyte * ) =
|
GLfloat *[MAX_CLIP_PLANES],
|
||||||
|
GLubyte *, GLubyte *, GLubyte * ) =
|
||||||
{
|
{
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
@@ -214,12 +219,16 @@ static GLboolean run_vertex_stage( GLcontext *ctx,
|
|||||||
if (ctx->Transform.ClipPlanesEnabled) {
|
if (ctx->Transform.ClipPlanesEnabled) {
|
||||||
usercliptab[VB->ClipPtr->size]( ctx,
|
usercliptab[VB->ClipPtr->size]( ctx,
|
||||||
VB->ClipPtr,
|
VB->ClipPtr,
|
||||||
|
store->clipdistance,
|
||||||
store->clipmask,
|
store->clipmask,
|
||||||
&store->ormask,
|
&store->ormask,
|
||||||
&store->andmask );
|
&store->andmask );
|
||||||
|
|
||||||
if (store->andmask)
|
if (store->andmask)
|
||||||
return GL_FALSE;
|
return GL_FALSE;
|
||||||
|
|
||||||
|
memcpy(VB->ClipDistancePtr, store->clipdistance,
|
||||||
|
sizeof(store->clipdistance));
|
||||||
}
|
}
|
||||||
|
|
||||||
VB->ClipAndMask = store->andmask;
|
VB->ClipAndMask = store->andmask;
|
||||||
@@ -236,6 +245,7 @@ static GLboolean init_vertex_stage( GLcontext *ctx,
|
|||||||
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
|
struct vertex_buffer *VB = &TNL_CONTEXT(ctx)->vb;
|
||||||
struct vertex_stage_data *store;
|
struct vertex_stage_data *store;
|
||||||
GLuint size = VB->Size;
|
GLuint size = VB->Size;
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
stage->privatePtr = CALLOC(sizeof(*store));
|
stage->privatePtr = CALLOC(sizeof(*store));
|
||||||
store = VERTEX_STAGE_DATA(stage);
|
store = VERTEX_STAGE_DATA(stage);
|
||||||
@@ -247,8 +257,17 @@ static GLboolean init_vertex_stage( GLcontext *ctx,
|
|||||||
_mesa_vector4f_alloc( &store->proj, 0, size, 32 );
|
_mesa_vector4f_alloc( &store->proj, 0, size, 32 );
|
||||||
|
|
||||||
store->clipmask = (GLubyte *) ALIGN_MALLOC(sizeof(GLubyte)*size, 32 );
|
store->clipmask = (GLubyte *) ALIGN_MALLOC(sizeof(GLubyte)*size, 32 );
|
||||||
|
for (i = 0; i < MAX_CLIP_PLANES; i++)
|
||||||
|
store->clipdistance[i] =
|
||||||
|
(GLfloat *) ALIGN_MALLOC(sizeof(GLfloat) * size, 32);
|
||||||
|
|
||||||
if (!store->clipmask ||
|
if (!store->clipmask ||
|
||||||
|
!store->clipdistance[0] ||
|
||||||
|
!store->clipdistance[1] ||
|
||||||
|
!store->clipdistance[2] ||
|
||||||
|
!store->clipdistance[3] ||
|
||||||
|
!store->clipdistance[4] ||
|
||||||
|
!store->clipdistance[5] ||
|
||||||
!store->eye.data ||
|
!store->eye.data ||
|
||||||
!store->clip.data ||
|
!store->clip.data ||
|
||||||
!store->proj.data)
|
!store->proj.data)
|
||||||
@@ -262,10 +281,16 @@ static void dtr( struct tnl_pipeline_stage *stage )
|
|||||||
struct vertex_stage_data *store = VERTEX_STAGE_DATA(stage);
|
struct vertex_stage_data *store = VERTEX_STAGE_DATA(stage);
|
||||||
|
|
||||||
if (store) {
|
if (store) {
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
_mesa_vector4f_free( &store->eye );
|
_mesa_vector4f_free( &store->eye );
|
||||||
_mesa_vector4f_free( &store->clip );
|
_mesa_vector4f_free( &store->clip );
|
||||||
_mesa_vector4f_free( &store->proj );
|
_mesa_vector4f_free( &store->proj );
|
||||||
ALIGN_FREE( store->clipmask );
|
ALIGN_FREE( store->clipmask );
|
||||||
|
|
||||||
|
for (i = 0; i < MAX_CLIP_PLANES; i++)
|
||||||
|
ALIGN_FREE(store->clipdistance[i]);
|
||||||
|
|
||||||
FREE(store);
|
FREE(store);
|
||||||
stage->privatePtr = NULL;
|
stage->privatePtr = NULL;
|
||||||
stage->run = init_vertex_stage;
|
stage->run = init_vertex_stage;
|
||||||
|
Reference in New Issue
Block a user