diff options
Diffstat (limited to 'src/mesa')
| -rw-r--r-- | src/mesa/tnl/t_context.h | 1 | ||||
| -rw-r--r-- | src/mesa/tnl/t_vb_cliptmp.h | 103 | ||||
| -rw-r--r-- | src/mesa/tnl/t_vb_program.c | 15 | ||||
| -rw-r--r-- | src/mesa/tnl/t_vb_vertex.c | 31 | 
4 files changed, 132 insertions, 18 deletions
| diff --git a/src/mesa/tnl/t_context.h b/src/mesa/tnl/t_context.h index 6137c2d2fe..ca4edcfcb9 100644 --- a/src/mesa/tnl/t_context.h +++ b/src/mesa/tnl/t_context.h @@ -207,6 +207,7 @@ struct vertex_buffer     GLvector4f  *EyePtr;		                /* _TNL_BIT_POS */     GLvector4f  *ClipPtr;	                /* _TNL_BIT_POS */     GLvector4f  *NdcPtr;                         /* _TNL_BIT_POS */ +   GLfloat     *ClipDistancePtr[MAX_CLIP_PLANES]; /* _TNL_BIT_POS */     GLubyte     ClipOrMask;	                /* _TNL_BIT_POS */     GLubyte     ClipAndMask;	                /* _TNL_BIT_POS */     GLubyte     *ClipMask;		        /* _TNL_BIT_POS */ diff --git a/src/mesa/tnl/t_vb_cliptmp.h b/src/mesa/tnl/t_vb_cliptmp.h index 618b8b3130..0d2183a9e6 100644 --- a/src/mesa/tnl/t_vb_cliptmp.h +++ b/src/mesa/tnl/t_vb_cliptmp.h @@ -80,6 +80,58 @@ do {									\  } 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 )				\  do {									\     if (mask & PLANE_BIT) {						\ @@ -111,6 +163,37 @@ do {									\  } 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.   */ @@ -139,11 +222,7 @@ TAG(clip_line)( GLcontext *ctx, GLuint v0, GLuint v1, GLubyte mask )     if (mask & CLIP_USER_BIT) {        for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {  	 if (ctx->Transform.ClipPlanesEnabled & (1 << p)) { -            const GLfloat a = ctx->Transform._ClipUserPlane[p][0]; -            const GLfloat b = ctx->Transform._ClipUserPlane[p][1]; -            const GLfloat c = ctx->Transform._ClipUserPlane[p][2]; -            const GLfloat d = ctx->Transform._ClipUserPlane[p][3]; -	    LINE_CLIP( CLIP_USER_BIT, a, b, c, d ); +	    LINE_USERCLIP(p);  	 }        }     } @@ -228,11 +307,7 @@ TAG(clip_tri)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLubyte mask )     if (mask & CLIP_USER_BIT) {        for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {           if (ctx->Transform.ClipPlanesEnabled & (1 << p)) { -            const GLfloat a = ctx->Transform._ClipUserPlane[p][0]; -            const GLfloat b = ctx->Transform._ClipUserPlane[p][1]; -            const GLfloat c = ctx->Transform._ClipUserPlane[p][2]; -            const GLfloat d = ctx->Transform._ClipUserPlane[p][3]; -            POLY_CLIP( CLIP_USER_BIT, a, b, c, d ); +            POLY_USERCLIP(p);           }        }     } @@ -291,11 +366,7 @@ TAG(clip_quad)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3,     if (mask & CLIP_USER_BIT) {        for (p = 0; p < ctx->Const.MaxClipPlanes; p++) {  	 if (ctx->Transform.ClipPlanesEnabled & (1 << p)) { -            const GLfloat a = ctx->Transform._ClipUserPlane[p][0]; -            const GLfloat b = ctx->Transform._ClipUserPlane[p][1]; -            const GLfloat c = ctx->Transform._ClipUserPlane[p][2]; -            const GLfloat d = ctx->Transform._ClipUserPlane[p][3]; -	    POLY_CLIP( CLIP_USER_BIT, a, b, c, d ); +	    POLY_USERCLIP(p);  	 }        }     } @@ -317,4 +388,6 @@ TAG(clip_quad)( GLcontext *ctx, GLuint v0, GLuint v1, GLuint v2, GLuint v3,  #undef SIZE  #undef TAG  #undef POLY_CLIP +#undef POLY_USERCLIP  #undef LINE_CLIP +#undef LINE_USERCLIP diff --git a/src/mesa/tnl/t_vb_program.c b/src/mesa/tnl/t_vb_program.c index c10a27614f..5fb83c2b01 100644 --- a/src/mesa/tnl/t_vb_program.c +++ b/src/mesa/tnl/t_vb_program.c @@ -66,6 +66,7 @@ struct vp_stage_data {     GLvector4f results[VERT_RESULT_MAX];     GLvector4f ndcCoords;              /**< normalized device coords */ +   GLfloat *clipdistance[MAX_CLIP_PLANES];     GLubyte *clipmask;                 /**< clip flags */     GLubyte ormask, andmask;           /**< for clipping */  }; @@ -77,6 +78,7 @@ struct vp_stage_data {  static void  userclip( GLcontext *ctx,            GLvector4f *clip, +          GLfloat *clipdistance[MAX_CLIP_PLANES],            GLubyte *clipmask,            GLubyte *clipormask,            GLubyte *clipandmask ) @@ -105,6 +107,8 @@ userclip( GLcontext *ctx,  	       clipmask[i] |= CLIP_USER_BIT;  	    } +	    clipdistance[p][i] = dp; +  	    STRIDE_F(coord, stride);  	 } @@ -164,6 +168,7 @@ do_ndc_cliptest(GLcontext *ctx, struct vp_stage_data *store)        ctx->VertexProgram.Current->IsPositionInvariant)) {        userclip( ctx,  		VB->ClipPtr, +		store->clipdistance,  		store->clipmask,  		&store->ormask,  		&store->andmask ); @@ -171,6 +176,9 @@ do_ndc_cliptest(GLcontext *ctx, struct vp_stage_data *store)        if (store->andmask) {  	 return GL_FALSE;        } + +      memcpy(VB->ClipDistancePtr, store->clipdistance, +	     sizeof(store->clipdistance));     }     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 );     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;  } @@ -537,6 +549,9 @@ dtr(struct tnl_pipeline_stage *stage)        _mesa_vector4f_free( &store->ndcCoords );        ALIGN_FREE( store->clipmask ); +      for (i = 0; i < MAX_CLIP_PLANES; i++) +	 ALIGN_FREE(store->clipdistance[i]); +        FREE( store );        stage->privatePtr = NULL;     } diff --git a/src/mesa/tnl/t_vb_vertex.c b/src/mesa/tnl/t_vb_vertex.c index 4734754ea4..2a61ff1177 100644 --- a/src/mesa/tnl/t_vb_vertex.c +++ b/src/mesa/tnl/t_vb_vertex.c @@ -44,6 +44,7 @@ struct vertex_stage_data {     GLvector4f eye;     GLvector4f clip;     GLvector4f proj; +   GLfloat *clipdistance[MAX_CLIP_PLANES];     GLubyte *clipmask;     GLubyte ormask;     GLubyte andmask; @@ -56,11 +57,12 @@ struct vertex_stage_data {  /* This function implements cliptesting for user-defined clip planes.   * The clipping of primitives to these planes is implemented in - * t_render_clip.h. + * t_vp_cliptmp.h.   */  #define USER_CLIPTEST(NAME, SZ)					\  static void NAME( GLcontext *ctx,				\  		  GLvector4f *clip,				\ +		  GLfloat *clipdistances[MAX_CLIP_PLANES],	\  		  GLubyte *clipmask,				\  		  GLubyte *clipormask,				\  		  GLubyte *clipandmask )			\ @@ -88,6 +90,8 @@ static void NAME( GLcontext *ctx,				\  	       clipmask[i] |= CLIP_USER_BIT;			\  	    }							\  								\ +	    clipdistances[p][i] = dp;				\ +								\  	    STRIDE_F(coord, stride);				\  	 }							\  								\ @@ -107,8 +111,9 @@ USER_CLIPTEST(userclip3, 3)  USER_CLIPTEST(userclip4, 4)  static void (*(usercliptab[5]))( GLcontext *, -				 GLvector4f *, GLubyte *, -				 GLubyte *, GLubyte * ) = +				 GLvector4f *, +				 GLfloat *[MAX_CLIP_PLANES], +				 GLubyte *, GLubyte *, GLubyte * ) =  {     NULL,     NULL, @@ -214,12 +219,16 @@ static GLboolean run_vertex_stage( GLcontext *ctx,     if (ctx->Transform.ClipPlanesEnabled) {        usercliptab[VB->ClipPtr->size]( ctx,  				      VB->ClipPtr, +				      store->clipdistance,  				      store->clipmask,  				      &store->ormask,  				      &store->andmask );        if (store->andmask)  	 return GL_FALSE; + +      memcpy(VB->ClipDistancePtr, store->clipdistance, +	     sizeof(store->clipdistance));     }     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_stage_data *store;     GLuint size = VB->Size; +   unsigned i;     stage->privatePtr = CALLOC(sizeof(*store));     store = VERTEX_STAGE_DATA(stage); @@ -247,8 +257,17 @@ static GLboolean init_vertex_stage( GLcontext *ctx,     _mesa_vector4f_alloc( &store->proj, 0, 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 || +       !store->clipdistance[0] || +       !store->clipdistance[1] || +       !store->clipdistance[2] || +       !store->clipdistance[3] || +       !store->clipdistance[4] || +       !store->clipdistance[5] ||         !store->eye.data ||         !store->clip.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);     if (store) { +      unsigned i; +        _mesa_vector4f_free( &store->eye );        _mesa_vector4f_free( &store->clip );        _mesa_vector4f_free( &store->proj );        ALIGN_FREE( store->clipmask ); + +      for (i = 0; i < MAX_CLIP_PLANES; i++) +	 ALIGN_FREE(store->clipdistance[i]); +        FREE(store);        stage->privatePtr = NULL;        stage->run = init_vertex_stage; | 
