diff options
author | Zack Rusin <[email protected]> | 2013-08-15 13:10:22 -0400 |
---|---|---|
committer | Zack Rusin <[email protected]> | 2013-08-15 16:26:32 -0400 |
commit | 7115bc3940c4c1952d503d9d56ebe6fd1fb11645 (patch) | |
tree | 53e95c9973f39b3baaf476b968725617c11ce02d /src/gallium/auxiliary/draw | |
parent | 035bf2198368d3fa69387788a63039d71319f0bf (diff) |
draw: handle nan clipdistance
If clipdistance for one of the vertices is nan (or inf) then the
entire primitive should be discarded.
Signed-off-by: Zack Rusin <[email protected]>
Reviewed-by: Roland Scheidegger <[email protected]>
Diffstat (limited to 'src/gallium/auxiliary/draw')
-rw-r--r-- | src/gallium/auxiliary/draw/draw_cliptest_tmp.h | 2 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_llvm.c | 3 | ||||
-rw-r--r-- | src/gallium/auxiliary/draw/draw_pipe_clip.c | 15 |
3 files changed, 16 insertions, 4 deletions
diff --git a/src/gallium/auxiliary/draw/draw_cliptest_tmp.h b/src/gallium/auxiliary/draw/draw_cliptest_tmp.h index e4500dbd971..fc548102f2b 100644 --- a/src/gallium/auxiliary/draw/draw_cliptest_tmp.h +++ b/src/gallium/auxiliary/draw/draw_cliptest_tmp.h @@ -140,7 +140,7 @@ static boolean TAG(do_cliptest)( struct pt_post_vs *pvs, clipdist = out->data[cd[0]][i]; else clipdist = out->data[cd[1]][i-4]; - if (clipdist < 0) + if (clipdist < 0 || util_is_inf_or_nan(clipdist)) mask |= 1 << plane_idx; } else { if (dot4(clipvertex, plane[plane_idx]) < 0) diff --git a/src/gallium/auxiliary/draw/draw_llvm.c b/src/gallium/auxiliary/draw/draw_llvm.c index 84e33926a2b..820d6b0013e 100644 --- a/src/gallium/auxiliary/draw/draw_llvm.c +++ b/src/gallium/auxiliary/draw/draw_llvm.c @@ -1261,6 +1261,7 @@ generate_clipmask(struct draw_llvm *llvm, if (clip_user) { LLVMValueRef planes_ptr = draw_jit_context_planes(gallivm, context_ptr); LLVMValueRef indices[3]; + LLVMValueRef is_nan_or_inf; /* userclip planes */ while (ucp_enable) { @@ -1280,6 +1281,8 @@ generate_clipmask(struct draw_llvm *llvm, clipdist = LLVMBuildLoad(builder, outputs[cd[1]][i-4], ""); } test = lp_build_compare(gallivm, f32_type, PIPE_FUNC_GREATER, zero, clipdist); + is_nan_or_inf = lp_build_is_inf_or_nan(gallivm, vs_type, clipdist); + test = LLVMBuildOr(builder, test, is_nan_or_inf, ""); temp = lp_build_const_int_vec(gallivm, i32_type, 1 << plane_idx); test = LLVMBuildAnd(builder, test, temp, ""); mask = LLVMBuildOr(builder, mask, test, ""); diff --git a/src/gallium/auxiliary/draw/draw_pipe_clip.c b/src/gallium/auxiliary/draw/draw_pipe_clip.c index b76e9a501ac..0f90bfdff08 100644 --- a/src/gallium/auxiliary/draw/draw_pipe_clip.c +++ b/src/gallium/auxiliary/draw/draw_pipe_clip.c @@ -104,7 +104,7 @@ static void interp_attr( float dst[4], float t, const float in[4], const float out[4] ) -{ +{ dst[0] = LINTERP( t, out[0], in[0] ); dst[1] = LINTERP( t, out[1], in[1] ); dst[2] = LINTERP( t, out[2], in[2] ); @@ -380,6 +380,9 @@ do_clip_tri( struct draw_stage *stage, dp_prev = getclipdist(clipper, vert_prev, plane_idx); clipmask &= ~(1<<plane_idx); + if (util_is_inf_or_nan(dp_prev)) + return; //discard nan + assert(n < MAX_CLIPPED_VERTICES); if (n >= MAX_CLIPPED_VERTICES) return; @@ -392,6 +395,9 @@ do_clip_tri( struct draw_stage *stage, float dp = getclipdist(clipper, vert, plane_idx); + if (util_is_inf_or_nan(dp)) + return; //discard nan + if (!IS_NEGATIVE(dp_prev)) { assert(outcount < MAX_CLIPPED_VERTICES); if (outcount >= MAX_CLIPPED_VERTICES) @@ -522,6 +528,9 @@ do_clip_line( struct draw_stage *stage, const float dp0 = getclipdist(clipper, v0, plane_idx); const float dp1 = getclipdist(clipper, v1, plane_idx); + if (util_is_inf_or_nan(dp0) || util_is_inf_or_nan(dp1)) + return; //discard nan + if (dp1 < 0.0F) { float t = dp1 / (dp1 - dp0); t1 = MAX2(t1, t); @@ -574,7 +583,7 @@ clip_line( struct draw_stage *stage, { unsigned clipmask = (header->v[0]->clipmask | header->v[1]->clipmask); - + if (clipmask == 0) { /* no clipping needed */ stage->next->line( stage->next, header ); @@ -594,7 +603,7 @@ clip_tri( struct draw_stage *stage, unsigned clipmask = (header->v[0]->clipmask | header->v[1]->clipmask | header->v[2]->clipmask); - + if (clipmask == 0) { /* no clipping needed */ stage->next->tri( stage->next, header ); |